Skip to content

Commit

Permalink
add example source
Browse files Browse the repository at this point in the history
  • Loading branch information
lerandc committed Aug 4, 2021
1 parent 043d143 commit e169404
Show file tree
Hide file tree
Showing 5 changed files with 262 additions and 17 deletions.
6 changes: 5 additions & 1 deletion docs/source/examples.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
Examples
=================================
=================================

.. toctree::
examples/nanoparticle_on_substrate
examples/core_shell_nanoparticle
105 changes: 105 additions & 0 deletions docs/source/examples/core_shell_nanoparticle.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
Core-Shell Mn3O4/Co3O4 Nanoparticle
=========================================

.. code-block::
import numpy as np
import czone as cz
from pymatgen.core import Structure
from cz.volume import Volume, MultiVolume, Plane, snap_plane_near_point
from cz.generator import Generator, AmorphousGenerator
from cz.transform import Rotation, Reflection, Translation, rot_vtv
from cz.scene import Scene
.. code-block::
mn_crystal = Structure.from_file("Mn3O4_mp-18759_conventional_standard.cif")
co_crystal = Structure.from_file("Co3O4_mp-18748_conventional_standard.cif")
.. code-block::
# correct lattice mismatch
co_100 = np.linalg.norm(co_crystal.lattice.matrix @ np.array([1,0,0]))
mn_110 = np.linalg.norm(mn_crystal.lattice.matrix @ np.array([1,1,0]))
mn_crystal.apply_strain([co_100/mn_110-1, co_100/mn_110-1, 0])
.. code-block::
# Make Co3O4 core
co_gen = Generator(structure=co_crystal)
N_uc = 6 # stretch N unit cells from center
co_a = co_crystal.lattice.a
vecs_100 = np.array([[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]])
planes_100 = []
for v in vecs_100:
planes_100.append(snap_plane_near_point(N_uc*co_a*v, co_gen, tuple(v)))
co_core = Volume(alg_objects=planes_100, generator=co_gen)
.. code-block::
# Make unstrained Mn3O4 grain
mn_gen = Generator(structure=mn_crystal)
# rotate 45 degrees and place on top of Co core
r = Rotation(matrix=rot_v(np.array([0,0,1]), np.pi/4))
t = Translation(np.array([0,0,N_uc*co_a]))
mn_gen.transform(r)
mn_gen.transform(t)
.. code-block::
# define top and bottom 100 surfaces
surface_point = np.array([0,0,N_uc*co_a])
mn_c = mn_crystal.lattice.c
mn_bot = snap_plane_near_point(surface_point, mn_gen, (0,0,-1))
mn_top = snap_plane_near_point(surface_point+6*mn_c*np.array([0,0,1]), mn_gen, (0,0,1))
# define 112 facets
side_vs_112 = [(1,1,-2),(1,-1,-2), (-1,1,-2), (-1,-1,-2)]
sides_112 = []
for s in side_vs_112:
tmp_point = np.array([1,1,0]) * np.sign(s) * co_a
tmp_plane = snap_plane_near_point(tmp_point, mn_gen, s)
sides_112.append(tmp_plane)
# define 101 facets
mn_a = mn_crystal.lattice.a
side_vs_101 = [(1,0,1),(0,1,1),(-1,0,1),(0,-1,1)]
sides_101 = []
for s in side_vs_101:
tmp_point = np.array([1,1,0]) * np.sign(s) * 12*mn_a + mn_top.point
tmp_plane = snap_plane_near_point(tmp_point, mn_gen, s)
sides_101.append(tmp_plane)
.. code-block::
# create volume representing grain
mn_vols = [mn_bot, mn_top] + sides_112+sides_101
mn_grain = Volume(alg_objects=mn_vols, generator=mn_gen)
mn_grain.priority=1
.. code-block::
# rotate to make 5 other grains from +z shell grain
mn_grains = [mn_grain]
# get +x, -z, -x
for theta in [np.pi/2, np.pi, -np.pi/2]:
rot = Rotation(rot_v(np.array([0,1,0]),theta))
tmp_grain = mn_grain.from_volume(transformation=[rot])
mn_grains.append(tmp_grain)
# get +-y
for theta in [np.pi/2, -np.pi/2]:
rot = Rotation(rot_v(np.array([1,0,0]),theta))
tmp_grain = mn_grain.from_volume(transformation=[rot])
mn_grains.append(tmp_grain)
.. code-block::
# make final core-shell NP as multivolume and save to file
core_shell_NP = MultiVolume([co_core] + mn_grains)
core_shell_NP.populate_atoms()
core_shell_NP.to_file("core_shell_NP.xyz")
136 changes: 136 additions & 0 deletions docs/source/examples/nanoparticle_on_substrate.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
Defected FCC Nanoparticle on Carbon Substrate
=======================================================

