Skip to content

Commit

Permalink
Merge pull request #8 from chrisjsewell/test-force
Browse files Browse the repository at this point in the history
replace `generate_LAMMPS_structure` function and add more tests
  • Loading branch information
abelcarreras authored Jun 19, 2019
2 parents b1f980f + 56c427d commit 73ff49d
Show file tree
Hide file tree
Showing 17 changed files with 637 additions and 143 deletions.
2 changes: 1 addition & 1 deletion aiida_lammps/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.0b3"
__version__ = "0.3.0b3"
106 changes: 28 additions & 78 deletions aiida_lammps/calculations/lammps/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from aiida.engine import CalcJob
from aiida.common import InputValidationError
from aiida.common import CalcInfo, CodeInfo
from aiida.orm import StructureData, Dict
from aiida.plugins import DataFactory
from aiida_lammps.common.utils import convert_date_string
from aiida_lammps.common.generate_structure import generate_lammps_structure
from aiida_lammps.data.potential import EmpiricalPotential
import six

Expand Down Expand Up @@ -38,9 +38,9 @@ def get_FORCE_CONSTANTS_txt(force_constants):
fc_txt = "%4d\n" % (fc_shape[0])
for i in range(fc_shape[0]):
for j in range(fc_shape[1]):
fc_txt += "%4d%4d\n" % (i+1, j+1)
fc_txt += "%4d%4d\n" % (i + 1, j + 1)
for vec in force_constants[i][j]:
fc_txt +=("%22.15f"*3 + "\n") % tuple(vec)
fc_txt += ("%22.15f" * 3 + "\n") % tuple(vec)

return fc_txt

Expand All @@ -55,8 +55,8 @@ def structure_to_poscar(structure):
cell = structure.cell
for row in cell:
poscar += '{0: 22.16f} {1: 22.16f} {2: 22.16f}\n'.format(*row)
poscar += ' '.join(np.unique([site.kind_name for site in structure.sites]))+'\n'
poscar += ' '.join(np.array(labels, dtype=str))+'\n'
poscar += ' '.join(np.unique([site.kind_name for site in structure.sites])) + '\n'
poscar += ' '.join(np.array(labels, dtype=str)) + '\n'
poscar += 'Cartesian\n'
for site in structure.sites:
poscar += '{0: 22.16f} {1: 22.16f} {2: 22.16f}\n'.format(*site.position)
Expand All @@ -83,73 +83,11 @@ def parameters_to_input_file(parameters_object):
return input_file


def generate_LAMMPS_structure(structure, atom_style):
import numpy as np

types = [site.kind_name for site in structure.sites]

type_index_unique = np.unique(types, return_index=True)[1]
count_index_unique = np.diff(np.append(type_index_unique, [len(types)]))

atom_index = []
for i, index in enumerate(count_index_unique):
atom_index += [i for j in range(index)]

masses = [site.mass for site in structure.kinds]
positions = [site.position for site in structure.sites]

number_of_atoms = len(positions)

lammps_data_file = 'Generated using dynaphopy\n\n'
lammps_data_file += '{0} atoms\n\n'.format(number_of_atoms)
lammps_data_file += '{0} atom types\n\n'.format(len(masses))

cell = np.array(structure.cell)

a = np.linalg.norm(cell[0])
b = np.linalg.norm(cell[1])
c = np.linalg.norm(cell[2])

alpha = np.arccos(np.dot(cell[1], cell[2])/(c*b))
gamma = np.arccos(np.dot(cell[1], cell[0])/(a*b))
beta = np.arccos(np.dot(cell[2], cell[0])/(a*c))

xhi = a
xy = b * np.cos(gamma)
xz = c * np.cos(beta)
yhi = np.sqrt(pow(b,2)- pow(xy,2))
yz = (b*c*np.cos(alpha)-xy * xz)/yhi
zhi = np.sqrt(pow(c,2)-pow(xz,2)-pow(yz,2))

xhi = xhi + max(0,0, xy, xz, xy+xz)
yhi = yhi + max(0,0, yz)

lammps_data_file += '\n{0:20.10f} {1:20.10f} xlo xhi\n'.format(0, xhi)
lammps_data_file += '{0:20.10f} {1:20.10f} ylo yhi\n'.format(0, yhi)
lammps_data_file += '{0:20.10f} {1:20.10f} zlo zhi\n'.format(0, zhi)
lammps_data_file += '{0:20.10f} {1:20.10f} {2:20.10f} xy xz yz\n\n'.format(xy, xz, yz)

lammps_data_file += 'Masses\n\n'

for i, mass in enumerate(masses):
lammps_data_file += '{0} {1:20.10f} \n'.format(i+1, mass)

lammps_data_file += '\nAtoms\n\n'
for i, row in enumerate(positions):
if atom_style == 'charge':
# TODO variable initial charge
lammps_data_file += '{0} {1} 0.0 {2:20.10f} {3:20.10f} {4:20.10f}\n'.format(i+1, atom_index[i]+1, row[0],row[1],row[2])
else:
lammps_data_file += '{0} {1} {2:20.10f} {3:20.10f} {4:20.10f}\n'.format(i+1, atom_index[i]+1, row[0],row[1],row[2])

return lammps_data_file


def generate_LAMMPS_potential(pair_style):

