Skip to content

Commit

Permalink
Added modified Gaussian Calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
kmlefran committed Sep 13, 2023
1 parent 9f81ebf commit 71b43c6
Show file tree
Hide file tree
Showing 2 changed files with 233 additions and 3 deletions.
235 changes: 232 additions & 3 deletions aiida_aimall/calculations.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
Upon pip install, AimqbCalculation is accessible in AiiDA.calculations plugins
Using the 'aimall' entry point
"""
from aiida.common import datastructures
from aiida.engine import CalcJob
from aiida.orm import Dict, SinglefileData
from pymatgen.io.gaussian import GaussianInput # pylint: disable=import-error

from aiida.common import CalcInfo, CodeInfo, datastructures
from aiida.engine import CalcJob, ExitCode
from aiida.orm import Dict, Float, RemoteData, SinglefileData, Str, StructureData
from aiida.plugins import DataFactory

AimqbParameters = DataFactory("aimall")
Expand Down Expand Up @@ -96,3 +98,230 @@ def prepare_for_submission(self, folder):
]

return calcinfo


class GaussianWFXCalculation(CalcJob):
"""
AiiDA calculation plugin wrapping Gaussian
Template:
parameters = Dict(dict={
'link0_parameters': {
'%chk':'aiida.chk',
'%mem': '1024MB',
'%nprocshared': '2',
},
'functional':'PBE1PBE',
'basis_set':'6-31g',
'charge': 0,
'multiplicity': 1,
'route_parameters': {
'scf': {'cdiis': None}
'nosymm': None,
'opt': 'tight',
},
})
"""

# Defaults
INPUT_FILE = "aiida.inp"
OUTPUT_FILE = "aiida.out"
PARENT_FOLDER_NAME = "parent_calc"
DEFAULT_PARSER = "gaussian.base"

@classmethod
def define(cls, spec):
super().define(spec)

# Input parameters
spec.input(
"structure",
valid_type=StructureData,
required=False,
help="Input structure; will be converted to pymatgen object",
)
spec.input("structure_str", valid_type=Str, required=False)
spec.input(
"parameters", valid_type=Dict, required=True, help="Input parameters"
)
spec.input(
"settings",
valid_type=Dict,
required=False,
help="additional input parameters",
)

spec.input(
"parent_calc_folder",
valid_type=RemoteData,
required=False,
help="the folder of a completed gaussian calculation",
)

# Turn mpi off by default
spec.input("metadata.options.withmpi", valid_type=bool, default=False)

spec.input(
"metadata.options.parser_name",
valid_type=str,
default=cls.DEFAULT_PARSER,
non_db=True,
)

# Outputs
spec.output(
"output_parameters",
valid_type=Dict,
required=True,
help="The result parameters of the calculation",
)
spec.output(
"output_structure",
valid_type=StructureData,
required=False,
help="Final optimized structure, if available",
)
spec.output(
"energy_ev",
valid_type=Float,
required=False,
help="Final energy in electronvolts",
)
spec.output(
"wfx",
valid_type=SinglefileData,
required=False,
help="wfx file from calculation",
)
spec.default_output_node = "output_parameters"
spec.outputs.dynamic = True

# Exit codes
spec.exit_code(
200,
"ERROR_NO_RETRIEVED_FOLDER",
message="The retrieved folder data node could not be accessed.",
)
spec.exit_code(
210,
"ERROR_OUTPUT_MISSING",
message="The retrieved folder did not contain the output file.",
)
spec.exit_code(
211,
"ERROR_OUTPUT_LOG_READ",
message="The retrieved output log could not be read.",
)
spec.exit_code(
220,
"ERROR_OUTPUT_PARSING",
message="The output file could not be parsed.",
)
spec.exit_code(
301,
"ERROR_SCF_FAILURE",
message="The SCF did not converge and the calculation was terminated.",
)
spec.exit_code(
302,
"ERROR_ASYTOP",
message="The calculation was terminated due to a logic error in ASyTop.",
)
spec.exit_code(
303,
"ERROR_INACCURATE_QUADRATURE_CALDSU",
message="The calculation was terminated due to an inaccurate quadrature in CalDSu.",
)
spec.exit_code(
390,
"ERROR_TERMINATION",
message="The calculation was terminated due to an error.",
)
spec.exit_code(
391,
"ERROR_NO_NORMAL_TERMINATION",
message="The log did not contain 'Normal termination' (probably out of time).",
)
spec.exit_code(
410,
"ERROR_MULTIPLE_INPUT_STRUCTURES",
message="structure and structure_str were both provided as inputs. provide only one",
)

# --------------------------------------------------------------------------
def prepare_for_submission(self, folder):
"""
This is the routine to be called when you want to create
the input files and related stuff with a plugin.
:param folder: a aiida.common.folders.Folder subclass where
the plugin should put all its files.
"""

if "structure" in self.inputs and "structure_str" not in self.inputs:
structure = self.inputs.structure.get_pymatgen_molecule()
elif "structure" not in self.inputs and "structure_str" in self.inputs:
structure = self.inputs.structure_str.value
elif "structure" in self.inputs and "structure_str" in self.inputs:
return ExitCode(410)
else:
# If structure is not specified, it is read from the chk file
structure = None

# Generate the input file
input_string = GaussianWFXCalculation._render_input_string_from_params(
self.inputs.parameters.get_dict(), structure
)

with open(
folder.get_abs_path(self.INPUT_FILE), "w", encoding="utf-8"
) as out_file:
out_file.write(input_string)

settings = self.inputs.settings.get_dict() if "settings" in self.inputs else {}

# create code info
codeinfo = CodeInfo()
codeinfo.cmdline_params = settings.pop("cmdline", [])
codeinfo.code_uuid = self.inputs.code.uuid
codeinfo.stdin_name = self.INPUT_FILE
codeinfo.stdout_name = self.OUTPUT_FILE
codeinfo.withmpi = self.inputs.metadata.options.withmpi

# create calculation info
calcinfo = CalcInfo()
calcinfo.remote_copy_list = []
calcinfo.local_copy_list = []
calcinfo.uuid = self.uuid
calcinfo.cmdline_params = codeinfo.cmdline_params
calcinfo.stdin_name = self.INPUT_FILE
calcinfo.stdout_name = self.OUTPUT_FILE
calcinfo.codes_info = [codeinfo]
calcinfo.retrieve_list = [self.OUTPUT_FILE, "output.wfx"]

# symlink or copy to parent calculation
calcinfo.remote_symlink_list = []
calcinfo.remote_copy_list = []
if "parent_calc_folder" in self.inputs:
comp_uuid = self.inputs.parent_calc_folder.computer.uuid
remote_path = self.inputs.parent_calc_folder.get_remote_path()
copy_info = (comp_uuid, remote_path, self.PARENT_FOLDER_NAME)
if self.inputs.code.computer.uuid == comp_uuid:
# if running on the same computer - make a symlink
# if not - copy the folder
calcinfo.remote_symlink_list.append(copy_info)
else:
calcinfo.remote_copy_list.append(copy_info)

return calcinfo

@classmethod
def _render_input_string_from_params(cls, parameters, structure_string):
"""Generate the Gaussian input file using pymatgen."""
parameters.setdefault("dieze_tag", "#N")
parameters.setdefault("spin_multiplicity", parameters.pop("multiplicity", None))
parameters["title"] = "input generated by the aiida-gaussian plugin"
gaussian_input = GaussianInput(structure_string, **parameters)
return gaussian_input.to_string(cart_coords=True)
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ docs = [

[project.entry-points."aiida.calculations"]
"aimall" = "aiida_aimall.calculations:AimqbCalculation"
"gaussianwfx" = "aiida_aimall.calculations:GaussianWFXCalculation"

[project.entry-points."aiida.parsers"]
"aimqb.base" = "aiida_aimall.parsers:AimqbBaseParser"
Expand Down

0 comments on commit 71b43c6

Please sign in to comment.