1# -*- coding: utf-8 -*-
2# Copyright (C) 2011 Atsushi Togo
3# All rights reserved.
4#
5# This file is part of phonopy.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10#
11# * Redistributions of source code must retain the above copyright
12#   notice, this list of conditions and the following disclaimer.
13#
14# * Redistributions in binary form must reproduce the above copyright
15#   notice, this list of conditions and the following disclaimer in
16#   the documentation and/or other materials provided with the
17#   distribution.
18#
19# * Neither the name of the phonopy project nor the names of its
20#   contributors may be used to endorse or promote products derived
21#   from this software without specific prior written permission.
22#
23# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34# POSSIBILITY OF SUCH DAMAGE.
35
36import numpy as np
37
38class Atoms:
39    """Atoms class compatible with the ASE Atoms class
40    Only the necessary stuffs to phonpy are implemented. """
41
42    def __init__(self,
43                 symbols=None,
44                 positions=None,
45                 numbers=None,
46                 masses=None,
47                 magmoms=None,
48                 scaled_positions=None,
49                 cell=None,
50                 pbc=None):
51
52        # cell
53        if cell is None:
54            self.cell = None
55        else:
56            self.cell = np.array(cell, dtype='double', order='C')
57
58        # position
59        self.scaled_positions = None
60        if (not self.cell is None) and  (not positions is None):
61            self.set_positions(positions)
62        if (not scaled_positions is None):
63            self.set_scaled_positions(scaled_positions)
64
65        # Atom symbols
66        self.symbols = symbols
67
68        # Atomic numbers
69        if numbers is None:
70            self.numbers = None
71        else:
72            self.numbers = np.array(numbers, dtype='intc')
73
74        # masses
75        self.set_masses(masses)
76
77        # (initial) magnetic moments
78        self.set_magnetic_moments(magmoms)
79
80        # number --> symbol
81        if not self.numbers is None:
82            self._numbers_to_symbols()
83
84        # symbol --> number
85        elif not self.symbols is None:
86            self._symbols_to_numbers()
87
88        # symbol --> mass
89        if self.symbols and (self.masses is None):
90            self._symbols_to_masses()
91
92
93    def set_cell(self, cell):
94        self.cell = np.array(cell, dtype='double', order='C')
95
96    def get_cell(self):
97        return self.cell.copy()
98
99    def set_positions(self, cart_positions):
100        self.scaled_positions = np.array(
101            np.dot(cart_positions, np.linalg.inv(self.cell)),
102            dtype='double', order='C')
103
104    def get_positions(self):
105        return np.dot(self.scaled_positions, self.cell)
106
107    def set_scaled_positions(self, scaled_positions):
108        self.scaled_positions = np.array(scaled_positions,
109                                         dtype='double', order='C')
110
111    def get_scaled_positions(self):
112        return self.scaled_positions.copy()
113
114    def set_masses(self, masses):
115        if masses is None:
116            self.masses = None
117        else:
118            self.masses = np.array(masses, dtype='double')
119
120    def get_masses(self):
121        if self.masses is None:
122            return None
123        else:
124            return self.masses.copy()
125
126    def set_magnetic_moments(self, magmoms):
127        if magmoms is None:
128            self.magmoms = None
129        else:
130            self.magmoms = np.array(magmoms, dtype='double')
131
132    def get_magnetic_moments(self):
133        if self.magmoms is None:
134            return None
135        else:
136            return self.magmoms.copy()
137
138    def set_chemical_symbols(self, symbols):
139        self.symbols = symbols
140
141    def get_chemical_symbols(self):
142        return self.symbols[:]
143
144    def get_number_of_atoms(self):
145        return len(self.scaled_positions)
146
147    def get_atomic_numbers(self):
148        return self.numbers.copy()
149
150    def get_volume(self):
151        return np.linalg.det(self.cell)
152
153    def copy(self):
154        return Atoms(cell=self.cell,
155                     scaled_positions=self.scaled_positions,
156                     masses=self.masses,
157                     magmoms=self.magmoms,
158                     symbols=self.symbols,
159                     pbc=True)
160
161    def _numbers_to_symbols(self):
162        self.symbols = [atom_data[n][1] for n in self.numbers]
163
164    def _symbols_to_numbers(self):
165        self.numbers = np.array([symbol_map[s]
166                                 for s in self.symbols], dtype='intc')
167
168    def _symbols_to_masses(self):
169        masses = [atom_data[symbol_map[s]][3] for s in self.symbols]
170        if None in masses:
171            self.masses = None
172        else:
173            self.masses = np.array(masses, dtype='double')
174
175atom_data = [
176    [  0, "X", "X", None], # 0
177    [  1, "H", "Hydrogen", 1.00794], # 1
178    [  2, "He", "Helium", 4.002602], # 2
179    [  3, "Li", "Lithium", 6.941], # 3
180    [  4, "Be", "Beryllium", 9.012182], # 4
181    [  5, "B", "Boron", 10.811], # 5
182    [  6, "C", "Carbon", 12.0107], # 6
183    [  7, "N", "Nitrogen", 14.0067], # 7
184    [  8, "O", "Oxygen", 15.9994], # 8
185    [  9, "F", "Fluorine", 18.9984032], # 9
186    [ 10, "Ne", "Neon", 20.1797], # 10
187    [ 11, "Na", "Sodium", 22.98976928], # 11
188    [ 12, "Mg", "Magnesium", 24.3050], # 12
189    [ 13, "Al", "Aluminium", 26.9815386], # 13
190    [ 14, "Si", "Silicon", 28.0855], # 14
191    [ 15, "P", "Phosphorus", 30.973762], # 15
192    [ 16, "S", "Sulfur", 32.065], # 16
193    [ 17, "Cl", "Chlorine", 35.453], # 17
194    [ 18, "Ar", "Argon", 39.948], # 18
195    [ 19, "K", "Potassium", 39.0983], # 19
196    [ 20, "Ca", "Calcium", 40.078], # 20
197    [ 21, "Sc", "Scandium", 44.955912], # 21
198    [ 22, "Ti", "Titanium", 47.867], # 22
199    [ 23, "V", "Vanadium", 50.9415], # 23
200    [ 24, "Cr", "Chromium", 51.9961], # 24
201    [ 25, "Mn", "Manganese", 54.938045], # 25
202    [ 26, "Fe", "Iron", 55.845], # 26
203    [ 27, "Co", "Cobalt", 58.933195], # 27
204    [ 28, "Ni", "Nickel", 58.6934], # 28
205    [ 29, "Cu", "Copper", 63.546], # 29
206    [ 30, "Zn", "Zinc", 65.38], # 30
207    [ 31, "Ga", "Gallium", 69.723], # 31
208    [ 32, "Ge", "Germanium", 72.64], # 32
209    [ 33, "As", "Arsenic", 74.92160], # 33
210    [ 34, "Se", "Selenium", 78.96], # 34
211    [ 35, "Br", "Bromine", 79.904], # 35
212    [ 36, "Kr", "Krypton", 83.798], # 36
213    [ 37, "Rb", "Rubidium", 85.4678], # 37
214    [ 38, "Sr", "Strontium", 87.62], # 38
215    [ 39, "Y", "Yttrium", 88.90585], # 39
216    [ 40, "Zr", "Zirconium", 91.224], # 40
217    [ 41, "Nb", "Niobium", 92.90638], # 41
218    [ 42, "Mo", "Molybdenum", 95.96], # 42
219    [ 43, "Tc", "Technetium", None], # 43
220    [ 44, "Ru", "Ruthenium", 101.07], # 44
221    [ 45, "Rh", "Rhodium", 102.90550], # 45
222    [ 46, "Pd", "Palladium", 106.42], # 46
223    [ 47, "Ag", "Silver", 107.8682], # 47
224    [ 48, "Cd", "Cadmium", 112.411], # 48
225    [ 49, "In", "Indium", 114.818], # 49
226    [ 50, "Sn", "Tin", 118.710], # 50
227    [ 51, "Sb", "Antimony", 121.760], # 51
228    [ 52, "Te", "Tellurium", 127.60], # 52
229    [ 53, "I", "Iodine", 126.90447], # 53
230    [ 54, "Xe", "Xenon", 131.293], # 54
231    [ 55, "Cs", "Caesium", 132.9054519], # 55
232    [ 56, "Ba", "Barium", 137.327], # 56
233    [ 57, "La", "Lanthanum", 138.90547], # 57
234    [ 58, "Ce", "Cerium", 140.116], # 58
235    [ 59, "Pr", "Praseodymium", 140.90765], # 59
236    [ 60, "Nd", "Neodymium", 144.242], # 60
237    [ 61, "Pm", "Promethium", None], # 61
238    [ 62, "Sm", "Samarium", 150.36], # 62
239    [ 63, "Eu", "Europium", 151.964], # 63
240    [ 64, "Gd", "Gadolinium", 157.25], # 64
241    [ 65, "Tb", "Terbium", 158.92535], # 65
242    [ 66, "Dy", "Dysprosium", 162.500], # 66
243    [ 67, "Ho", "Holmium", 164.93032], # 67
244    [ 68, "Er", "Erbium", 167.259], # 68
245    [ 69, "Tm", "Thulium", 168.93421], # 69
246    [ 70, "Yb", "Ytterbium", 173.054], # 70
247    [ 71, "Lu", "Lutetium", 174.9668], # 71
248    [ 72, "Hf", "Hafnium", 178.49], # 72
249    [ 73, "Ta", "Tantalum", 180.94788], # 73
250    [ 74, "W", "Tungsten", 183.84], # 74
251    [ 75, "Re", "Rhenium", 186.207], # 75
252    [ 76, "Os", "Osmium", 190.23], # 76
253    [ 77, "Ir", "Iridium", 192.217], # 77
254    [ 78, "Pt", "Platinum", 195.084], # 78
255    [ 79, "Au", "Gold", 196.966569], # 79
256    [ 80, "Hg", "Mercury", 200.59], # 80
257    [ 81, "Tl", "Thallium", 204.3833], # 81
258    [ 82, "Pb", "Lead", 207.2], # 82
259    [ 83, "Bi", "Bismuth", 208.98040], # 83
260    [ 84, "Po", "Polonium", None], # 84
261    [ 85, "At", "Astatine", None], # 85
262    [ 86, "Rn", "Radon", None], # 86
263    [ 87, "Fr", "Francium", None], # 87
264    [ 88, "Ra", "Radium", None], # 88
265    [ 89, "Ac", "Actinium", None], # 89
266    [ 90, "Th", "Thorium", 232.03806], # 90
267    [ 91, "Pa", "Protactinium", 231.03588], # 91
268    [ 92, "U", "Uranium", 238.02891], # 92
269    [ 93, "Np", "Neptunium", None], # 93
270    [ 94, "Pu", "Plutonium", None], # 94
271    [ 95, "Am", "Americium", None], # 95
272    [ 96, "Cm", "Curium", None], # 96
273    [ 97, "Bk", "Berkelium", None], # 97
274    [ 98, "Cf", "Californium", None], # 98
275    [ 99, "Es", "Einsteinium", None], # 99
276    [100, "Fm", "Fermium", None], # 100
277    [101, "Md", "Mendelevium", None], # 101
278    [102, "No", "Nobelium", None], # 102
279    [103, "Lr", "Lawrencium", None], # 103
280    [104, "Rf", "Rutherfordium", None], # 104
281    [105, "Db", "Dubnium", None], # 105
282    [106, "Sg", "Seaborgium", None], # 106
283    [107, "Bh", "Bohrium", None], # 107
284    [108, "Hs", "Hassium", None], # 108
285    [109, "Mt", "Meitnerium", None], # 109
286    [110, "Ds", "Darmstadtium", None], # 110
287    [111, "Rg", "Roentgenium", None], # 111
288    [112, "Cn", "Copernicium", None], # 112
289    [113, "Uut", "Ununtrium", None], # 113
290    [114, "Uuq", "Ununquadium", None], # 114
291    [115, "Uup", "Ununpentium", None], # 115
292    [116, "Uuh", "Ununhexium", None], # 116
293    [117, "Uus", "Ununseptium", None], # 117
294    [118, "Uuo", "Ununoctium", None], # 118
295    ]
296
297symbol_map = {
298    "H":1,
299    "He":2,
300    "Li":3,
301    "Be":4,
302    "B":5,
303    "C":6,
304    "N":7,
305    "O":8,
306    "F":9,
307    "Ne":10,
308    "Na":11,
309    "Mg":12,
310    "Al":13,
311    "Si":14,
312    "P":15,
313    "S":16,
314    "Cl":17,
315    "Ar":18,
316    "K":19,
317    "Ca":20,
318    "Sc":21,
319    "Ti":22,
320    "V":23,
321    "Cr":24,
322    "Mn":25,
323    "Fe":26,
324    "Co":27,
325    "Ni":28,
326    "Cu":29,
327    "Zn":30,
328    "Ga":31,
329    "Ge":32,
330    "As":33,
331    "Se":34,
332    "Br":35,
333    "Kr":36,
334    "Rb":37,
335    "Sr":38,
336    "Y":39,
337    "Zr":40,
338    "Nb":41,
339    "Mo":42,
340    "Tc":43,
341    "Ru":44,
342    "Rh":45,
343    "Pd":46,
344    "Ag":47,
345    "Cd":48,
346    "In":49,
347    "Sn":50,
348    "Sb":51,
349    "Te":52,
350    "I":53,
351    "Xe":54,
352    "Cs":55,
353    "Ba":56,
354    "La":57,
355    "Ce":58,
356    "Pr":59,
357    "Nd":60,
358    "Pm":61,
359    "Sm":62,
360    "Eu":63,
361    "Gd":64,
362    "Tb":65,
363    "Dy":66,
364    "Ho":67,
365    "Er":68,
366    "Tm":69,
367    "Yb":70,
368    "Lu":71,
369    "Hf":72,
370    "Ta":73,
371    "W":74,
372    "Re":75,
373    "Os":76,
374    "Ir":77,
375    "Pt":78,
376    "Au":79,
377    "Hg":80,
378    "Tl":81,
379    "Pb":82,
380    "Bi":83,
381    "Po":84,
382    "At":85,
383    "Rn":86,
384    "Fr":87,
385    "Ra":88,
386    "Ac":89,
387    "Th":90,
388    "Pa":91,
389    "U":92,
390    "Np":93,
391    "Pu":94,
392    "Am":95,
393    "Cm":96,
394    "Bk":97,
395    "Cf":98,
396    "Es":99,
397    "Fm":100,
398    "Md":101,
399    "No":102,
400    "Lr":103,
401    "Rf":104,
402    "Db":105,
403    "Sg":106,
404    "Bh":107,
405    "Hs":108,
406    "Mt":109,
407    "Ds":110,
408    "Rg":111,
409    "Cn":112,
410    "Uut":113,
411    "Uuq":114,
412    "Uup":115,
413    "Uuh":116,
414    "Uus":117,
415    "Uuo":118,
416    }
417
418