def HEA(f_file, verbose=3): """ Helium approach Calculate porosity using celllist f_file ... file name verbose ... verbosity """ #print('----------------') #print('HEA: calculation') #print('----------------') print('f_file : {}'.format(f_file)) t1 = time.time() # read the structure struct = read(f_file) p_framework = struct.get_positions() s_framework = struct.get_chemical_symbols() cell = struct.get_cell() Lx = numpy.linalg.norm(cell[:][0, :]) Ly = numpy.linalg.norm(cell[:][1, :]) Lz = numpy.linalg.norm(cell[:][2, :]) # Guess for M M0 = get_M(Lx=Lx, Ly=Ly, Lz=Lz, m='high') # Optimize d for M0 dopt = get_opt_r(Lx=Lx, Ly=Ly, Lz=Lz, Mx=M0[0], My=M0[1], Mz=M0[2]) # Optimize M for dopt M = get_M(Lx=Lx, Ly=Ly, Lz=Lz, m='high', d=dopt) Mx, My, Mz = M # Celllist = get_subcells(cell, M, p_framework) # Get COMs of Celllist p_insert = get_COMs_celllist(cell, M) # Species we are inserting s_insert = ['He'] * len(p_insert) # Remove atoms an the insertion grid overlapping with the framework ropt = dopt / 2. print('r_opt: {:10.5f} A'.format(ropt)) p_insert_red, s_insert_red = prune_points(p_framework=p_framework, p_insert=p_insert, s_framework=s_framework, s_insert=s_insert, r_i=ropt) # Calculate number of atoms N_insert = len(p_insert) N_insert_red = len(p_insert_red) P_points = N_insert_red / N_insert print('N_insert: {:10d}'.format(N_insert)) print('N_insert_reduced: {:10d}'.format(N_insert_red)) # Calculate volumes struct_subcell = Atoms(cell=cell) cell_subcell = struct_subcell.get_cell() cell_subcell[:][0, :] = cell_subcell[:][0, :] / Mx cell_subcell[:][1, :] = cell_subcell[:][1, :] / My cell_subcell[:][2, :] = cell_subcell[:][2, :] / Mz struct_subcell.set_cell(cell_subcell) V_subcell = struct_subcell.get_volume() * N_insert_red V_insert = 4 / 3. * numpy.pi * ropt**3. * N_insert_red V_framework = struct.get_volume() P_subcell = V_subcell / V_framework print('optimal M: {:10d} {:10d} {:10d}'.format(Mx, My, Mz)) # simple cubic packing f_sc = 0.52 f_calc = V_insert / V_subcell print('------------------') print('packing fraction f') print('------------------') print('f_sc: {:15.5f}'.format(f_sc)) print('f_calc: {:15.5f}'.format(f_calc)) P_volume = V_insert / (V_framework * f_calc) print('----------------------') print('HEA porosity P [%]') print('----------------------') print('P_subcell: {:15.5f}'.format(P_subcell * 100.0)) print('P_points: {:15.5f}'.format(P_points * 100.0)) print('P_volume: {:15.5f}'.format(P_volume * 100.0)) print('---------------') print(' Volume V [A^3]') print('---------------') print('V_framework: {:15.5f}'.format(V_framework)) print('V_subcell: {:15.5f}'.format(V_subcell)) print('V_He: {:15.5f}'.format(V_insert)) t2 = time.time() print('Total CPU time: {:15.5f} s'.format(t2 - t1)) print('\n') if verbose > 3: get_ase(f_file, p_insert_red, s_insert_red) return [ P_points * 100.0, P_subcell * 100.0, P_volume * 100.0, V_framework, V_subcell, V_insert, N_insert, N_insert_red, f_calc, ropt ]
class execution(object): def __init__(self, executionInput, xyz=None, stateFile='state.json'): ''' Setup a new execution Name: input file xyz: xyz coordinates (for future automated execution) stateFile: state file to use for tracking of executions TODO: - only ground state in non-periodic cell supported NOW, more to add! - inputs from a dict to better handle automated executions ''' if isinstance(executionInput, str): self.inp = self.json(executionInput) self.inputFileName = executionInput if isinstance(executionInput, dict): self.inp = executionInput self.inputFileName = 'dict' # TODO: generate meaningful name here (how?) self.setup() def setup(self): '''setup''' self.functional = self.inp.get('functional') or 'LDA' self.runtype = self.inp.get('runtype') or 'calc' # this actually can't be none! _xyz = self.inp.get('xyz') if isinstance(_xyz, str): self.inputXYZ = _xyz self.atoms = read(self.inputXYZ) else: # support reading frm a dict (TODO: other type of objects - ?) from ase.atoms import Atoms from ase.atom import Atom self.atoms = \ Atoms([Atom(a[0],(a[1],a[2],a[3])) for a in _xyz]) # TODO: support multiple cell types self.atoms.cell = (self.inp['cell']['x'], self.inp['cell']['y'], self.inp['cell']['z']) # Mixer setup - only "broyden" supported self.mixer = self.inp.get('mixer') if self.mixer is None: self.mixer = Mixer else: self.mixer = BroydenMixer # Custom ID: allow to trace parameter set using a custom id self.custom_id = self.inp.get('custom_id') # Periodic Boundary Conditions self.atoms.pbc = False # This should not be done always self.atoms.center() self.nbands = self.inp.get('nbands') self.gpts = None self.setup_gpts() self.max_iterations = self.inp.get('maxiter') or 333 # Name: to be set by __str__ first time it is run self.name = None # self.logExtension = 'txt' self.dataExtension = 'gpw' # Timing / statistics self.lastElapsed = None # def get_optimizer(self, name='QuasiNewton'): from importlib import import_module name = name.lower() _optimMap = \ { 'mdmin': 'MDMin', 'hesslbfgs': 'HessLBFGS', 'linelbfgs': 'LineLBFGS', 'fire': 'FIRE', 'lbfgs': 'LBFGS', 'lbfgsls': 'LBFGSLineSearch', 'bfgsls': 'BFGSLineSearch', 'bfgs': 'BFGS', 'quasinewton': 'QuasiNewton' } _class = _optimMap[name] _m = import_module('ase.optimize') return getattr(_m, _class) # def setup_gpts(self): self.gpts = h2gpts(self.inp.get('spacing') or 0.20, self.atoms.get_cell(), idiv=self.inp.get('idiv') or 8) def filename(self, force_id=None, extension='txt'): '''to correctly support this: stateFile support must be completed as it isn't just add "_0" to __str__() for now ''' base = self.__str__() if self.custom_id is not None: base = base + '_' + self.custom_id if force_id is None: _fn = base + '_0.' + extension else: _fn = '{}_{}.{}'.format(base, force_id, extension) return _fn # @property def xyz(self): return self.inp['xyz'] # @property def spacegroup(self): '''international ID of determined spacegroup''' sg = spglib.get_symmetry_dataset(spglib.refine_cell( self.atoms))['international'] return sg.replace('/', ':') # def __str__(self): '''get execution name - to be used for log filename Components: - Number atoms - Volume - Spacegroup number - Functional name ''' if self.name is None: self.name = '{}_{}_{}_{}'.format( len(self.atoms), int(self.atoms.get_volume() * 100), self.spacegroup, self.functional) _gpaw = os.environ['GPAW'] _pwd = os.environ['PWD'] self.procname = '{} ({})'.format(self.name, _pwd.replace(_gpaw + '/', '')) setproctitle(self.procname) return self.name ## def print(self, *args, **kwargs): '''print wrapper - initial step before logger''' r = print(*args, *kwargs) return r # def pretty(self): '''pretty print original parameters''' _p = pformat(self.inp) self.print(_p) # def json(self, filename): '''load parameters from json''' with open(filename, 'rb') as f: s = f.read() j = json.loads(s) return j # def run(self, force_id=None, runtype=None): ''' perform execution - only calc or optim supported now ''' _lastStart = time.time() if runtype is None and self.runtype is 'calc': _f = self.calc else: _f = self.optim # calculate try: result = _f(force_id) finally: _lastEnd = time.time() self.lastElapsed = _lastEnd - _lastStart return result # def calc(self, force_id=None, functional=None): '''prepare and launch execution force_id: use this id for filename generation ''' # Allow to override the funtional _fnl = functional or self.functional # generate filenames _fn = self.filename(force_id) _dn = self.filename(force_id, extension=self.dataExtension) self.print('Calculation with {} log and Input: {}.'.format( _fn, self.inputFileName)) if self.nbands is None: _calc = GPAW(xc=_fnl, txt=self.filename(force_id), mixer=self.mixer(), maxiter=self.max_iterations, gpts=self.gpts) else: _calc = GPAW(xc=_fnl, txt=self.filename(force_id), nbands=self.nbands, mixer=self.mixer(), maxiter=self.max_iterations, gpts=self.gpts) self.atoms.set_calculator(_calc) self.atoms.get_potential_energy() # write out wavefunctions _calc.write(_dn, 'all') return _calc ##### def optim(self, force_id=None, functional=None): '''prepare and launch execution force_id: use this id for filename generation ''' _optim_name = self.inp.get('optimizer') or 'QuasiNewton' optimizer = self.get_optimizer(_optim_name) # Allow to override the funtional _fnl = functional or self.functional # generate filenames _fn = self.filename(force_id) _dn = self.filename(force_id, extension=self.dataExtension) self.print('Optimization with {} log and Input: {}.'.format( _fn, self.inputFileName)) if self.nbands is None: _calc = GPAW(xc=_fnl, txt=self.filename(force_id), mixer=self.mixer(), maxiter=self.max_iterations, gpts=self.gpts) else: _calc = GPAW(xc=_fnl, txt=self.filename(force_id), nbands=self.nbands, mixer=self.mixer(), maxiter=self.max_iterations, gpts=self.gpts) self.atoms.set_calculator(_calc) self.opt = optimizer(self.atoms, trajectory=self.__str__() + '_emt.traj') self.opt.run(fmax=0.05) # write out wavefunctions _calc.write(_dn, 'all') return _calc
class TestCalculator_SW_Potential(quippytest.QuippyTestCase): def setUp(self): self.xml = """ <SW_params n_types="2" label="PRB_31_plus_H"> <comment> Stillinger and Weber, Phys. Rev. B 31 p 5262 (1984), extended for other elements </comment> <per_type_data type="1" atomic_num="1" /> <per_type_data type="2" atomic_num="14" /> <per_pair_data atnum_i="1" atnum_j="1" AA="0.0" BB="0.0" p="0" q="0" a="1.0" sigma="1.0" eps="0.0" /> <per_pair_data atnum_i="1" atnum_j="14" AA="8.581214" BB="0.0327827" p="4" q="0" a="1.25" sigma="2.537884" eps="2.1672" /> <per_pair_data atnum_i="14" atnum_j="14" AA="7.049556277" BB="0.6022245584" p="4" q="0" a="1.80" sigma="2.0951" eps="2.1675" /> <!-- triplet terms: atnum_c is the center atom, neighbours j and k --> <per_triplet_data atnum_c="1" atnum_j="1" atnum_k="1" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="1" atnum_j="1" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="1" atnum_j="14" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="14" atnum_j="1" atnum_k="1" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="14" atnum_j="1" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> <per_triplet_data atnum_c="14" atnum_j="14" atnum_k="14" lambda="21.0" gamma="1.20" eps="2.1675" /> </SW_params> """ quippy.system_module.system_reseed_rng(2065775975) self.pot_calculator = Potential('IP SW', param_str=self.xml) self.at = Atoms('Si8', positions=diamond_pos, pbc=True, cell=[5.44, 5.44, 5.44]) self.f = np.zeros((3, len(self.at)), order='F') self.df = np.zeros((3, len(self.at)), order='F') self.v = np.zeros((3, 3), order='F') self.energy_ref = -34.5038375509 self.forces_ref = np.array([[0.89920374, -0.38025157, -0.38727027], [0.36623356, -0.52403757, 0.7200206], [-0.36952654, 0.12899529, 0.00458111], [-0.19912365, -0.1632057, 1.08509495], [-0.67565314, -0.59410498, -0.47921521], [0.17097454, 0.5847822, -0.31088749], [0.43613712, 0.90811269, 0.1600328], [-0.62824563, 0.03970963, -0.79235649]]) self.virial_ref = np.array([[-0.34103601, 0.60925144, -0.02138795], [0.60925144, -0.36145702, -0.19375487], [-0.02138795, -0.19375487, -0.34640615]]).T # Voigt notation by hand from virial self.stress_ref = -np.array([ -0.34103601, -0.36145702, -0.34640615, -0.19375487, -0.02138795, 0.60925144 ]) / self.at.get_volume() self.at.set_calculator(self.pot_calculator) def test_energy(self): self.assertAlmostEqual(self.at.get_potential_energy(), self.energy_ref) def test_forces(self): self.assertArrayAlmostEqual(self.at.get_forces(), self.forces_ref, tol=1E-06) def test_stress(self): self.assertArrayAlmostEqual(self.at.get_stress(), self.stress_ref) def test_virial(self): self.assertArrayAlmostEqual(self.pot_calculator.get_virial(self.at), self.virial_ref, tol=1E-06) def test_calc_args_1(self): self.pot_calculator.calculate(self.at, propertes=["forces"], calc_args="do_rescale_E E_scale=1.01") f = self.pot_calculator.results['forces'] self.assertArrayAlmostEqual(f, self.forces_ref * 1.01, tol=1E-06) def test_calc_args_2(self): self.pot_calculator.calculate(self.at, properties=["forces"], do_rescale_E=True, E_scale=1.01) f = self.pot_calculator.results['forces'] self.assertArrayAlmostEqual(f, self.forces_ref * 1.01, tol=1E-06) def test_calc_args_3(self): pot2 = Potential('IP SW', param_str=self.xml, calc_args="do_rescale_E E_scale=1.01") f = pot2.get_forces(self.at) self.assertArrayAlmostEqual(f, self.forces_ref * 1.01, tol=1E-06) def test_calc_args_4(self): pot2 = Potential('IP SW', param_str=self.xml, calc_args={ 'do_rescale_E': True, 'E_scale': 1.01 }) f = pot2.get_forces(self.at) self.assertArrayAlmostEqual(f, self.forces_ref * 1.01, tol=1E-06)
'sme/method': 'fermi_dirac', 'ELECTRONIC_TEMPERATURE': 300, 'DIA/ALGORITHM': 'STANDARD', 'mix/METHOD': 'BROYDEN_MIXING', 'ALPHA': 0.1, 'BETA': 1.5, 'NBUFFER': 8, 'cpu': 24, 'cutoff': 300, 'run_type': 'cell_opt', 'atoms': atoms, } calc = CP2K(**kwargs) atoms.set_calculator(calc) s = time.time() e = atoms.get_potential_energy() t = time.time() - s v = atoms.get_volume() print('*=================================================*') print('volume time energy (eV)') print('{0:1.2f} {1:1.1f} {2:1.4f} '.format(v, t, e)) print('cell:') print(atoms.cell)