Exemplo n.º 1
0
    def calculate(self,
                  atoms=None,
                  properties=['energy'],
                  system_changes=all_changes):
        bad = [
            change for change in system_changes
            if change not in self.supported_changes
        ]

        if self.calculator_initialized and any(bad):
            raise PropertyNotImplementedError(
                'Cannot change {} through IPI protocol.  '
                'Please create new socket calculator.'.format(
                    bad if len(bad) > 1 else bad[0]))

        self.calculator_initialized = True

        if self.server is None:
            assert self.calc is not None
            cmd = self.calc.command.replace('PREFIX', self.calc.prefix)
            self.calc.write_input(atoms,
                                  properties=properties,
                                  system_changes=system_changes)
            self.launch_server(cmd)

        self.atoms = atoms.copy()
        results = self.server.calculate(atoms)
        virial = results.pop('virial')
        if self.atoms.number_of_lattice_vectors == 3 and any(self.atoms.pbc):
            from ase.constraints import full_3x3_to_voigt_6_stress
            vol = atoms.get_volume()
            results['stress'] = -full_3x3_to_voigt_6_stress(virial) / vol
        self.results.update(results)
Exemplo n.º 2
0
 def adjust_stress(self, atoms, stress):
     # symmetrize stress as rank 2 tensor
     raw_stress = voigt_6_to_full_3x3_stress(stress)
     symmetrized_stress = symmetrize_rank2(atoms.get_cell(),
                                           atoms.get_reciprocal_cell().T,
                                           raw_stress, self.rotations)
     stress[:] = full_3x3_to_voigt_6_stress(symmetrized_stress)
Exemplo n.º 3
0
    def get_forces(self, apply_constraint=False):
        atoms_forces = self.atoms.get_forces()

        # Now, adjust forces:
        constraint_forces = -atoms_forces
        old = self.atoms.get_positions()
        oldcell = self.atoms.get_cell()
        masses = self.atoms.get_masses()
        for i in range(self.maxiter):
            converged = True
            for j, ab in enumerate(self.pairs):
                a = ab[0]
                b = ab[1]
                cd = self.bondlengths[j]
                d = old[a] - old[b]
                d = find_mic([d], oldcell, self.atoms._pbc)[0][0]
                dv = atoms_forces[a] / masses[a] - atoms_forces[b] / masses[b]
                m = 1 / (1 / masses[a] + 1 / masses[b])
                x = -np.dot(dv, d) / cd**2
                if abs(x) > self.tolerance or np.isnan(x) or np.isinf(x):
                    atoms_forces[a] += x * m * d
                    atoms_forces[b] -= x * m * d
                    converged = False
            if converged:
                break
        else:
            raise RuntimeError('Did not converge')
        constraint_forces += atoms_forces

        stress = self.atoms.get_stress()
        volume = self.atoms.get_volume()
        virial = -volume * voigt_6_to_full_3x3_stress(stress)
        atoms_forces = np.dot(atoms_forces, self.deform_grad)
        dg_inv = np.linalg.inv(self.deform_grad)
        virial = np.dot(virial, dg_inv.T)

        if self.hydrostatic_strain:
            vtr = virial.trace()
            virial = np.diag([vtr / 3.0, vtr / 3.0, vtr / 3.0])

        # Zero out components corresponding to fixed lattice elements
        if (self.mask != 1.0).any():
            virial *= self.mask

        if self.constant_volume:
            vtr = virial.trace()
            np.fill_diagonal(virial, np.diag(virial) - vtr / 3.0)

        natoms = len(self.atoms)
        forces = np.zeros((natoms + 3, 3))
        forces[:natoms] = atoms_forces
        forces[natoms:] = virial / self.cell_factor

        self.stress = -full_3x3_to_voigt_6_stress(virial) / volume
        return forces
Exemplo n.º 4
0
 def calculate(self, atoms, properties, system_changes):
     Calculator.calculate(self, atoms, properties, system_changes)
     julia_atoms = ASEAtoms(atoms)
     julia_atoms = convert(julia_atoms)
     self.results = {}
     if 'energy' in properties:
         self.results['energy'] = energy(self.julip_calculator, julia_atoms)
     if 'forces' in properties:
         self.results['forces'] = np.array(
             forces(self.julip_calculator, julia_atoms))
     if 'stress' in properties:
         voigt_stress = full_3x3_to_voigt_6_stress(
             np.array(stress(self.julip_calculator, julia_atoms)))
         self.results['stress'] = voigt_stress
Exemplo n.º 5
0
def test_stress():
    # build a water dimer, which has 6 atoms
    water1 = molecule('H2O')
    water2 = molecule('H2O')
    water2.positions[:, 0] += 5.0
    atoms = water1 + water2
    atoms.cell = [10, 10, 10]
    atoms.pbc = True

    atoms.new_array('stress', np.arange(6, dtype=float))  # array with clashing name
    atoms.calc = EMT()
    a_stress = atoms.get_stress()
    atoms.write('tmp.xyz')
    b = ase.io.read('tmp.xyz')
    assert abs(b.get_stress() - a_stress).max() < 1e-6
    assert abs(b.arrays['stress'] - np.arange(6, dtype=float)).max() < 1e-6
    b_stress = b.info['stress']
    assert abs(full_3x3_to_voigt_6_stress(b_stress) - a_stress).max() < 1e-6
