1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
24 from math
import pi
, cos
, sin
, tan
, sqrt
25 from mathutils
import Vector
, Matrix
28 # -----------------------------------------------------------------------------
29 # Atom, stick and element data
32 # This is a list that contains some data of all possible elements. The structure
35 # 1, "Hydrogen", "H", [0.0,0.0,1.0], 0.32, 0.32, 0.32 , -1 , 1.54 means
37 # No., name, short name, color, radius (used), radius (covalent), radius (atomic),
39 # charge state 1, radius (ionic) 1, charge state 2, radius (ionic) 2, ... all
40 # charge states for any atom are listed, if existing.
41 # The list is fixed and cannot be changed ... (see below)
43 ATOM_CLUSTER_ELEMENTS_DEFAULT
= (
44 ( 1, "Hydrogen", "H", ( 1.0, 1.0, 1.0, 1.0), 0.32, 0.32, 0.79 , -1 , 1.54 ),
45 ( 2, "Helium", "He", ( 0.85, 1.0, 1.0, 1.0), 0.93, 0.93, 0.49 ),
46 ( 3, "Lithium", "Li", ( 0.8, 0.50, 1.0, 1.0), 1.23, 1.23, 2.05 , 1 , 0.68 ),
47 ( 4, "Beryllium", "Be", ( 0.76, 1.0, 0.0, 1.0), 0.90, 0.90, 1.40 , 1 , 0.44 , 2 , 0.35 ),
48 ( 5, "Boron", "B", ( 1.0, 0.70, 0.70, 1.0), 0.82, 0.82, 1.17 , 1 , 0.35 , 3 , 0.23 ),
49 ( 6, "Carbon", "C", ( 0.56, 0.56, 0.56, 1.0), 0.77, 0.77, 0.91 , -4 , 2.60 , 4 , 0.16 ),
50 ( 7, "Nitrogen", "N", ( 0.18, 0.31, 0.97, 1.0), 0.75, 0.75, 0.75 , -3 , 1.71 , 1 , 0.25 , 3 , 0.16 , 5 , 0.13 ),
51 ( 8, "Oxygen", "O", ( 1.0, 0.05, 0.05, 1.0), 0.73, 0.73, 0.65 , -2 , 1.32 , -1 , 1.76 , 1 , 0.22 , 6 , 0.09 ),
52 ( 9, "Fluorine", "F", ( 0.56, 0.87, 0.31, 1.0), 0.72, 0.72, 0.57 , -1 , 1.33 , 7 , 0.08 ),
53 (10, "Neon", "Ne", ( 0.70, 0.89, 0.96, 1.0), 0.71, 0.71, 0.51 , 1 , 1.12 ),
54 (11, "Sodium", "Na", ( 0.67, 0.36, 0.94, 1.0), 1.54, 1.54, 2.23 , 1 , 0.97 ),
55 (12, "Magnesium", "Mg", ( 0.54, 1.0, 0.0, 1.0), 1.36, 1.36, 1.72 , 1 , 0.82 , 2 , 0.66 ),
56 (13, "Aluminium", "Al", ( 0.74, 0.65, 0.65, 1.0), 1.18, 1.18, 1.82 , 3 , 0.51 ),
57 (14, "Silicon", "Si", ( 0.94, 0.78, 0.62, 1.0), 1.11, 1.11, 1.46 , -4 , 2.71 , -1 , 3.84 , 1 , 0.65 , 4 , 0.42 ),
58 (15, "Phosphorus", "P", ( 1.0, 0.50, 0.0, 1.0), 1.06, 1.06, 1.23 , -3 , 2.12 , 3 , 0.44 , 5 , 0.35 ),
59 (16, "Sulfur", "S", ( 1.0, 1.0, 0.18, 1.0), 1.02, 1.02, 1.09 , -2 , 1.84 , 2 , 2.19 , 4 , 0.37 , 6 , 0.30 ),
60 (17, "Chlorine", "Cl", ( 0.12, 0.94, 0.12, 1.0), 0.99, 0.99, 0.97 , -1 , 1.81 , 5 , 0.34 , 7 , 0.27 ),
61 (18, "Argon", "Ar", ( 0.50, 0.81, 0.89, 1.0), 0.98, 0.98, 0.88 , 1 , 1.54 ),
62 (19, "Potassium", "K", ( 0.56, 0.25, 0.83, 1.0), 2.03, 2.03, 2.77 , 1 , 0.81 ),
63 (20, "Calcium", "Ca", ( 0.23, 1.0, 0.0, 1.0), 1.74, 1.74, 2.23 , 1 , 1.18 , 2 , 0.99 ),
64 (21, "Scandium", "Sc", ( 0.90, 0.90, 0.90, 1.0), 1.44, 1.44, 2.09 , 3 , 0.73 ),
65 (22, "Titanium", "Ti", ( 0.74, 0.76, 0.78, 1.0), 1.32, 1.32, 2.00 , 1 , 0.96 , 2 , 0.94 , 3 , 0.76 , 4 , 0.68 ),
66 (23, "Vanadium", "V", ( 0.65, 0.65, 0.67, 1.0), 1.22, 1.22, 1.92 , 2 , 0.88 , 3 , 0.74 , 4 , 0.63 , 5 , 0.59 ),
67 (24, "Chromium", "Cr", ( 0.54, 0.6, 0.78, 1.0), 1.18, 1.18, 1.85 , 1 , 0.81 , 2 , 0.89 , 3 , 0.63 , 6 , 0.52 ),
68 (25, "Manganese", "Mn", ( 0.61, 0.47, 0.78, 1.0), 1.17, 1.17, 1.79 , 2 , 0.80 , 3 , 0.66 , 4 , 0.60 , 7 , 0.46 ),
69 (26, "Iron", "Fe", ( 0.87, 0.4, 0.2, 1.0), 1.17, 1.17, 1.72 , 2 , 0.74 , 3 , 0.64 ),
70 (27, "Cobalt", "Co", ( 0.94, 0.56, 0.62, 1.0), 1.16, 1.16, 1.67 , 2 , 0.72 , 3 , 0.63 ),
71 (28, "Nickel", "Ni", ( 0.31, 0.81, 0.31, 1.0), 1.15, 1.15, 1.62 , 2 , 0.69 ),
72 (29, "Copper", "Cu", ( 0.78, 0.50, 0.2, 1.0), 1.17, 1.17, 1.57 , 1 , 0.96 , 2 , 0.72 ),
73 (30, "Zinc", "Zn", ( 0.49, 0.50, 0.69, 1.0), 1.25, 1.25, 1.53 , 1 , 0.88 , 2 , 0.74 ),
74 (31, "Gallium", "Ga", ( 0.76, 0.56, 0.56, 1.0), 1.26, 1.26, 1.81 , 1 , 0.81 , 3 , 0.62 ),
75 (32, "Germanium", "Ge", ( 0.4, 0.56, 0.56, 1.0), 1.22, 1.22, 1.52 , -4 , 2.72 , 2 , 0.73 , 4 , 0.53 ),
76 (33, "Arsenic", "As", ( 0.74, 0.50, 0.89, 1.0), 1.20, 1.20, 1.33 , -3 , 2.22 , 3 , 0.58 , 5 , 0.46 ),
77 (34, "Selenium", "Se", ( 1.0, 0.63, 0.0, 1.0), 1.16, 1.16, 1.22 , -2 , 1.91 , -1 , 2.32 , 1 , 0.66 , 4 , 0.50 , 6 , 0.42 ),
78 (35, "Bromine", "Br", ( 0.65, 0.16, 0.16, 1.0), 1.14, 1.14, 1.12 , -1 , 1.96 , 5 , 0.47 , 7 , 0.39 ),
79 (36, "Krypton", "Kr", ( 0.36, 0.72, 0.81, 1.0), 1.31, 1.31, 1.24 ),
80 (37, "Rubidium", "Rb", ( 0.43, 0.18, 0.69, 1.0), 2.16, 2.16, 2.98 , 1 , 1.47 ),
81 (38, "Strontium", "Sr", ( 0.0, 1.0, 0.0, 1.0), 1.91, 1.91, 2.45 , 2 , 1.12 ),
82 (39, "Yttrium", "Y", ( 0.58, 1.0, 1.0, 1.0), 1.62, 1.62, 2.27 , 3 , 0.89 ),
83 (40, "Zirconium", "Zr", ( 0.58, 0.87, 0.87, 1.0), 1.45, 1.45, 2.16 , 1 , 1.09 , 4 , 0.79 ),
84 (41, "Niobium", "Nb", ( 0.45, 0.76, 0.78, 1.0), 1.34, 1.34, 2.08 , 1 , 1.00 , 4 , 0.74 , 5 , 0.69 ),
85 (42, "Molybdenum", "Mo", ( 0.32, 0.70, 0.70, 1.0), 1.30, 1.30, 2.01 , 1 , 0.93 , 4 , 0.70 , 6 , 0.62 ),
86 (43, "Technetium", "Tc", ( 0.23, 0.61, 0.61, 1.0), 1.27, 1.27, 1.95 , 7 , 0.97 ),
87 (44, "Ruthenium", "Ru", ( 0.14, 0.56, 0.56, 1.0), 1.25, 1.25, 1.89 , 4 , 0.67 ),
88 (45, "Rhodium", "Rh", ( 0.03, 0.49, 0.54, 1.0), 1.25, 1.25, 1.83 , 3 , 0.68 ),
89 (46, "Palladium", "Pd", ( 0.0, 0.41, 0.52, 1.0), 1.28, 1.28, 1.79 , 2 , 0.80 , 4 , 0.65 ),
90 (47, "Silver", "Ag", ( 0.75, 0.75, 0.75, 1.0), 1.34, 1.34, 1.75 , 1 , 1.26 , 2 , 0.89 ),
91 (48, "Cadmium", "Cd", ( 1.0, 0.85, 0.56, 1.0), 1.48, 1.48, 1.71 , 1 , 1.14 , 2 , 0.97 ),
92 (49, "Indium", "In", ( 0.65, 0.45, 0.45, 1.0), 1.44, 1.44, 2.00 , 3 , 0.81 ),
93 (50, "Tin", "Sn", ( 0.4, 0.50, 0.50, 1.0), 1.41, 1.41, 1.72 , -4 , 2.94 , -1 , 3.70 , 2 , 0.93 , 4 , 0.71 ),
94 (51, "Antimony", "Sb", ( 0.61, 0.38, 0.70, 1.0), 1.40, 1.40, 1.53 , -3 , 2.45 , 3 , 0.76 , 5 , 0.62 ),
95 (52, "Tellurium", "Te", ( 0.83, 0.47, 0.0, 1.0), 1.36, 1.36, 1.42 , -2 , 2.11 , -1 , 2.50 , 1 , 0.82 , 4 , 0.70 , 6 , 0.56 ),
96 (53, "Iodine", "I", ( 0.58, 0.0, 0.58, 1.0), 1.33, 1.33, 1.32 , -1 , 2.20 , 5 , 0.62 , 7 , 0.50 ),
97 (54, "Xenon", "Xe", ( 0.25, 0.61, 0.69, 1.0), 1.31, 1.31, 1.24 ),
98 (55, "Caesium", "Cs", ( 0.34, 0.09, 0.56, 1.0), 2.35, 2.35, 3.35 , 1 , 1.67 ),
99 (56, "Barium", "Ba", ( 0.0, 0.78, 0.0, 1.0), 1.98, 1.98, 2.78 , 1 , 1.53 , 2 , 1.34 ),
100 (57, "Lanthanum", "La", ( 0.43, 0.83, 1.0, 1.0), 1.69, 1.69, 2.74 , 1 , 1.39 , 3 , 1.06 ),
101 (58, "Cerium", "Ce", ( 1.0, 1.0, 0.78, 1.0), 1.65, 1.65, 2.70 , 1 , 1.27 , 3 , 1.03 , 4 , 0.92 ),
102 (59, "Praseodymium", "Pr", ( 0.85, 1.0, 0.78, 1.0), 1.65, 1.65, 2.67 , 3 , 1.01 , 4 , 0.90 ),
103 (60, "Neodymium", "Nd", ( 0.78, 1.0, 0.78, 1.0), 1.64, 1.64, 2.64 , 3 , 0.99 ),
104 (61, "Promethium", "Pm", ( 0.63, 1.0, 0.78, 1.0), 1.63, 1.63, 2.62 , 3 , 0.97 ),
105 (62, "Samarium", "Sm", ( 0.56, 1.0, 0.78, 1.0), 1.62, 1.62, 2.59 , 3 , 0.96 ),
106 (63, "Europium", "Eu", ( 0.38, 1.0, 0.78, 1.0), 1.85, 1.85, 2.56 , 2 , 1.09 , 3 , 0.95 ),
107 (64, "Gadolinium", "Gd", ( 0.27, 1.0, 0.78, 1.0), 1.61, 1.61, 2.54 , 3 , 0.93 ),
108 (65, "Terbium", "Tb", ( 0.18, 1.0, 0.78, 1.0), 1.59, 1.59, 2.51 , 3 , 0.92 , 4 , 0.84 ),
109 (66, "Dysprosium", "Dy", ( 0.12, 1.0, 0.78, 1.0), 1.59, 1.59, 2.49 , 3 , 0.90 ),
110 (67, "Holmium", "Ho", ( 0.0, 1.0, 0.61, 1.0), 1.58, 1.58, 2.47 , 3 , 0.89 ),
111 (68, "Erbium", "Er", ( 0.0, 0.90, 0.45, 1.0), 1.57, 1.57, 2.45 , 3 , 0.88 ),
112 (69, "Thulium", "Tm", ( 0.0, 0.83, 0.32, 1.0), 1.56, 1.56, 2.42 , 3 , 0.87 ),
113 (70, "Ytterbium", "Yb", ( 0.0, 0.74, 0.21, 1.0), 1.74, 1.74, 2.40 , 2 , 0.93 , 3 , 0.85 ),
114 (71, "Lutetium", "Lu", ( 0.0, 0.67, 0.14, 1.0), 1.56, 1.56, 2.25 , 3 , 0.85 ),
115 (72, "Hafnium", "Hf", ( 0.30, 0.76, 1.0, 1.0), 1.44, 1.44, 2.16 , 4 , 0.78 ),
116 (73, "Tantalum", "Ta", ( 0.30, 0.65, 1.0, 1.0), 1.34, 1.34, 2.09 , 5 , 0.68 ),
117 (74, "Tungsten", "W", ( 0.12, 0.58, 0.83, 1.0), 1.30, 1.30, 2.02 , 4 , 0.70 , 6 , 0.62 ),
118 (75, "Rhenium", "Re", ( 0.14, 0.49, 0.67, 1.0), 1.28, 1.28, 1.97 , 4 , 0.72 , 7 , 0.56 ),
119 (76, "Osmium", "Os", ( 0.14, 0.4, 0.58, 1.0), 1.26, 1.26, 1.92 , 4 , 0.88 , 6 , 0.69 ),
120 (77, "Iridium", "Ir", ( 0.09, 0.32, 0.52, 1.0), 1.27, 1.27, 1.87 , 4 , 0.68 ),
121 (78, "Platinum", "Pt", ( 0.81, 0.81, 0.87, 1.0), 1.30, 1.30, 1.83 , 2 , 0.80 , 4 , 0.65 ),
122 (79, "Gold", "Au", ( 1.0, 0.81, 0.13, 1.0), 1.34, 1.34, 1.79 , 1 , 1.37 , 3 , 0.85 ),
123 (80, "Mercury", "Hg", ( 0.72, 0.72, 0.81, 1.0), 1.49, 1.49, 1.76 , 1 , 1.27 , 2 , 1.10 ),
124 (81, "Thallium", "Tl", ( 0.65, 0.32, 0.30, 1.0), 1.48, 1.48, 2.08 , 1 , 1.47 , 3 , 0.95 ),
125 (82, "Lead", "Pb", ( 0.34, 0.34, 0.38, 1.0), 1.47, 1.47, 1.81 , 2 , 1.20 , 4 , 0.84 ),
126 (83, "Bismuth", "Bi", ( 0.61, 0.30, 0.70, 1.0), 1.46, 1.46, 1.63 , 1 , 0.98 , 3 , 0.96 , 5 , 0.74 ),
127 (84, "Polonium", "Po", ( 0.67, 0.36, 0.0, 1.0), 1.46, 1.46, 1.53 , 6 , 0.67 ),
128 (85, "Astatine", "At", ( 0.45, 0.30, 0.27, 1.0), 1.45, 1.45, 1.43 , -3 , 2.22 , 3 , 0.85 , 5 , 0.46 ),
129 (86, "Radon", "Rn", ( 0.25, 0.50, 0.58, 1.0), 1.00, 1.00, 1.34 ),
130 (87, "Francium", "Fr", ( 0.25, 0.0, 0.4, 1.0), 1.00, 1.00, 1.00 , 1 , 1.80 ),
131 (88, "Radium", "Ra", ( 0.0, 0.49, 0.0, 1.0), 1.00, 1.00, 1.00 , 2 , 1.43 ),
132 (89, "Actinium", "Ac", ( 0.43, 0.67, 0.98, 1.0), 1.00, 1.00, 1.00 , 3 , 1.18 ),
133 (90, "Thorium", "Th", ( 0.0, 0.72, 1.0, 1.0), 1.65, 1.65, 1.00 , 4 , 1.02 ),
134 (91, "Protactinium", "Pa", ( 0.0, 0.63, 1.0, 1.0), 1.00, 1.00, 1.00 , 3 , 1.13 , 4 , 0.98 , 5 , 0.89 ),
135 (92, "Uranium", "U", ( 0.0, 0.56, 1.0, 1.0), 1.42, 1.42, 1.00 , 4 , 0.97 , 6 , 0.80 ),
136 (93, "Neptunium", "Np", ( 0.0, 0.50, 1.0, 1.0), 1.00, 1.00, 1.00 , 3 , 1.10 , 4 , 0.95 , 7 , 0.71 ),
137 (94, "Plutonium", "Pu", ( 0.0, 0.41, 1.0, 1.0), 1.00, 1.00, 1.00 , 3 , 1.08 , 4 , 0.93 ),
138 (95, "Americium", "Am", ( 0.32, 0.36, 0.94, 1.0), 1.00, 1.00, 1.00 , 3 , 1.07 , 4 , 0.92 ),
139 (96, "Curium", "Cm", ( 0.47, 0.36, 0.89, 1.0), 1.00, 1.00, 1.00 ),
140 (97, "Berkelium", "Bk", ( 0.54, 0.30, 0.89, 1.0), 1.00, 1.00, 1.00 ),
141 (98, "Californium", "Cf", ( 0.63, 0.21, 0.83, 1.0), 1.00, 1.00, 1.00 ),
142 (99, "Einsteinium", "Es", ( 0.70, 0.12, 0.83, 1.0), 1.00, 1.00, 1.00 ),
143 (100, "Fermium", "Fm", ( 0.70, 0.12, 0.72, 1.0), 1.00, 1.00, 1.00 ),
144 (101, "Mendelevium", "Md", ( 0.70, 0.05, 0.65, 1.0), 1.00, 1.00, 1.00 ),
145 (102, "Nobelium", "No", ( 0.74, 0.05, 0.52, 1.0), 1.00, 1.00, 1.00 ),
146 (103, "Lawrencium", "Lr", ( 0.78, 0.0, 0.4, 1.0), 1.00, 1.00, 1.00 ),
147 (104, "Vacancy", "Vac", ( 0.5, 0.5, 0.5, 1.0), 1.00, 1.00, 1.00),
148 (105, "Default", "Default", ( 1.0, 1.0, 1.0, 1.0), 1.00, 1.00, 1.00),
149 (106, "Stick", "Stick", ( 0.5, 0.5, 0.5, 1.0), 1.00, 1.00, 1.00),
152 # This list here contains all data of the elements and will be used during
153 # runtime. It is a list of classes.
154 # During executing Atomic Blender, the list will be initialized with the fixed
155 # data from above via the class structure below (CLASS_atom_pdb_Elements). We
156 # have then one fixed list (above), which will never be changed, and a list of
157 # classes with same data. The latter can be modified via loading a separate
159 ATOM_CLUSTER_ELEMENTS
= []
160 ATOM_CLUSTER_ALL_ATOMS
= []
162 # This is the class, which stores the properties for one element.
163 class CLASS_atom_cluster_Elements(object):
164 __slots__
= ('number', 'name', 'short_name', 'color', 'radii', 'radii_ionic')
165 def __init__(self
, number
, name
, short_name
, color
, radii
, radii_ionic
):
168 self
.short_name
= short_name
171 self
.radii_ionic
= radii_ionic
173 # This is the class, which stores the properties of one atom.
174 class CLASS_atom_cluster_atom(object):
175 __slots__
= ('location')
176 def __init__(self
, location
):
177 self
.location
= location
179 # -----------------------------------------------------------------------------
182 def DEF_atom_read_atom_data():
184 del ATOM_CLUSTER_ELEMENTS
[:]
186 for item
in ATOM_CLUSTER_ELEMENTS_DEFAULT
:
188 # All three radii into a list
189 radii
= [item
[4],item
[5],item
[6]]
190 # The handling of the ionic radii will be done later. So far, it is an
194 li
= CLASS_atom_cluster_Elements(item
[0],item
[1],item
[2],item
[3],
196 ATOM_CLUSTER_ELEMENTS
.append(li
)
199 # -----------------------------------------------------------------------------
200 # Routines for shapes
202 def vec_in_sphere(atom_pos
,size
, skin
):
207 if atom_pos
.length
> size
/2.0:
210 if atom_pos
.length
< (size
/2.0)*(1-skin
):
213 return (regular
, inner
)
216 def vec_in_parabole(atom_pos
, height
, diameter
):
223 pz
= atom_pos
[2] + height
/2.0
225 a
= diameter
/ sqrt(4 * height
)
229 return (False, False)
230 if px
== 0.0 and py
== 0.0:
238 y
= pz
* py
* a
* a
/ (px
*px
+ py
*py
)
240 z
= (x
*x
+ y
*y
) / (a
* a
)
242 if( atom_pos
.length
> sqrt(x
*x
+y
*y
+z
*z
) ):
245 return (regular
, inner
)
248 def vec_in_pyramide_square(atom_pos
, size
, skin
):
251 Please, if possible leave all this! The code documents the
252 mathemetical way of cutting a pyramide with square base.
254 P1 = Vector((-size/2, 0.0, -size/4))
255 P2 = Vector((0.0, -size/2, -size/4))
256 P4 = Vector((size/2, 0.0, -size/4))
257 P5 = Vector((0.0, size/2, -size/4))
258 P6 = Vector((0.0, 0.0, size/4))
291 # A much faster way for calculation:
294 n1
= Vector((-1/4, -1/4, 1/4)) * size2
296 n2
= Vector(( 1/4, 1/4, 1/4)) * size2
298 n3
= Vector((-1/4, 1/4, 1/4)) * size2
300 n4
= Vector(( 1/4, -1/4, 1/4)) * size2
302 n5
= Vector(( 0.0, 0.0, -1/2)) * size2
305 distance_plane_1
= abs((n1
@ atom_pos
- g1
)/n1
.length
)
306 on_plane_1
= (atom_pos
- n1
* (distance_plane_1
/n1
.length
)).length
307 distance_plane_2
= abs((n2
@ atom_pos
- g2
)/n2
.length
)
308 on_plane_2
= (atom_pos
- n2
* (distance_plane_2
/n2
.length
)).length
309 distance_plane_3
= abs((n3
@ atom_pos
- g3
)/n3
.length
)
310 on_plane_3
= (atom_pos
- n3
* (distance_plane_3
/n3
.length
)).length
311 distance_plane_4
= abs((n4
@ atom_pos
- g4
)/n4
.length
)
312 on_plane_4
= (atom_pos
- n4
* (distance_plane_4
/n4
.length
)).length
313 distance_plane_5
= abs((n5
@ atom_pos
- g5
)/n5
.length
)
314 on_plane_5
= (atom_pos
- n5
* (distance_plane_5
/n5
.length
)).length
318 if(atom_pos
.length
> on_plane_1
):
320 if(atom_pos
.length
> on_plane_2
):
322 if(atom_pos
.length
> on_plane_3
):
324 if(atom_pos
.length
> on_plane_4
):
326 if(atom_pos
.length
> on_plane_5
):
330 return (regular
, inner
)
332 size
= size
* (1.0 - skin
)
336 n1
= Vector((-1/4, -1/4, 1/4)) * size2
338 n2
= Vector(( 1/4, 1/4, 1/4)) * size2
340 n3
= Vector((-1/4, 1/4, 1/4)) * size2
342 n4
= Vector(( 1/4, -1/4, 1/4)) * size2
344 n5
= Vector(( 0.0, 0.0, -1/2)) * size2
347 distance_plane_1
= abs((n1
@ atom_pos
- g1
)/n1
.length
)
348 on_plane_1
= (atom_pos
- n1
* (distance_plane_1
/n1
.length
)).length
349 distance_plane_2
= abs((n2
@ atom_pos
- g2
)/n2
.length
)
350 on_plane_2
= (atom_pos
- n2
* (distance_plane_2
/n2
.length
)).length
351 distance_plane_3
= abs((n3
@ atom_pos
- g3
)/n3
.length
)
352 on_plane_3
= (atom_pos
- n3
* (distance_plane_3
/n3
.length
)).length
353 distance_plane_4
= abs((n4
@ atom_pos
- g4
)/n4
.length
)
354 on_plane_4
= (atom_pos
- n4
* (distance_plane_4
/n4
.length
)).length
355 distance_plane_5
= abs((n5
@ atom_pos
- g5
)/n5
.length
)
356 on_plane_5
= (atom_pos
- n5
* (distance_plane_5
/n5
.length
)).length
359 if(atom_pos
.length
> on_plane_1
):
361 if(atom_pos
.length
> on_plane_2
):
363 if(atom_pos
.length
> on_plane_3
):
365 if(atom_pos
.length
> on_plane_4
):
367 if(atom_pos
.length
> on_plane_5
):
370 return (regular
, inner
)
373 def vec_in_pyramide_hex_abc(atom_pos
, size
, skin
):
376 #c = size/2.0*cos((30/360)*2.0*pi)
377 c
= size
* 0.4330127020
378 #s = size/2.0*sin((30/360)*2.0*pi)
380 #h = 2.0 * (sqrt(6.0)/3.0) * c
384 Please, if possible leave all this! The code documents the
385 mathemetical way of cutting a tetraeder.
387 P1 = Vector((0.0, a, 0.0))
388 P2 = Vector(( -c, -s, 0.0))
389 P3 = Vector(( c, -s, 0.0))
390 P4 = Vector((0.0, 0.0, h))
391 C = (P1+P2+P3+P4)/4.0
422 n1
= Vector(( -h
*(a
+s
), c
*h
, c
*a
))
423 g1
= -1/2*c
*(a
*h
+s
*h
)
424 n2
= Vector(( 0, -2*c
*h
, 2*c
*s
))
425 g2
= -1/2*c
*(a
*h
+s
*h
)
426 n3
= Vector(( h
*(a
+s
), c
*h
, a
*c
))
427 g3
= -1/2*c
*(a
*h
+s
*h
)
428 n4
= Vector(( 0, 0, -2*c
*(s
+a
) ))
431 distance_plane_1
= abs((n1
@ atom_pos
- g1
)/n1
.length
)
432 on_plane_1
= (atom_pos
- n1
* (distance_plane_1
/n1
.length
)).length
433 distance_plane_2
= abs((n2
@ atom_pos
- g2
)/n2
.length
)
434 on_plane_2
= (atom_pos
- n2
* (distance_plane_2
/n2
.length
)).length
435 distance_plane_3
= abs((n3
@ atom_pos
- g3
)/n3
.length
)
436 on_plane_3
= (atom_pos
- n3
* (distance_plane_3
/n3
.length
)).length
437 distance_plane_4
= abs((n4
@ atom_pos
- g4
)/n4
.length
)
438 on_plane_4
= (atom_pos
- n4
* (distance_plane_4
/n4
.length
)).length
442 if(atom_pos
.length
> on_plane_1
):
444 if(atom_pos
.length
> on_plane_2
):
446 if(atom_pos
.length
> on_plane_3
):
448 if(atom_pos
.length
> on_plane_4
):
452 return (regular
, inner
)
454 size
= size
* (1.0 - skin
)
457 #c = size/2.0*cos((30/360)*2.0*pi)
458 c
= size
* 0.4330127020
459 #s = size/2.0*sin((30/360)*2.0*pi)
461 #h = 2.0 * (sqrt(6.0)/3.0) * c
464 n1
= Vector(( -h
*(a
+s
), c
*h
, c
*a
))
465 g1
= -1/2*c
*(a
*h
+s
*h
)
466 n2
= Vector(( 0, -2*c
*h
, 2*c
*s
))
467 g2
= -1/2*c
*(a
*h
+s
*h
)
468 n3
= Vector(( h
*(a
+s
), c
*h
, a
*c
))
469 g3
= -1/2*c
*(a
*h
+s
*h
)
470 n4
= Vector(( 0, 0, -2*c
*(s
+a
) ))
473 distance_plane_1
= abs((n1
@ atom_pos
- g1
)/n1
.length
)
474 on_plane_1
= (atom_pos
- n1
* (distance_plane_1
/n1
.length
)).length
475 distance_plane_2
= abs((n2
@ atom_pos
- g2
)/n2
.length
)
476 on_plane_2
= (atom_pos
- n2
* (distance_plane_2
/n2
.length
)).length
477 distance_plane_3
= abs((n3
@ atom_pos
- g3
)/n3
.length
)
478 on_plane_3
= (atom_pos
- n3
* (distance_plane_3
/n3
.length
)).length
479 distance_plane_4
= abs((n4
@ atom_pos
- g4
)/n4
.length
)
480 on_plane_4
= (atom_pos
- n4
* (distance_plane_4
/n4
.length
)).length
483 if(atom_pos
.length
> on_plane_1
):
485 if(atom_pos
.length
> on_plane_2
):
487 if(atom_pos
.length
> on_plane_3
):
489 if(atom_pos
.length
> on_plane_4
):
492 return (regular
, inner
)
496 def vec_in_octahedron(atom_pos
,size
, skin
):
502 Please, if possible leave all this! The code documents the
503 mathemetical way of cutting an octahedron.
505 P1 = Vector((-size/2, 0.0, 0.0))
506 P2 = Vector((0.0, -size/2, 0.0))
507 P3 = Vector((0.0, 0.0, -size/2))
508 P4 = Vector((size/2, 0.0, 0.0))
509 P5 = Vector((0.0, size/2, 0.0))
510 P6 = Vector((0.0, 0.0, size/2))
561 # A much faster way for calculation:
564 n1
= Vector((-1/4, -1/4, -1/4)) * size2
566 n2
= Vector((-1/4, 1/4, -1/4)) * size2
568 n3
= Vector((-1/4, -1/4, 1/4)) * size2
570 n4
= Vector(( 1/4, -1/4, 1/4)) * size2
572 n5
= Vector(( 1/4, -1/4, -1/4)) * size2
574 n6
= Vector(( 1/4, 1/4, 1/4)) * size2
576 n7
= Vector(( 1/4, 1/4, -1/4)) * size2
578 n8
= Vector((-1/4, 1/4, 1/4)) * size2
581 distance_plane_1
= abs((n1
@ atom_pos
- g1
)/n1
.length
)
582 on_plane_1
= (atom_pos
- n1
* (distance_plane_1
/n1
.length
)).length
583 distance_plane_2
= abs((n2
@ atom_pos
- g2
)/n2
.length
)
584 on_plane_2
= (atom_pos
- n2
* (distance_plane_2
/n2
.length
)).length
585 distance_plane_3
= abs((n3
@ atom_pos
- g3
)/n3
.length
)
586 on_plane_3
= (atom_pos
- n3
* (distance_plane_3
/n3
.length
)).length
587 distance_plane_4
= abs((n4
@ atom_pos
- g4
)/n4
.length
)
588 on_plane_4
= (atom_pos
- n4
* (distance_plane_4
/n4
.length
)).length
589 distance_plane_5
= abs((n5
@ atom_pos
- g5
)/n5
.length
)
590 on_plane_5
= (atom_pos
- n5
* (distance_plane_5
/n5
.length
)).length
591 distance_plane_6
= abs((n6
@ atom_pos
- g6
)/n6
.length
)
592 on_plane_6
= (atom_pos
- n6
* (distance_plane_6
/n6
.length
)).length
593 distance_plane_7
= abs((n7
@ atom_pos
- g7
)/n7
.length
)
594 on_plane_7
= (atom_pos
- n7
* (distance_plane_7
/n7
.length
)).length
595 distance_plane_8
= abs((n8
@ atom_pos
- g8
)/n8
.length
)
596 on_plane_8
= (atom_pos
- n8
* (distance_plane_8
/n8
.length
)).length
598 if(atom_pos
.length
> on_plane_1
):
600 if(atom_pos
.length
> on_plane_2
):
602 if(atom_pos
.length
> on_plane_3
):
604 if(atom_pos
.length
> on_plane_4
):
606 if(atom_pos
.length
> on_plane_5
):
608 if(atom_pos
.length
> on_plane_6
):
610 if(atom_pos
.length
> on_plane_7
):
612 if(atom_pos
.length
> on_plane_8
):
616 return (regular
, inner
)
618 size
= size
* (1.0 - skin
)
622 n1
= Vector((-1/4, -1/4, -1/4)) * size2
624 n2
= Vector((-1/4, 1/4, -1/4)) * size2
626 n3
= Vector((-1/4, -1/4, 1/4)) * size2
628 n4
= Vector(( 1/4, -1/4, 1/4)) * size2
630 n5
= Vector(( 1/4, -1/4, -1/4)) * size2
632 n6
= Vector(( 1/4, 1/4, 1/4)) * size2
634 n7
= Vector(( 1/4, 1/4, -1/4)) * size2
636 n8
= Vector((-1/4, 1/4, 1/4)) * size2
639 distance_plane_1
= abs((n1
@ atom_pos
- g1
)/n1
.length
)
640 on_plane_1
= (atom_pos
- n1
* (distance_plane_1
/n1
.length
)).length
641 distance_plane_2
= abs((n2
@ atom_pos
- g2
)/n2
.length
)
642 on_plane_2
= (atom_pos
- n2
* (distance_plane_2
/n2
.length
)).length
643 distance_plane_3
= abs((n3
@ atom_pos
- g3
)/n3
.length
)
644 on_plane_3
= (atom_pos
- n3
* (distance_plane_3
/n3
.length
)).length
645 distance_plane_4
= abs((n4
@ atom_pos
- g4
)/n4
.length
)
646 on_plane_4
= (atom_pos
- n4
* (distance_plane_4
/n4
.length
)).length
647 distance_plane_5
= abs((n5
@ atom_pos
- g5
)/n5
.length
)
648 on_plane_5
= (atom_pos
- n5
* (distance_plane_5
/n5
.length
)).length
649 distance_plane_6
= abs((n6
@ atom_pos
- g6
)/n6
.length
)
650 on_plane_6
= (atom_pos
- n6
* (distance_plane_6
/n6
.length
)).length
651 distance_plane_7
= abs((n7
@ atom_pos
- g7
)/n7
.length
)
652 on_plane_7
= (atom_pos
- n7
* (distance_plane_7
/n7
.length
)).length
653 distance_plane_8
= abs((n8
@ atom_pos
- g8
)/n8
.length
)
654 on_plane_8
= (atom_pos
- n8
* (distance_plane_8
/n8
.length
)).length
657 if(atom_pos
.length
> on_plane_1
):
659 if(atom_pos
.length
> on_plane_2
):
661 if(atom_pos
.length
> on_plane_3
):
663 if(atom_pos
.length
> on_plane_4
):
665 if(atom_pos
.length
> on_plane_5
):
667 if(atom_pos
.length
> on_plane_6
):
669 if(atom_pos
.length
> on_plane_7
):
671 if(atom_pos
.length
> on_plane_8
):
674 return (regular
, inner
)
677 def vec_in_truncated_octahedron(atom_pos
,size
, skin
):
682 # The normal octahedron
685 n1
= Vector((-1/4, -1/4, -1/4)) * size2
687 n2
= Vector((-1/4, 1/4, -1/4)) * size2
689 n3
= Vector((-1/4, -1/4, 1/4)) * size2
691 n4
= Vector(( 1/4, -1/4, 1/4)) * size2
693 n5
= Vector(( 1/4, -1/4, -1/4)) * size2
695 n6
= Vector(( 1/4, 1/4, 1/4)) * size2
697 n7
= Vector(( 1/4, 1/4, -1/4)) * size2
699 n8
= Vector((-1/4, 1/4, 1/4)) * size2
702 distance_plane_1
= abs((n1
@ atom_pos
- g1
)/n1
.length
)
703 on_plane_1
= (atom_pos
- n1
* (distance_plane_1
/n1
.length
)).length
704 distance_plane_2
= abs((n2
@ atom_pos
- g2
)/n2
.length
)
705 on_plane_2
= (atom_pos
- n2
* (distance_plane_2
/n2
.length
)).length
706 distance_plane_3
= abs((n3
@ atom_pos
- g3
)/n3
.length
)
707 on_plane_3
= (atom_pos
- n3
* (distance_plane_3
/n3
.length
)).length
708 distance_plane_4
= abs((n4
@ atom_pos
- g4
)/n4
.length
)
709 on_plane_4
= (atom_pos
- n4
* (distance_plane_4
/n4
.length
)).length
710 distance_plane_5
= abs((n5
@ atom_pos
- g5
)/n5
.length
)
711 on_plane_5
= (atom_pos
- n5
* (distance_plane_5
/n5
.length
)).length
712 distance_plane_6
= abs((n6
@ atom_pos
- g6
)/n6
.length
)
713 on_plane_6
= (atom_pos
- n6
* (distance_plane_6
/n6
.length
)).length
714 distance_plane_7
= abs((n7
@ atom_pos
- g7
)/n7
.length
)
715 on_plane_7
= (atom_pos
- n7
* (distance_plane_7
/n7
.length
)).length
716 distance_plane_8
= abs((n8
@ atom_pos
- g8
)/n8
.length
)
717 on_plane_8
= (atom_pos
- n8
* (distance_plane_8
/n8
.length
)).length
719 # Here are the 6 additional faces
720 # pp = (size/2.0) - (sqrt(2.0)/2.0) * ((size/sqrt(2.0))/3.0)
723 n_1
= Vector((1.0,0.0,0.0))
724 n_2
= Vector((-1.0,0.0,0.0))
725 n_3
= Vector((0.0,1.0,0.0))
726 n_4
= Vector((0.0,-1.0,0.0))
727 n_5
= Vector((0.0,0.0,1.0))
728 n_6
= Vector((0.0,0.0,-1.0))
730 distance_plane_1b
= abs((n_1
@ atom_pos
+ pp
)/n_1
.length
)
731 on_plane_1b
= (atom_pos
- n_1
* (distance_plane_1b
/n_1
.length
)).length
732 distance_plane_2b
= abs((n_2
@ atom_pos
+ pp
)/n_2
.length
)
733 on_plane_2b
= (atom_pos
- n_2
* (distance_plane_2b
/n_2
.length
)).length
734 distance_plane_3b
= abs((n_3
@ atom_pos
+ pp
)/n_3
.length
)
735 on_plane_3b
= (atom_pos
- n_3
* (distance_plane_3b
/n_3
.length
)).length
736 distance_plane_4b
= abs((n_4
@ atom_pos
+ pp
)/n_4
.length
)
737 on_plane_4b
= (atom_pos
- n_4
* (distance_plane_4b
/n_4
.length
)).length
738 distance_plane_5b
= abs((n_5
@ atom_pos
+ pp
)/n_5
.length
)
739 on_plane_5b
= (atom_pos
- n_5
* (distance_plane_5b
/n_5
.length
)).length
740 distance_plane_6b
= abs((n_6
@ atom_pos
+ pp
)/n_6
.length
)
741 on_plane_6b
= (atom_pos
- n_6
* (distance_plane_6b
/n_6
.length
)).length
743 if(atom_pos
.length
> on_plane_1
):
745 if(atom_pos
.length
> on_plane_2
):
747 if(atom_pos
.length
> on_plane_3
):
749 if(atom_pos
.length
> on_plane_4
):
751 if(atom_pos
.length
> on_plane_5
):
753 if(atom_pos
.length
> on_plane_6
):
755 if(atom_pos
.length
> on_plane_7
):
757 if(atom_pos
.length
> on_plane_8
):
759 if(atom_pos
.length
> on_plane_1b
):
761 if(atom_pos
.length
> on_plane_2b
):
763 if(atom_pos
.length
> on_plane_3b
):
765 if(atom_pos
.length
> on_plane_4b
):
767 if(atom_pos
.length
> on_plane_5b
):
769 if(atom_pos
.length
> on_plane_6b
):
773 return (regular
, inner
)
775 size
= size
* (1.0 - skin
)
777 # The normal octahedron
780 n1
= Vector((-1/4, -1/4, -1/4)) * size2
782 n2
= Vector((-1/4, 1/4, -1/4)) * size2
784 n3
= Vector((-1/4, -1/4, 1/4)) * size2
786 n4
= Vector(( 1/4, -1/4, 1/4)) * size2
788 n5
= Vector(( 1/4, -1/4, -1/4)) * size2
790 n6
= Vector(( 1/4, 1/4, 1/4)) * size2
792 n7
= Vector(( 1/4, 1/4, -1/4)) * size2
794 n8
= Vector((-1/4, 1/4, 1/4)) * size2
797 distance_plane_1
= abs((n1
@ atom_pos
- g1
)/n1
.length
)
798 on_plane_1
= (atom_pos
- n1
* (distance_plane_1
/n1
.length
)).length
799 distance_plane_2
= abs((n2
@ atom_pos
- g2
)/n2
.length
)
800 on_plane_2
= (atom_pos
- n2
* (distance_plane_2
/n2
.length
)).length
801 distance_plane_3
= abs((n3
@ atom_pos
- g3
)/n3
.length
)
802 on_plane_3
= (atom_pos
- n3
* (distance_plane_3
/n3
.length
)).length
803 distance_plane_4
= abs((n4
@ atom_pos
- g4
)/n4
.length
)
804 on_plane_4
= (atom_pos
- n4
* (distance_plane_4
/n4
.length
)).length
805 distance_plane_5
= abs((n5
@ atom_pos
- g5
)/n5
.length
)
806 on_plane_5
= (atom_pos
- n5
* (distance_plane_5
/n5
.length
)).length
807 distance_plane_6
= abs((n6
@ atom_pos
- g6
)/n6
.length
)
808 on_plane_6
= (atom_pos
- n6
* (distance_plane_6
/n6
.length
)).length
809 distance_plane_7
= abs((n7
@ atom_pos
- g7
)/n7
.length
)
810 on_plane_7
= (atom_pos
- n7
* (distance_plane_7
/n7
.length
)).length
811 distance_plane_8
= abs((n8
@ atom_pos
- g8
)/n8
.length
)
812 on_plane_8
= (atom_pos
- n8
* (distance_plane_8
/n8
.length
)).length
814 # Here are the 6 additional faces
815 # pp = (size/2.0) - (sqrt(2.0)/2.0) * ((size/sqrt(2.0))/3.0)
818 n_1
= Vector((1.0,0.0,0.0))
819 n_2
= Vector((-1.0,0.0,0.0))
820 n_3
= Vector((0.0,1.0,0.0))
821 n_4
= Vector((0.0,-1.0,0.0))
822 n_5
= Vector((0.0,0.0,1.0))
823 n_6
= Vector((0.0,0.0,-1.0))
825 distance_plane_1b
= abs((n_1
@ atom_pos
+ pp
)/n_1
.length
)
826 on_plane_1b
= (atom_pos
- n_1
* (distance_plane_1b
/n_1
.length
)).length
827 distance_plane_2b
= abs((n_2
@ atom_pos
+ pp
)/n_2
.length
)
828 on_plane_2b
= (atom_pos
- n_2
* (distance_plane_2b
/n_2
.length
)).length
829 distance_plane_3b
= abs((n_3
@ atom_pos
+ pp
)/n_3
.length
)
830 on_plane_3b
= (atom_pos
- n_3
* (distance_plane_3b
/n_3
.length
)).length
831 distance_plane_4b
= abs((n_4
@ atom_pos
+ pp
)/n_4
.length
)
832 on_plane_4b
= (atom_pos
- n_4
* (distance_plane_4b
/n_4
.length
)).length
833 distance_plane_5b
= abs((n_5
@ atom_pos
+ pp
)/n_5
.length
)
834 on_plane_5b
= (atom_pos
- n_5
* (distance_plane_5b
/n_5
.length
)).length
835 distance_plane_6b
= abs((n_6
@ atom_pos
+ pp
)/n_6
.length
)
836 on_plane_6b
= (atom_pos
- n_6
* (distance_plane_6b
/n_6
.length
)).length
840 if(atom_pos
.length
> on_plane_1
):
842 if(atom_pos
.length
> on_plane_2
):
844 if(atom_pos
.length
> on_plane_3
):
846 if(atom_pos
.length
> on_plane_4
):
848 if(atom_pos
.length
> on_plane_5
):
850 if(atom_pos
.length
> on_plane_6
):
852 if(atom_pos
.length
> on_plane_7
):
854 if(atom_pos
.length
> on_plane_8
):
856 if(atom_pos
.length
> on_plane_1b
):
858 if(atom_pos
.length
> on_plane_2b
):
860 if(atom_pos
.length
> on_plane_3b
):
862 if(atom_pos
.length
> on_plane_4b
):
864 if(atom_pos
.length
> on_plane_5b
):
866 if(atom_pos
.length
> on_plane_6b
):
869 return (regular
, inner
)
871 # -----------------------------------------------------------------------------
872 # Routines for lattices
874 def create_hexagonal_abcabc_lattice(ctype
, size
, skin
, lattice
):
876 atom_number_total
= 0
877 atom_number_drawn
= 0
882 e = (1/sqrt(2.0)) * lattice
883 f = sqrt(3.0/4.0) * e
884 df1 = (e/2.0) * tan((30.0/360.0)*2.0*pi)
885 df2 = (e/2.0) / cos((30.0/360.0)*2.0*pi)
886 g = sqrt(2.0/3.0) * e
889 e
= 0.7071067810 * lattice
891 df1
= 0.2886751348 * e
892 df2
= 0.5773502690 * e
895 if ctype
== "parabolid_abc":
896 # size = height, skin = diameter
897 number_x
= int(skin
/(2*e
))+4
898 number_y
= int(skin
/(2*f
))+4
899 number_z
= int(size
/(2*g
))
901 number_x
= int(size
/(2*e
))+4
902 number_y
= int(size
/(2*f
))+4
903 number_z
= int(size
/(2*g
))+1+4
906 for k
in range(-number_z
,number_z
+1):
907 for j
in range(-number_y
,number_y
+1):
908 for i
in range(-number_x
,number_x
+1):
909 atom
= Vector((float(i
)*e
,float(j
)*f
,float(k
)*g
))
923 if ctype
== "sphere_hex_abc":
924 message
= vec_in_sphere(atom
, size
, skin
)
925 elif ctype
== "pyramide_hex_abc":
926 # size = height, skin = diameter
927 message
= vec_in_pyramide_hex_abc(atom
, size
, skin
)
928 elif ctype
== "parabolid_abc":
929 message
= vec_in_parabole(atom
, size
, skin
)
931 if message
[0] == True and message
[1] == True:
932 atom_add
= CLASS_atom_cluster_atom(atom
)
933 ATOM_CLUSTER_ALL_ATOMS
.append(atom_add
)
934 atom_number_total
+= 1
935 atom_number_drawn
+= 1
936 if message
[0] == True and message
[1] == False:
937 atom_number_total
+= 1
952 print("Atom positions calculated")
954 return (atom_number_total
, atom_number_drawn
)
957 def create_hexagonal_abab_lattice(ctype
, size
, skin
, lattice
):
959 atom_number_total
= 0
960 atom_number_drawn
= 0
965 e = (1/sqrt(2.0)) * lattice
966 f = sqrt(3.0/4.0) * e
967 df = (e/2.0) * tan((30.0/360.0)*2*pi)
968 g = sqrt(2.0/3.0) * e
971 e
= 0.7071067814 * lattice
973 df
= 0.2886751348 * e
977 if ctype
== "parabolid_ab":
978 # size = height, skin = diameter
979 number_x
= int(skin
/(2*e
))+4
980 number_y
= int(skin
/(2*f
))+4
981 number_z
= int(size
/(2*g
))
983 number_x
= int(size
/(2*e
))+4
984 number_y
= int(size
/(2*f
))+4
985 number_z
= int(size
/(2*g
))+1+4
988 for k
in range(-number_z
,number_z
+1):
989 for j
in range(-number_y
,number_y
+1):
990 for i
in range(-number_x
,number_x
+1):
992 atom
= Vector((float(i
)*e
,float(j
)*f
,float(k
)*g
))
1003 if ctype
== "sphere_hex_ab":
1004 message
= vec_in_sphere(atom
, size
, skin
)
1005 elif ctype
== "parabolid_ab":
1006 # size = height, skin = diameter
1007 message
= vec_in_parabole(atom
, size
, skin
)
1009 if message
[0] == True and message
[1] == True:
1010 atom_add
= CLASS_atom_cluster_atom(atom
)
1011 ATOM_CLUSTER_ALL_ATOMS
.append(atom_add
)
1012 atom_number_total
+= 1
1013 atom_number_drawn
+= 1
1014 if message
[0] == True and message
[1] == False:
1015 atom_number_total
+= 1
1017 if "even" in y_displ
:
1023 if "even" in z_displ
:
1028 print("Atom positions calculated")
1030 return (atom_number_total
, atom_number_drawn
)
1033 def create_square_lattice(ctype
, size
, skin
, lattice
):
1035 atom_number_total
= 0
1036 atom_number_drawn
= 0
1038 if ctype
== "parabolid_square":
1039 # size = height, skin = diameter
1040 number_k
= int(size
/(2.0*lattice
))
1041 number_j
= int(skin
/(2.0*lattice
)) + 5
1042 number_i
= int(skin
/(2.0*lattice
)) + 5
1044 number_k
= int(size
/(2.0*lattice
))
1045 number_j
= int(size
/(2.0*lattice
))
1046 number_i
= int(size
/(2.0*lattice
))
1049 for k
in range(-number_k
,number_k
+1):
1050 for j
in range(-number_j
,number_j
+1):
1051 for i
in range(-number_i
,number_i
+1):
1053 atom
= Vector((float(i
),float(j
),float(k
))) * lattice
1055 if ctype
== "sphere_square":
1056 message
= vec_in_sphere(atom
, size
, skin
)
1057 elif ctype
== "pyramide_square":
1058 message
= vec_in_pyramide_square(atom
, size
, skin
)
1059 elif ctype
== "parabolid_square":
1060 # size = height, skin = diameter
1061 message
= vec_in_parabole(atom
, size
, skin
)
1062 elif ctype
== "octahedron":
1063 message
= vec_in_octahedron(atom
, size
, skin
)
1064 elif ctype
== "truncated_octahedron":
1065 message
= vec_in_truncated_octahedron(atom
,size
, skin
)
1067 if message
[0] == True and message
[1] == True:
1068 atom_add
= CLASS_atom_cluster_atom(atom
)
1069 ATOM_CLUSTER_ALL_ATOMS
.append(atom_add
)
1070 atom_number_total
+= 1
1071 atom_number_drawn
+= 1
1072 if message
[0] == True and message
[1] == False:
1073 atom_number_total
+= 1
1075 print("Atom positions calculated")
1077 return (atom_number_total
, atom_number_drawn
)
1081 # -----------------------------------------------------------------------------
1082 # Routine for the icosahedron
1085 # Note that the icosahedron needs a special treatment since it requires a
1086 # non-common crystal lattice. The faces are (111) facets and the geometry
1087 # is five-fold. So far, a max size of 8217 atoms can be chosen.
1088 # More details about icosahedron shaped clusters can be found in:
1090 # 1. C. Mottet, G. Tréglia, B. Legrand, Surface Science 383 (1997) L719-L727
1091 # 2. C. R. Henry, Surface Science Reports 31 (1998) 231-325
1093 # The following code is a translation from an existing Fortran code into Python.
1094 # The Fortran code has been created by Christine Mottet and translated by me
1097 # Although a couple of code lines are non-typical for Python, it is best to
1098 # leave the code as is.
1102 # 1. Unlimited cluster size
1105 def create_icosahedron(size
, lattice
):
1107 natot
= int(1 + (10*size
*size
+15*size
+11)*size
/3)
1109 x
= list(range(natot
+1))
1110 y
= list(range(natot
+1))
1111 z
= list(range(natot
+1))
1113 xs
= list(range(12+1))
1114 ys
= list(range(12+1))
1115 zs
= list(range(12+1))
1117 xa
= [[[ [] for i
in range(12+1)] for j
in range(12+1)] for k
in range(20+1)]
1118 ya
= [[[ [] for i
in range(12+1)] for j
in range(12+1)] for k
in range(20+1)]
1119 za
= [[[ [] for i
in range(12+1)] for j
in range(12+1)] for k
in range(20+1)]
1121 naret
= [[ [] for i
in range(12+1)] for j
in range(12+1)]
1122 nfacet
= [[[ [] for i
in range(12+1)] for j
in range(12+1)] for k
in range(12+1)]
1126 tdef
= (rac5
+1.0)/2.0
1128 rapp
= sqrt(2.0*(1.0-tdef
/(tdef
*tdef
+1.0)))
1129 nats
= 2 * (5*size
*size
+1)
1137 for i
in range(2, 5+1):
1142 for i
in range(2, 3+1):
1150 for i
in range(2, 4+1, 2):
1158 xdef
= rac2
/ sqrt(tdef
* tdef
+ 1)
1160 for i
in range(2, 13+1):
1161 x
[i
] = x
[i
] * xdef
/ 2.0
1162 y
[i
] = y
[i
] * xdef
/ 2.0
1163 z
[i
] = z
[i
] * xdef
/ 2.0
1167 for n
in range (2, size
+1):
1171 for i
in range(1, 12+1):
1172 for j
in range(1, 12+1):
1174 for k
in range (1, 12+1):
1184 for i
in range(1, 12+1):
1194 for i
in range(1, 12+1):
1195 for j
in range(2, 12+1):
1205 dij2
= xij2
+ yij2
+ zij2
1206 dssn
= n
* rapp
/ rac2
1208 diffij
= abs(dij2
-dssn2
)
1212 for k
in range(3, 12+1):
1222 djk2
= xjk2
+ yjk2
+ zjk2
1223 diffjk
= abs(djk2
-dssn2
)
1233 dik2
= xik2
+ yik2
+ zik2
1234 diffik
= abs(dik2
-dssn2
)
1238 if nfacet
[i
][j
][k
] != 0:
1242 nfacet
[i
][j
][k
] = ifacet
1244 if naret
[i
][j
] == 0:
1247 for l
in range(1,n
-1+1):
1249 xa
[i
][j
][l
] = xs
[i
]+l
*(xs
[j
]-xs
[i
]) / n
1250 ya
[i
][j
][l
] = ys
[i
]+l
*(ys
[j
]-ys
[i
]) / n
1251 za
[i
][j
][l
] = zs
[i
]+l
*(zs
[j
]-zs
[i
]) / n
1252 x
[nat
] = xa
[i
][j
][l
]
1253 y
[nat
] = ya
[i
][j
][l
]
1254 z
[nat
] = za
[i
][j
][l
]
1256 if naret
[i
][k
] == 0:
1259 for l
in range(1, n
-1+1):
1261 xa
[i
][k
][l
] = xs
[i
]+l
*(xs
[k
]-xs
[i
]) / n
1262 ya
[i
][k
][l
] = ys
[i
]+l
*(ys
[k
]-ys
[i
]) / n
1263 za
[i
][k
][l
] = zs
[i
]+l
*(zs
[k
]-zs
[i
]) / n
1264 x
[nat
] = xa
[i
][k
][l
]
1265 y
[nat
] = ya
[i
][k
][l
]
1266 z
[nat
] = za
[i
][k
][l
]
1268 if naret
[j
][k
] == 0:
1271 for l
in range(1, n
-1+1):
1273 xa
[j
][k
][l
] = xs
[j
]+l
*(xs
[k
]-xs
[j
]) / n
1274 ya
[j
][k
][l
] = ys
[j
]+l
*(ys
[k
]-ys
[j
]) / n
1275 za
[j
][k
][l
] = zs
[j
]+l
*(zs
[k
]-zs
[j
]) / n
1276 x
[nat
] = xa
[j
][k
][l
]
1277 y
[nat
] = ya
[j
][k
][l
]
1278 z
[nat
] = za
[j
][k
][l
]
1280 for l
in range(2, n
-1+1):
1281 for ll
in range(1, l
-1+1):
1282 xf
= xa
[i
][j
][l
]+ll
*(xa
[i
][k
][l
]-xa
[i
][j
][l
]) / l
1283 yf
= ya
[i
][j
][l
]+ll
*(ya
[i
][k
][l
]-ya
[i
][j
][l
]) / l
1284 zf
= za
[i
][j
][l
]+ll
*(za
[i
][k
][l
]-za
[i
][j
][l
]) / l
1292 atom_number_total
= 0
1293 atom_number_drawn
= 0
1295 for i
in range (1,natot
+1):
1297 atom
= Vector((x
[i
],y
[i
],z
[i
])) * lattice
1299 atom_add
= CLASS_atom_cluster_atom(atom
)
1300 ATOM_CLUSTER_ALL_ATOMS
.append(atom_add
)
1301 atom_number_total
+= 1
1302 atom_number_drawn
+= 1
1304 return (atom_number_total
, atom_number_drawn
)