Exemple #1
0
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
    ]
Exemple #2
0
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
Exemple #3
0
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)
Exemple #4
0
          '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)