Exemplo n.º 6
0
 def calculate(self, atoms, properties, system_changes):
      Calculator.calculate(self, atoms, properties, system_changes)
      if system_changes:
          self.results = {}
      if 'energy' in properties and 'energy' not in self.results:
          self.results['energy'] = self.calc.get_potential_energy(atoms)
          self.results['free_energy'] = self.results['energy']
      if 'forces' in properties and 'forces' not in self.results:
          raw_forces = self.calc.get_forces(atoms)
          self.results['forces'] = forces(atoms.get_cell(), atoms.get_reciprocal_cell().T, raw_forces,
              self.rotations, self.translations, self.symm_map)
      if 'stress' in properties and 'stress' not in self.results:
          raw_stress = self.calc.get_stress(atoms)
          print(raw_stress)
          if len(raw_stress) == 6: # Voigt
              raw_stress = voigt_6_to_full_3x3_stress(raw_stress)
          symmetrized_stress = stress(atoms.get_cell(), atoms.get_reciprocal_cell().T, raw_stress, self.rotations)
          self.results['stress'] = full_3x3_to_voigt_6_stress(symmetrized_stress)
Exemplo n.º 7
0
    def calculate(self, atoms=None, properties=['energy'],
                  system_changes=all_changes):
        
        bad = [change for change in system_changes
               if change not in self.supported_changes]

        if self.calculator_initialized and any(bad):
            raise PropertyNotImplementedError(
                'Cannot change {} through IPI protocol.  '
                'Please create new socket calculator.'
                .format(bad if len(bad) > 1 else bad[0]))

        self.calculator_initialized = True

        if self.server is None:
            #if 'vc' in self.calculation:
            #    self.cell_factor = 10
            #self.calculation = 'scf'
            self.cell_dynamics = 'ipi'
            self.ion_dynamics = 'ipi'
            self.dontcalcforces = False
                    
            self.write_input(atoms, properties=properties,
                                  system_changes=system_changes)
            
            if self._socket_type=='UNIX' or ((not self._unixsocket and not self._port) and self._socket_type!='INET'):
                self._socket_type = 'UNIX'
                if not self._unixsocket:
                    self._unixsocket = self.scratch.split('/')[-1]
                socket_string = ' --ipi {0}:UNIX >> {1}'.format(self._unixsocket,self.log)
            elif self._socket_type=='INET' or (not self._unixsocket and self._port):
                self._socket_type = 'INET'
                port = SocketServer.default_port
                SocketServer.default_port += 1
                while socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex(('localhost', port)) == 0:
                    port += 1
                self._port = port
                if re.match('^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$', self.ionode_address):
                    self._ip = self.ionode_address
                elif self.ionode_address in self.site.nic_inet_ips.keys():
                    self._ip = self.site.nic_inet_ips[self.ionode_address]
                else:
                    raise Exception('Not a valida IPV4 address or NIC interface: {}'.format(self.ionode_address))
                socket_string = ' --ipi {0}:{1} >> {2}'.format(self._ip,self._port,self.log)
            else:
                raise Exception('Socket type: {} not implemented.'.format(self._socket_type))
            if self.socket_log:
                print(self._socket_type,file=self.socket_log)
            cmd = ' '.join(self.command) + socket_string

            self.launch_server(cmd)

        results = self.server.calculate(atoms,properties)
        
        if 'virial' in results.keys():
            if self.atoms.number_of_lattice_vectors == 3 and any(self.atoms.pbc):
                from ase.constraints import full_3x3_to_voigt_6_stress
                vol = atoms.get_volume()
                results['stress'] = -full_3x3_to_voigt_6_stress(results['virial']) / vol
            else:
                raise Exception('Stress calculation: cell and periodic boundary conditions must be defined.')
        self.results.update(results)