.. code-block::
import czone as cz
import numpy as np
from cz.volume import MultiVolume, Volume, Sphere, Plane, snap_plane_near_point
from cz.generator import Generator, AmorphousGenerator
from cz.transform import Rotation, Reflection, Translation, rot_vtv
from cz.scene import Scene
.. code-block::
c_generator = AmorphousGenerator()
substrate_prism = makeRectPrism(120,120,50)
substrate = Volume(points=substrate_prism, generator=c_generator)
.. code-block::
base_Au_gen = Generator.from_spacegroup(Z=[79],
coords=np.array([[0,0,0]]),
cellDims=4.07825*np.ones(3),
cellAngs=[90,90,90],
sgn=225)
.. code-block::
d_111 = 4.07825/np.sqrt(3)
sphere = Sphere(center=np.array([0,0,0]), radius=32.5)
refl_111_plane = snap_plane_near_point(sphere.center, base_Au_gen, (1,1,1))
b_111 = base_Au_gen.voxel.sbases @ np.array([1,1,1])
b_111 *= d_111 / np.linalg.norm(b_111)
cutoff_111_a = snap_plane_near_point(-3*b_111, base_Au_gen, (1,1,1))
cutoff_111_b = snap_plane_near_point(-8*b_111, base_Au_gen, (1,1,1))
.. code-block::
b_112 = base_Au_gen.voxel.sbases @ np.array([1,1,-2]).T / 3
b_121 = base_Au_gen.voxel.sbases @ np.array([-1,2,-1]).T / 3
refl_111 = Reflection(refl_111_plane)
translate_112 = Translation(shift=b_112)
translate_121 = Translation(shift=b_121)
twin_gen = base_Au_gen.from_generator(transformation=[refl_111])
shift_a_gen = base_Au_gen.from_generator(transformation=[translate_112])
shift_b_gen = base_Au_gen.from_generator(transformation=[translate_121])
.. code-block::
Au_main_grain = Volume(alg_objects=[sphere, refl_111_plane], generator=base_Au_gen)
Au_sf_a_grain = Volume(alg_objects=[sphere, cutoff_111_a], generator=shift_a_gen)
Au_sf_b_grain = Volume(alg_objects=[sphere, cutoff_111_b], generator=shift_b_gen)
Au_twin_grain = Volume(alg_objects=[sphere], generator=twin_gen)
Au_twin_grain.priority = 4
Au_main_grain.priority = 3
Au_sf_a_grain.priority = 2
Au_sf_b_grain.priority = 1
defected_NP = MultiVolume(volumes=[Au_twin_grain, Au_main_grain, Au_sf_a_grain, Au_sf_b_grain])
.. code-block::
# rotate to a random zone axis
zone_axis = np.random.randn(3)
zone_axis /= np.linalg.norm(zone_axis)
rot = Rotation(matrix=rot_vtv(zone_axis, [0,0,1]))
defected_NP.transform(rot)
.. code-block::
moving_plane = Plane(point=[0,0,-0.8*sphere.radius], normal=[0,0,-1]) # not quite the bottom of the NP
target_plane = Plane(point=[0,0,50], normal=[0,0,1]) # the surface of the substrate
alignment_transform = s2s_alignment(moving_plane,
target_plane,
np.array([0,0,0]),
np.array([60,60,0]))
defected_NP.transform(alignment_transform)
.. code-block::
# remove substrate where NP exists
defected_NP.priority = 0
substrate.priority = 1
defected_NP_scene = cz.scene.Scene(bounds=np.array([[0,0,0],[120,120,120]]),
objects=[defected_NP, substrate])
defected_NP_scene.populate()
defected_NP_scene.to_file("defected_NP.xyz")
.. code-block::
sphere = Sphere(center=np.array([0,0,0]), radius=radius)
vol = Volume(alg_objects=[small_sphere])
sf_object_prefab = fccMixedTwinSF(generator=base_Au_gen, volume=vol, ratio=0.75, N=3)
current_vol = sf_object_prefab.build_object()
# apply random rotation
zone_axis = np.random.randn(3)
zone_axis /= np.linalg.norm(zone_axis)
rot = Rotation(matrix=rot_vtv(zone_axis, [0,0,1]))
current_vol.transform(rot)
# put on substrate and apply random shift about center of FOV
moving_plane = Plane(point=[0,0,-0.8*small_sphere.radius], normal=[0,0,-1]) # not quite the bottom of the NP
target_plane = Plane(point=[0,0,50], normal=[0,0,1]) # the surface of the substrate
final_center = np.array([60,60,0]) + 10*np.random.randn(3)*np.array([1,1,0])
alignment_transform = s2s_alignment(moving_plane,
target_plane,
small_sphere.center,
final_center)
current_vol.transform(alignment_transform)
scene = cz.scene.Scene(bounds=np.array([[0,0,0],[120,120,125]]), objects=[current_vol])
scene.populate()
scene.to_file("particle.xyz")
scene.add_object(substrate)
scene.populate()
scene.to_file("particle_on_substrate.xyz")
17 changes: 16 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,26 @@ Its interface is flexible and allows for easy development of progammatic constru
that are suitable for applications in materials science, and much of the bookkeeping
typically required when making complex atomic objects is abstracted from the user.

The basis design principle of Construction Zone is to a sculpting approach to creating atomic objects and scenes.
Construction Zone implements several core classes which help accomplish this task.
Generator objects are additive elements that provide the sculpting blocks--
they are classes which fill a given space with atoms, whether that is as a crystalline
lattice or an amorphous collection of points. Volume objects are subtractive elements
that define the boundaries of an nanoscale structure. Together, Volumes and Generators
can be joined together and treated as semantic objects, like a nanoparticle or a substrate.
Multiple objects in space can interact with eachother in Scenes, which take care
of conflict resolutions like object intersetion and atom overlapping.
Volumes and Generators can also be transformed with Transformation objects, which
can apply arbitrary transformations to the structures at hand, like symmetry operations
or strain fields.

If you use Construction Zone in your own work, we kindly ask that you cite the following:
Zenodo DOI incoming soon!

.. toctree::
:maxdepth: 4
:caption: Contents

intro
installation
examples
modules
Expand Down
15 changes: 0 additions & 15 deletions docs/source/intro.rst

This file was deleted.

0 comments on commit e169404

Please sign in to comment.