Coverage for /builds/ase/ase/ase/calculators/openmx/writer.py : 14.37%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2The ASE Calculator for OpenMX <http://www.openmx-square.org>: Python interface
3to the software package for nano-scale material simulations based on density
4functional theories.
5 Copyright (C) 2018 JaeHwan Shim and JaeJun Yu
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation, either version 2.1 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with ASE. If not, see <http://www.gnu.org/licenses/>.
19"""
20import os
21import numpy as np
22from ase.units import Bohr, Ha, Ry, fs, m, s
23from ase.calculators.calculator import kpts2sizeandoffsets
24from ase.calculators.openmx.reader import (
25 read_electron_valency, get_file_name, get_standard_key)
26from ase.calculators.openmx import parameters as param
28keys = [param.tuple_integer_keys, param.tuple_float_keys,
29 param.tuple_bool_keys, param.integer_keys, param.float_keys,
30 param.string_keys, param.bool_keys, param.list_int_keys,
31 param.list_bool_keys, param.list_float_keys, param.matrix_keys]
34def write_openmx(label=None, atoms=None, parameters=None, properties=None,
35 system_changes=None):
36 """
37 From atom image, 'images', write '.dat' file.
38 First, set
39 Write input (dat)-file.
40 See calculator.py for further details.
42 Parameters:
43 - atoms : The Atoms object to write.
44 - properties : The properties which should be calculated.
45 - system_changes : List of properties changed since last run.
46 """
47 from ase.calculators.openmx import parameters as param
48 filtered_keywords = parameters_to_keywords(label=label, atoms=atoms,
49 parameters=parameters,
50 properties=properties,
51 system_changes=system_changes)
52 keys = ['string', 'bool', 'integer', 'float',
53 'tuple_integer', 'tuple_float', 'tuple_bool',
54 'matrix', 'list_int', 'list_bool', 'list_float']
55 # Start writing the file
56 filename = get_file_name('.dat', label)
57 with open(filename, 'w') as fd:
58 # Write 1-line keywords
59 for fltrd_keyword in filtered_keywords.keys():
60 for key in keys:
61 openmx_keywords = getattr(param, key + '_keys')
62 write = globals()['write_' + key]
63 for omx_keyword in openmx_keywords:
64 if fltrd_keyword == get_standard_key(omx_keyword):
65 write(fd, omx_keyword, filtered_keywords[fltrd_keyword])
68def parameters_to_keywords(label=None, atoms=None, parameters=None,
69 properties=None, system_changes=None):
70 """
71 Before writing `label.dat` file, set up the ASE variables to OpenMX
72 keywords. First, It initializes with given openmx keywords and reconstruct
73 dictionary using standard parameters. If standard parameters and openmx
74 keywords are contradict to each other, ignores openmx keyword.
75 It includes,
77 For aesthetical purpose, sequnece of writing input file is specified.
78 """
79 from ase.calculators.openmx.parameters import matrix_keys
80 from ase.calculators.openmx.parameters import unit_dat_keywords
81 from collections import OrderedDict
82 keywords = OrderedDict()
83 sequence = [
84 'system_currentdirectory', 'system_name', 'data_path',
85 'level_of_fileout',
86 'species_number', 'definition_of_atomic_species',
87 'atoms_number', 'atoms_speciesandcoordinates_unit',
88 'atoms_speciesandcoordinates', 'atoms_unitvectors_unit',
89 'atoms_unitvectors', 'band_dispersion', 'band_nkpath',
90 'band_kpath']
92 directory, prefix = os.path.split(label)
93 curdir = os.path.join(os.getcwd(), prefix)
94 counterparts = {
95 'system_currentdirectory': curdir,
96 'system_name': prefix,
97 'data_path': os.environ.get('OPENMX_DFT_DATA_PATH'),
98 'species_number': len(get_species(atoms.get_chemical_symbols())),
99 'atoms_number': len(atoms),
100 'scf_restart': 'restart',
101 'scf_maxiter': 'maxiter',
102 'scf_xctype': 'xc',
103 'scf_energycutoff': 'energy_cutoff',
104 'scf_criterion': 'convergence',
105 'scf_external_fields': 'external',
106 'scf_mixing_type': 'mixer',
107 'scf_electronic_temperature': 'smearing',
108 'scf_system_charge': 'charge',
109 'scf_eigenvaluesolver': 'eigensolver'
110 }
111 standard_units = {'eV': 1, 'Ha': Ha, 'Ry': Ry, 'Bohr': Bohr, 'fs': fs,
112 'K': 1, 'GV / m': 1e9 / 1.6e-19 / m,
113 'Ha/Bohr': Ha / Bohr,
114 'm/s': m / s, '_amu': 1, 'Tesla': 1}
115 unit_dict = {get_standard_key(k): v for k, v in unit_dat_keywords.items()}
117 for key in sequence:
118 keywords[key] = None
119 for key in parameters:
120 if 'scf' in key:
121 keywords[key] = None
122 for key in parameters:
123 if 'md' in key:
124 keywords[key] = None
126 # Initializes keywords to to given parameters
127 for key in parameters.keys():
128 keywords[key] = parameters[key]
130 def parameter_overwrites(openmx_keyword):
131 """
132 In a situation conflicting ASE standard parameters and OpenMX keywords,
133 ASE parameters overrides to OpenMX keywords. While doing so, units are
134 converted to OpenMX unit.
135 However, if both parameters and keyword are not given, we fill up that
136 part in suitable manner
137 openmx_keyword : key | Name of key used in OpenMX
138 keyword : value | value corresponds to openmx_keyword
139 ase_parameter : key | Name of parameter used in ASE
140 parameter : value | value corresponds to ase_parameter
141 """
142 ase_parameter = counterparts[openmx_keyword]
143 keyword = parameters.get(openmx_keyword)
144 parameter = parameters.get(ase_parameter)
145 if parameter is not None:
146 # Handles the unit
147 unit = standard_units.get(unit_dict.get(openmx_keyword))
148 if unit is not None:
149 return parameter / unit
150 return parameter
151 elif keyword is not None:
152 return keyword
153 elif 'scf' in openmx_keyword:
154 return None
155 else:
156 return counterparts[openmx_keyword]
158 # Overwrites openmx keyword using standard parameters
159 for openmx_keyword in counterparts.keys():
160 keywords[openmx_keyword] = parameter_overwrites(openmx_keyword)
162 # keywords['scf_stress_tensor'] = 'stress' in properties
163 # This is not working due to the UnitCellFilter method.
164 if 'energies' in properties:
165 keywords['energy_decomposition'] = True
166 if 'stress' in properties:
167 keywords['scf_stress_tensor'] = True
169 keywords['scf_xctype'] = get_xc(keywords['scf_xctype'])
170 keywords['scf_kgrid'] = get_scf_kgrid(atoms, parameters)
171 keywords['scf_spinpolarization'] = get_spinpol(atoms, parameters)
173 if parameters.get('band_kpath') is not None:
174 keywords['band_dispersion'] = True
175 keywords['band_kpath'] = parameters.get('band_kpath')
176 if parameters.get('band_nkpath') is not None:
177 keywords['band_nkpath'] = len(keywords['band_kpath'])
179 # Set up Wannier Environment
180 if parameters.get('wannier_func_calc') is not None:
181 keywords['species_number'] *= 2
183 # Set up some parameters for the later use
184 parameters['_xc'] = keywords['scf_xctype']
185 parameters['_data_path'] = keywords['data_path']
186 parameters['_year'] = get_dft_data_year(parameters)
188 # Set up the matrix-type OpenMX keywords
189 for key in matrix_keys:
190 get_matrix_key = globals()['get_' + get_standard_key(key)]
191 keywords[get_standard_key(key)] = get_matrix_key(atoms, parameters)
192 return OrderedDict([(k, v)for k, v in keywords.items()
193 if not (v is None or
194 (isinstance(v, list) and v == []))])
197def get_species(symbols):
198 species = []
199 [species.append(s) for s in symbols if s not in species]
200 return species
203def get_xc(xc):
204 """
205 Change the name of xc appropriate to OpenMX format
206 """
207 xc = xc.upper()
208 assert xc.upper() in param.OpenMXParameters().allowed_xc
209 if xc in ['PBE', 'GGA', 'GGA-PBE']:
210 return 'GGA-PBE'
211 elif xc in ['LDA']:
212 return 'LDA'
213 elif xc in ['CA', 'PW']:
214 return 'LSDA-' + xc
215 elif xc in ['LSDA', 'LSDA-CA']:
216 return 'LSDA-CA'
217 elif xc in ['LSDA-PW']:
218 return 'LSDA-PW'
219 else:
220 return 'LDA'
223def get_vps(xc):
224 if xc in ['GGA-PBE']:
225 return 'PBE'
226 else:
227 return 'CA'
230def get_scf_kgrid(atoms, parameters):
231 kpts, scf_kgrid = parameters.get('kpts'), parameters.get('scf_kgrid')
232 if isinstance(kpts, (tuple, list, np.ndarray)) and len(
233 kpts) == 3 and isinstance(kpts[0], int):
234 return kpts
235 elif isinstance(kpts, float) or isinstance(kpts, int):
236 return tuple(kpts2sizeandoffsets(atoms=atoms, density=kpts)[0])
237 else:
238 return scf_kgrid
241def get_definition_of_atomic_species(atoms, parameters):
242 """
243 Using atoms and parameters, Returns the list `definition_of_atomic_species`
244 where matrix of strings contains the information between keywords.
245 For example,
246 definition_of_atomic_species =
247 [['H','H5.0-s1>1p1>1','H_CA13'],
248 ['C','C5.0-s1>1p1>1','C_CA13']]
249 Goes to,
250 <Definition.of.Atomic.Species
251 H H5.0-s1>1p1>1 H_CA13
252 C C5.0-s1>1p1>1 C_CA13
253 Definition.of.Atomic.Species>
254 Further more, you can specify the wannier information here.
255 A. Define local functions for projectors
256 Since the pseudo-atomic orbitals are used for projectors,
257 the specification of them is the same as for the basis functions.
258 An example setting, for silicon in diamond structure, is as following:
259 Species.Number 2
260 <Definition.of.Atomic.Species
261 Si Si7.0-s2p2d1 Si_CA13
262 proj1 Si5.5-s1p1d1f1 Si_CA13
263 Definition.of.Atomic.Species>
264 """
265 if parameters.get('definition_of_atomic_species') is not None:
266 return parameters['definition_of_atomic_species']
268 definition_of_atomic_species = []
269 xc = parameters.get('_xc')
270 year = parameters.get('_year')
272 chem = atoms.get_chemical_symbols()
273 species = get_species(chem)
274 for element in species:
275 rad_orb = get_cutoff_radius_and_orbital(element=element)
276 suffix = get_pseudo_potential_suffix(element=element, xc=xc, year=year)
277 definition_of_atomic_species.append([element, rad_orb, suffix])
278 # Put the same orbital and radii with chemical symbol.
279 wannier_projectors = parameters.get('definition_of_wannier_projectors', [])
280 for i, projector in enumerate(wannier_projectors):
281 full_projector = definition_of_atomic_species[i]
282 full_projector[0] = projector
283 definition_of_atomic_species.append(full_projector)
284 return definition_of_atomic_species
287def get_dft_data_year(parameters):
288 """
289 It seems there is no version or potential year checker in openmx, thus we
290 implemented one. It parse the pesudo potential path variable such as
291 `~/PATH/TO/OPENMX/openmx3.9/DFT_DATA19/` or `.../openmx3.8/DFT_DATA13/`.
292 By spliting this string, we harness the number of the year that generated
293 such pseudo potential path.
294 """
295 if parameters.get('dft_data_year') is not None:
296 return str(parameters.get('dft_data_year'))
297 data_path = parameters['_data_path']
298 year = data_path.split('DFT_DATA')[1][:2]
299 if year is not None:
300 return year
301 else:
302 raise ValueError('DFT_DATA year can not be found. Please specify '
303 '`dft_data_year` as year of pseudo potential relesed')
306def get_cutoff_radius_and_orbital(element=None, orbital=None):
307 """
308 For a given element, retruns the string specifying cutoff radius and
309 orbital using default_settings.py. For example,
310 'Si' -> 'Si.7.0-s2p2d1'
311 If one wannts to change the atomic radius for a special purpose, one should
312 change the default_settings.py directly.
313 """
314 from ase.calculators.openmx import default_settings
315 orbital = element
316 orbital_letters = ['s', 'p', 'd', 'f', 'g', 'h']
317 default_dictionary = default_settings.default_dictionary
318 orbital_numbers = default_dictionary[element]['orbitals used']
319 cutoff_radius = default_dictionary[element]['cutoff radius']
320 orbital += "%.1f" % float(cutoff_radius) + '-'
321 for i, orbital_number in enumerate(orbital_numbers):
322 orbital += orbital_letters[i] + str(orbital_number)
323 return orbital
326def get_pseudo_potential_suffix(element=None, xc=None, year='13'):
327 """
328 For a given element, returns the string specifying pseudo potential suffix.
329 For example,
330 'Si' -> 'Si_CA13'
331 or
332 'Si' -> 'Si_CA19'
333 depending on pseudo potential generation year
334 """
335 from ase.calculators.openmx import default_settings
336 default_dictionary = default_settings.default_dictionary
337 pseudo_potential_suffix = element
338 vps = get_vps(xc)
339 suffix = default_dictionary[element]['pseudo-potential suffix']
340 pseudo_potential_suffix += '_' + vps + year + suffix
341 return pseudo_potential_suffix
344def get_atoms_speciesandcoordinates(atoms, parameters):
345 """
346 The atomic coordinates and the number of spin charge are given by the
347 keyword
348 'Atoms.SpeciesAndCoordinates' as follows:
349 <Atoms.SpeciesAndCoordinates
350 1 Mn 0.00000 0.00000 0.00000 8.0 5.0 45.0 0.0 45.0 0.0 1 on
351 2 O 1.70000 0.00000 0.00000 3.0 3.0 45.0 0.0 45.0 0.0 1 on
352 Atoms.SpeciesAndCoordinates>
353 to know more, link <http://www.openmx-square.org/openmx_man3.7/node85.html>
354 """
355 atoms_speciesandcoordinates = []
356 xc = parameters.get('_xc')
357 year = parameters.get('_year')
358 data_pth = parameters.get('_data_path')
359 # Appending number and elemental symbol
360 elements = atoms.get_chemical_symbols()
361 for i, element in enumerate(elements):
362 atoms_speciesandcoordinates.append([str(i + 1), element])
363 # Appending positions
364 unit = parameters.get('atoms_speciesandcoordinates_unit', 'ang').lower()
365 if unit == 'ang':
366 positions = atoms.get_positions()
367 elif unit == 'frac':
368 positions = atoms.get_scaled_positions(wrap=False)
369 elif unit == 'au':
370 positions = atoms.get_positions() / Bohr
371 for i, position in enumerate(positions):
372 atoms_speciesandcoordinates[i].extend(position)
374 # Even if 'atoms_speciesandcoordinates_unit' exists, `positions` goes first
375 if parameters.get('atoms_speciesandcoordinates') is not None:
376 atoms_spncrd = parameters['atoms_speciesandcoordinates'].copy()
377 for i in range(len(atoms)):
378 atoms_spncrd[i][2] = atoms_speciesandcoordinates[i][2]
379 atoms_spncrd[i][3] = atoms_speciesandcoordinates[i][3]
380 atoms_spncrd[i][4] = atoms_speciesandcoordinates[i][4]
381 return atoms_spncrd
383 # Appending magnetic moment
384 magmoms = atoms.get_initial_magnetic_moments()
385 for i, magmom in enumerate(magmoms):
386 up_down_spin = get_up_down_spin(magmom, elements[i], xc, data_pth, year)
387 atoms_speciesandcoordinates[i].extend(up_down_spin)
388 # Appending magnetic field Spin magnetic moment theta phi
389 spin_directions = get_spin_direction(magmoms)
390 for i, spin_direction in enumerate(spin_directions):
391 atoms_speciesandcoordinates[i].extend(spin_direction)
392 # Appending magnetic field for Orbital magnetic moment theta phi
393 orbital_directions = get_orbital_direction()
394 for i, orbital_direction in enumerate(orbital_directions):
395 atoms_speciesandcoordinates[i].extend(orbital_direction)
396 # Appending Noncolinear schem switch
397 noncollinear_switches = get_noncollinear_switches()
398 for i, noncollinear_switch in enumerate(noncollinear_switches):
399 atoms_speciesandcoordinates[i].extend(noncollinear_switch)
400 # Appending orbital_enhancement_switch
401 lda_u_switches = get_lda_u_switches()
402 for i, lda_u_switch in enumerate(lda_u_switches):
403 atoms_speciesandcoordinates[i].extend(lda_u_switch)
404 return atoms_speciesandcoordinates
407def get_up_down_spin(magmom, element, xc, data_path, year):
408 magmom = np.linalg.norm(magmom)
409 suffix = get_pseudo_potential_suffix(element, xc, year)
410 filename = os.path.join(data_path, 'VPS/' + suffix + '.vps')
411 valence_electron = float(read_electron_valency(filename))
412 return [valence_electron / 2 + magmom / 2,
413 valence_electron / 2 - magmom / 2]
416def get_spin_direction(magmoms):
417 '''
418 From atoms.magmom, returns the spin direction of phi and theta
419 '''
420 if np.array(magmoms).dtype == float or \
421 np.array(magmoms).dtype is np.float64:
422 return []
423 else:
424 magmoms = np.array(magmoms)
425 return magmoms / np.linalg.norm(magmoms, axis=1)
428def get_orbital_direction():
429 orbital_direction = []
430 # print("Not Implemented Yet")
431 return orbital_direction
434def get_noncollinear_switches():
435 noncolinear_switches = []
436 # print("Not Implemented Yet")
437 return noncolinear_switches
440def get_lda_u_switches():
441 lda_u_switches = []
442 # print("Not Implemented Yet")
443 return lda_u_switches
446def get_spinpol(atoms, parameters):
447 ''' Judgeds the keyword 'scf.SpinPolarization'
448 If the keyword is not None, spinpol gets the keyword by following priority
449 1. standard_spinpol
450 2. scf_spinpolarization
451 3. magnetic moments of atoms
452 '''
453 standard_spinpol = parameters.get('spinpol', None)
454 scf_spinpolarization = parameters.get('scf_spinpolarization', None)
455 m = atoms.get_initial_magnetic_moments()
456 syn = {True: 'On', False: None, 'on': 'On', 'off': None,
457 None: None, 'nc': 'NC'}
458 spinpol = np.any(m >= 0.1)
459 if scf_spinpolarization is not None:
460 spinpol = scf_spinpolarization
461 if standard_spinpol is not None:
462 spinpol = standard_spinpol
463 if isinstance(spinpol, str):
464 spinpol = spinpol.lower()
465 return syn[spinpol]
468def get_atoms_unitvectors(atoms, parameters):
469 zero_vec = np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
470 if np.all(atoms.get_cell() == zero_vec) is True:
471 default_cell = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
472 return parameters.get('atoms_unitvectors', default_cell)
473 unit = parameters.get('atoms_unitvectors_unit', 'ang').lower()
474 if unit == 'ang':
475 atoms_unitvectors = atoms.get_cell()
476 elif unit == 'au':
477 atoms_unitvectors = atoms.get_cell() / Bohr
478 return atoms_unitvectors
481def get_hubbard_u_values(atoms, parameters):
482 return parameters.get('hubbard_u_values', [])
485def get_atoms_cont_orbitals(atoms, parameters):
486 return parameters.get('atoms_cont_orbitals', [])
489def get_md_fixed_xyz(atoms, parameters):
490 return parameters.get('md_fixed_xyz', [])
493def get_md_tempcontrol(atoms, parameters):
494 return parameters.get('md_tempcontrol', [])
497def get_md_init_velocity(atoms, parameters):
498 return parameters.get('md_init_velocity', [])
501def get_band_kpath_unitcell(atoms, parameters):
502 return parameters.get('band_kpath_unitcell', [])
505def get_band_kpath(atoms, parameters):
506 kpts = parameters.get('kpts')
507 if isinstance(kpts, list) and len(kpts) > 3:
508 return get_kpath(kpts=kpts)
509 else:
510 return parameters.get('band_kpath', [])
513def get_mo_kpoint(atoms, parameters):
514 return parameters.get('mo_kpoint', [])
517def get_wannier_initial_projectors(atoms, parameters):
518 """
519 B. Specify the orbital, central position and orientation of a projector
520 Wannier.Initial.Projectos will be used to specify the projector name,
521 local orbital function, center of local orbital, and the local z-axis and
522 x-axis for orbital orientation.
524 An example setting is shown here:
525 wannier_initial_projectors=
526 [['proj1-sp3','0.250','0.250','0.25','-1.0','0.0','0.0','0.0','0.0','-1.0']
527 ,['proj1-sp3','0.000','0.000','0.00','0.0','0.0','1.0','1.0','0.0','0.0']]
528 Goes to,
529 <Wannier.Initial.Projectors
530 proj1-sp3 0.250 0.250 0.250 -1.0 0.0 0.0 0.0 0.0 -1.0
531 proj1-sp3 0.000 0.000 0.000 0.0 0.0 1.0 1.0 0.0 0.0
532 Wannier.Initial.Projectors>
533 """
534 return parameters.get('wannier_initial_projectors', [])
537def get_kpath(self, kpts=None, symbols=None, band_kpath=None, eps=1e-5):
538 """
539 Convert band_kpath <-> kpts. Symbols will be guess automatically
540 by using dft space group method
541 For example,
542 kpts = [(0, 0, 0), (0.125, 0, 0) ... (0.875, 0, 0),
543 (1, 0, 0), (1, 0.0625, 0) .. (1, 0.4375,0),
544 (1, 0.5,0),(0.9375, 0.5,0).. ( ... ),
545 (0.5, 0.5, 0.5) ... ... ,
546 ... ... ... ,
547 ... (0.875, 0, 0),(1.0, 0.0, 0.0)]
548 band_kpath =
549 [['15','0.0','0.0','0.0','1.0','0.0','0.0','g','X'],
550 ['15','1.0','0.0','0.0','1.0','0.5','0.0','X','W'],
551 ['15','1.0','0.5','0.0','0.5','0.5','0.5','W','L'],
552 ['15','0.5','0.5','0.5','0.0','0.0','0.0','L','g'],
553 ['15','0.0','0.0','0.0','1.0','0.0','0.0','g','X']]
554 where, it will be written as
555 <Band.kpath
556 15 0.0 0.0 0.0 1.0 0.0 0.0 g X
557 15 1.0 0.0 0.0 1.0 0.5 0.0 X W
558 15 1.0 0.5 0.0 0.5 0.5 0.5 W L
559 15 0.5 0.5 0.5 0.0 0.0 0.0 L g
560 15 0.0 0.0 0.0 1.0 0.0 0.0 g X
561 Band.kpath>
562 """
563 if kpts is None:
564 kx_linspace = np.linspace(band_kpath[0]['start_point'][0],
565 band_kpath[0]['end_point'][0],
566 band_kpath[0][0])
567 ky_linspace = np.linspace(band_kpath[0]['start_point'][1],
568 band_kpath[0]['end_point'][1],
569 band_kpath[0]['kpts'])
570 kz_linspace = np.linspace(band_kpath[0]['start_point'][2],
571 band_kpath[0]['end_point'][2],
572 band_kpath[0]['kpts'])
573 kpts = np.array([kx_linspace, ky_linspace, kz_linspace]).T
574 for path in band_kpath[1:]:
575 kx_linspace = np.linspace(path['start_point'][0],
576 path['end_point'][0],
577 path['kpts'])
578 ky_linspace = np.linspace(path['start_point'][1],
579 path['end_point'][1],
580 path['kpts'])
581 kz_linspace = np.linspace(path['start_point'][2],
582 path['end_point'][2],
583 path['kpts'])
584 k_lin = np.array([kx_linspace, ky_linspace, kz_linspace]).T
585 kpts = np.append(kpts, k_lin, axis=0)
586 return kpts
587 elif band_kpath is None:
588 band_kpath = []
589 points = np.asarray(kpts)
590 diffs = points[1:] - points[:-1]
591 kinks = abs(diffs[1:] - diffs[:-1]).sum(1) > eps
592 N = len(points)
593 indices = [0]
594 indices.extend(np.arange(1, N - 1)[kinks])
595 indices.append(N - 1)
596 for start, end, s_sym, e_sym in zip(indices[1:], indices[:-1],
597 symbols[1:], symbols[:-1]):
598 band_kpath.append({'start_point': start, 'end_point': end,
599 'kpts': 20,
600 'path_symbols': (s_sym, e_sym)})
601 else:
602 raise KeyError('You should specify band_kpath or kpts')
603 return band_kpath
606def write_string(fd, key, value):
607 fd.write(" ".join([key, value]))
608 fd.write("\n")
611def write_tuple_integer(fd, key, value):
612 fd.write(" ".join([key, "%d %d %d" % value]))
613 fd.write("\n")
616def write_tuple_float(fd, key, value):
617 fd.write(" ".join([key, "%.4f %.4f %.4f" % value]))
618 fd.write("\n")
621def write_tuple_bool(fd, key, value):
622 omx_bl = {True: 'On', False: 'Off'}
623 fd.write(" ".join([key, "%s %s %s" % [omx_bl[bl] for bl in value]]))
624 fd.write("\n")
627def write_integer(fd, key, value):
628 fd.write(" ".join([key, "%d" % value]))
629 fd.write("\n")
632def write_float(fd, key, value):
633 fd.write(" ".join([key, "%.8g" % value]))
634 fd.write("\n")
637def write_bool(fd, key, value):
638 omx_bl = {True: 'On', False: 'Off'}
639 fd.write(" ".join([key, "%s" % omx_bl[value]]))
640 fd.write("\n")
643def write_list_int(fd, key, value):
644 fd.write("".join(key) + ' ' + " ".join(map(str, value)))
647def write_list_bool(fd, key, value):
648 omx_bl = {True: 'On', False: 'Off'}
649 fd.write("".join(key) + ' ' + " ".join([omx_bl[bl] for bl in value]))
652def write_list_float(fd, key, value):
653 fd.write("".join(key) + ' ' + " ".join(map(str, value)))
656def write_matrix(fd, key, value):
657 fd.write('<' + key)
658 fd.write("\n")
659 for line in value:
660 fd.write(" " + " ".join(map(str, line)))
661 fd.write("\n")
662 fd.write(key + '>')
663 fd.write("\n\n")
666def get_openmx_key(key):
667 """
668 For the writing purpose, we need to know Original OpenMX keyword format.
669 By comparing keys in the parameters.py, restore the original key
670 """
671 for openmx_key in keys:
672 for openmx_keyword in openmx_key:
673 if key == get_standard_key(openmx_keyword):
674 return openmx_keyword