potential_file = '# Potential file generated by aiida plugin (please check citation in the orignal file)\n'
for key, value in pair_style.dict.data.iteritems():
potential_file += '{} {}\n'.format(key, value)
potential_file += '{} {}\n'.format(key, value)

return potential_file

Expand All @@ -175,22 +113,28 @@ class BaseLammpsCalculation(CalcJob):
def define(cls, spec):
super(BaseLammpsCalculation, cls).define(spec)
spec.input('structure', valid_type=StructureData, help='the structure')
spec.input('potential', valid_type=EmpiricalPotential, help='lammps potential')
spec.input('parameters', valid_type=Dict, help='the parameters', required=False, default=Dict())
spec.input('metadata.options.output_filename', valid_type=six.string_types, default=cls._OUTPUT_FILE_NAME)
spec.input('potential', valid_type=EmpiricalPotential,
help='lammps potential')
spec.input('parameters', valid_type=Dict,
help='the parameters', required=False)
spec.input('metadata.options.output_filename',
valid_type=six.string_types, default=cls._OUTPUT_FILE_NAME)

spec.default_output_port = 'results'
spec.output('results',
valid_type=DataFactory('dict'),
required=True,
help='the data extracted from the main output file')
spec.default_output_node = 'results'

# TODO review aiidateam/aiida_core#2997, when closed, for exit code formalization

# Unrecoverable errors: resources like the retrieved folder or its expected contents are missing
spec.exit_code(
200, 'ERROR_NO_RETRIEVED_FOLDER',
message='The retrieved folder data node could not be accessed.')
spec.exit_code(
201, 'ERROR_NO_RETRIEVED_TEMP_FOLDER',
message='The retrieved temporary folder data node could not be accessed.')
spec.exit_code(
210, 'ERROR_OUTPUT_FILE_MISSING',
message='the main output file was not found')
Expand Down Expand Up @@ -220,7 +164,6 @@ def prepare_extra_files(self, tempfolder, potential_object):
return True

def prepare_for_submission(self, tempfolder):

"""Create the input files from the input nodes passed to this instance of the `CalcJob`.
:param tempfolder: an `aiida.common.folders.Folder` to temporarily write files on disk
Expand All @@ -231,14 +174,20 @@ def prepare_for_submission(self, tempfolder):
potential_txt = self.inputs.potential.get_potential_file()

# Setup structure
structure_txt = generate_LAMMPS_structure(self.inputs.structure,
structure_txt = generate_lammps_structure(self.inputs.structure,
self.inputs.potential.atom_style)

if "parameters" in self.inputs:
parameters = self.inputs.parameters
else:
parameters = Dict()

# Check lammps version date in parameters
lammps_date = convert_date_string(self.inputs.parameters.get_dict().get("lammps_version", '11 Aug 2017'))
lammps_date = convert_date_string(
parameters.get_dict().get("lammps_version", '11 Aug 2017'))

# Setup input parameters
input_txt = self._generate_input_function(self.inputs.parameters,
input_txt = self._generate_input_function(parameters,
self.inputs.potential,
self._INPUT_STRUCTURE,
self._OUTPUT_TRAJECTORY_FILE_NAME,
Expand All @@ -249,7 +198,7 @@ def prepare_for_submission(self, tempfolder):
with open(input_filename, 'w') as infile:
infile.write(input_txt)

self.validate_parameters(self.inputs.parameters, self.inputs.potential)
self.validate_parameters(parameters, self.inputs.potential)

# prepare extra files if needed
self.prepare_extra_files(tempfolder, self.inputs.potential)
Expand All @@ -261,7 +210,8 @@ def prepare_for_submission(self, tempfolder):
infile.write(structure_txt)

if potential_txt is not None:
potential_filename = tempfolder.get_abs_path(self.inputs.potential.potential_filename)
potential_filename = tempfolder.get_abs_path(
self.inputs.potential.potential_filename)
with open(potential_filename, 'w') as infile:
infile.write(potential_txt)

Expand Down
6 changes: 6 additions & 0 deletions aiida_lammps/calculations/lammps/force.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from aiida.plugins import DataFactory
from aiida_lammps.calculations.lammps import BaseLammpsCalculation
from aiida_lammps.common.utils import convert_date_string
import six
Expand Down Expand Up @@ -53,6 +54,11 @@ def define(cls, spec):

# spec.input('settings', valid_type=six.string_types, default='lammps.optimize')

spec.output('arrays',
valid_type=DataFactory('array'),
required=True,
help='force data per step')

def validate_parameters(self, param_data, potential_object):
self._retrieve_list += [self._OUTPUT_TRAJECTORY_FILE_NAME]
self._retrieve_temporary_list += []
3 changes: 2 additions & 1 deletion aiida_lammps/calculations/lammps/md.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def validate_parameters(self, param_data, potential_object):
))

self._retrieve_list += []
self._retrieve_temporary_list += [self._OUTPUT_TRAJECTORY_FILE_NAME]
if self._OUTPUT_TRAJECTORY_FILE_NAME not in self._retrieve_temporary_list:
self._retrieve_temporary_list += [self._OUTPUT_TRAJECTORY_FILE_NAME]

return True
Loading

0 comments on commit 73ff49d

Please sign in to comment.