Exemplo n.º 8
0
    def calculate(
        self,
        atoms=None,
        properties=None,
        system_changes=all_changes,
    ):
        if properties is None:
            properties = self.implemented_properties

        Calculator.calculate(self, atoms, properties, system_changes)

        natoms = len(self.atoms)

        sigma = self.parameters.sigma
        epsilon = self.parameters.epsilon
        rc = self.parameters.rc

        if self.nl is None or 'numbers' in system_changes:
            self.nl = NeighborList([rc / 2] * natoms, self_interaction=False)

        self.nl.update(self.atoms)

        positions = self.atoms.positions
        cell = self.atoms.cell

        # potential value at rc
        e0 = 4 * epsilon * ((sigma / rc)**12 - (sigma / rc)**6)

        energies = np.zeros(natoms)
        forces = np.zeros((natoms, 3))
        stresses = np.zeros((natoms, 3, 3))

        for ii in range(natoms):
            neighbors, offsets = self.nl.get_neighbors(ii)
            cells = np.dot(offsets, cell)

            # pointing *towards* neighbours
            distance_vectors = positions[neighbors] + cells - positions[ii]

            r2 = (distance_vectors**2).sum(1)
            c6 = (sigma**2 / r2)**3
            c6[r2 > rc**2] = 0.0
            c12 = c6**2

            pairwise_energies = 4 * epsilon * (c12 - c6) - e0 * (c6 != 0.0)
            energies[ii] += 0.5 * pairwise_energies.sum()  # atomic energies

            pairwise_forces = (-24 * epsilon * (2 * c12 - c6) /
                               r2)[:, np.newaxis] * distance_vectors

            forces[ii] += pairwise_forces.sum(axis=0)
            stresses[ii] += 0.5 * np.dot(
                pairwise_forces.T,
                distance_vectors)  # equivalent to outer product

            # add j < i contributions
            for jj, atom_j in enumerate(neighbors):
                energies[atom_j] += 0.5 * pairwise_energies[jj]
                forces[atom_j] += -pairwise_forces[jj]  # f_ji = - f_ij
                stresses[atom_j] += 0.5 * np.outer(pairwise_forces[jj],
                                                   distance_vectors[jj])

        # no lattice, no stress
        if self.atoms.number_of_lattice_vectors == 3:
            stresses = full_3x3_to_voigt_6_stress(stresses)
            self.results['stress'] = (stresses.sum(axis=0) /
                                      self.atoms.get_volume())
            self.results['stresses'] = stresses / self.atoms.get_volume()

        energy = energies.sum()
        self.results['energy'] = energy
        self.results['energies'] = energies

        self.results['free_energy'] = energy

        self.results['forces'] = forces
Exemplo n.º 9
0
Arquivo: lj.py Projeto: arosen93/rASE
    def calculate(
        self,
        atoms=None,
        properties=None,
        system_changes=all_changes,
    ):
        if properties is None:
            properties = self.implemented_properties

        Calculator.calculate(self, atoms, properties, system_changes)

        natoms = len(self.atoms)

        sigma = self.parameters.sigma
        epsilon = self.parameters.epsilon
        rc = self.parameters.rc
        ro = self.parameters.ro
        smooth = self.parameters.smooth

        if self.nl is None or 'numbers' in system_changes:
            self.nl = NeighborList([rc / 2] * natoms,
                                   self_interaction=False,
                                   bothways=True)

        self.nl.update(self.atoms)

        positions = self.atoms.positions
        cell = self.atoms.cell

        # potential value at rc
        e0 = 4 * epsilon * ((sigma / rc)**12 - (sigma / rc)**6)

        energies = np.zeros(natoms)
        forces = np.zeros((natoms, 3))
        stresses = np.zeros((natoms, 3, 3))

        for ii in range(natoms):
            neighbors, offsets = self.nl.get_neighbors(ii)
            cells = np.dot(offsets, cell)

            # pointing *towards* neighbours
            distance_vectors = positions[neighbors] + cells - positions[ii]

            r2 = (distance_vectors**2).sum(1)
            c6 = (sigma**2 / r2)**3
            c6[r2 > rc**2] = 0.0
            c12 = c6**2

            if smooth:
                cutoff_fn = cutoff_function(r2, rc**2, ro**2)
                d_cutoff_fn = d_cutoff_function(r2, rc**2, ro**2)

            pairwise_energies = 4 * epsilon * (c12 - c6)
            pairwise_forces = -24 * epsilon * (2 * c12 - c6) / r2  # du_ij

            if smooth:
                # order matters, otherwise the pairwise energy is already modified
                pairwise_forces = (cutoff_fn * pairwise_forces +
                                   2 * d_cutoff_fn * pairwise_energies)
                pairwise_energies *= cutoff_fn
            else:
                pairwise_energies -= e0 * (c6 != 0.0)

            pairwise_forces = pairwise_forces[:, np.newaxis] * distance_vectors

            energies[ii] += 0.5 * pairwise_energies.sum()  # atomic energies
            forces[ii] += pairwise_forces.sum(axis=0)

            stresses[ii] += 0.5 * np.dot(
                pairwise_forces.T,
                distance_vectors)  # equivalent to outer product

        # no lattice, no stress
        if self.atoms.cell.rank == 3:
            stresses = full_3x3_to_voigt_6_stress(stresses)
            self.results['stress'] = stresses.sum(
                axis=0) / self.atoms.get_volume()
            self.results['stresses'] = stresses / self.atoms.get_volume()

        energy = energies.sum()
        self.results['energy'] = energy
        self.results['energies'] = energies

        self.results['free_energy'] = energy

        self.results['forces'] = forces