aiida-chemshell 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. {aiida_chemshell-0.2.0/src/aiida_chemshell.egg-info → aiida_chemshell-0.2.1}/PKG-INFO +11 -3
  2. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/README.md +10 -2
  3. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/pyproject.toml +4 -3
  4. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/calculations/base.py +26 -21
  5. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/parsers/base.py +19 -31
  6. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/workflows/batch_calculation.py +10 -1
  7. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1/src/aiida_chemshell.egg-info}/PKG-INFO +11 -3
  8. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell.egg-info/entry_points.txt +1 -2
  9. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/tests/test_batch_workcahin.py +39 -0
  10. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/tests/test_calculations.py +13 -11
  11. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/tests/test_inputs.py +3 -3
  12. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/LICENSE +0 -0
  13. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/setup.cfg +0 -0
  14. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/__init__.py +0 -0
  15. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/calculations/__init__.py +0 -0
  16. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/calculations/file_conversion.py +0 -0
  17. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/calculations/solvant_removal.py +0 -0
  18. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/calculations/utils.py +0 -0
  19. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/parsers/__init__.py +0 -0
  20. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/parsers/file_conversion.py +0 -0
  21. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/periodic_table.py +0 -0
  22. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/units.py +0 -0
  23. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/utils.py +0 -0
  24. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/workflows/__init__.py +0 -0
  25. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/workflows/isolated_atoms.py +0 -0
  26. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell/workflows/optimisation.py +0 -0
  27. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell.egg-info/SOURCES.txt +0 -0
  28. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell.egg-info/dependency_links.txt +0 -0
  29. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell.egg-info/requires.txt +0 -0
  30. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/src/aiida_chemshell.egg-info/top_level.txt +0 -0
  31. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/tests/test_error_codes.py +0 -0
  32. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/tests/test_isolated_atoms_workchain.py +0 -0
  33. {aiida_chemshell-0.2.0 → aiida_chemshell-0.2.1}/tests/test_workflows.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiida-chemshell
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: AiiDA workflow plugin for the ChemShell chemical modelling software package
5
5
  Author-email: "Dr. Benjamin T. Speake" <benjamin.speake@stfc.ac.uk>
6
6
  License: BSD 3-Clause License
@@ -62,9 +62,10 @@ Dynamic: license-file
62
62
  [![Pipeline Status](https://github.com/stfc/aiida-chemshell/actions/workflows/ci-testing.yml/badge.svg?branch=main)](https://github.com/stfc/aiida-chemshell/actions)
63
63
  [![Coverage Status]( https://coveralls.io/repos/github/stfc/aiida-chemshell/badge.svg?branch=main)](https://coveralls.io/github/stfc/aiida-chemshell?branch=main)
64
64
 
65
- [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18392782.svg)](https://doi.org/10.5281/zenodo.18392782)
65
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.18392782-blue.svg)](https://doi.org/10.5281/zenodo.18392782)
66
66
 
67
- # aiida-chemshell
67
+
68
+ # AiiDA ChemShell
68
69
 
69
70
  An [AiiDA](https://www.aiida.net) plugin for the [ChemShell](https://chemshell.org/) multiscale
70
71
  computational chemistry software package.
@@ -110,6 +111,13 @@ verdi code create core.code.installed --config chemshell.yml -n
110
111
 
111
112
  If successful this will have created a code with the label `chemsh` which can then be used to run ChemShell jobs within the AiiDA workflow.
112
113
 
114
+ ### ChemShell with MPI
115
+
116
+ It is important to note that the configuration of an MPI enabled ChemShell code differs slightly depending on whether the code instance uses
117
+ the `chemsh` or `chemsh.x` executable. If you have a parallel (MPI enabled) build of ChemShell but are using the `chemsh` wrapper executable
118
+ please set `with_mpi: false` as the underlying plugin will handle how to call the mpi runtime. If you are calling the `chemsh.x` executable
119
+ directly then `with_mpi: true` is required to run parallel jobs.
120
+
113
121
  ## Examples
114
122
 
115
123
  ### QM Based Single Point Energy
@@ -5,9 +5,10 @@
5
5
  [![Pipeline Status](https://github.com/stfc/aiida-chemshell/actions/workflows/ci-testing.yml/badge.svg?branch=main)](https://github.com/stfc/aiida-chemshell/actions)
6
6
  [![Coverage Status]( https://coveralls.io/repos/github/stfc/aiida-chemshell/badge.svg?branch=main)](https://coveralls.io/github/stfc/aiida-chemshell?branch=main)
7
7
 
8
- [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18392782.svg)](https://doi.org/10.5281/zenodo.18392782)
8
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.18392782-blue.svg)](https://doi.org/10.5281/zenodo.18392782)
9
9
 
10
- # aiida-chemshell
10
+
11
+ # AiiDA ChemShell
11
12
 
12
13
  An [AiiDA](https://www.aiida.net) plugin for the [ChemShell](https://chemshell.org/) multiscale
13
14
  computational chemistry software package.
@@ -53,6 +54,13 @@ verdi code create core.code.installed --config chemshell.yml -n
53
54
 
54
55
  If successful this will have created a code with the label `chemsh` which can then be used to run ChemShell jobs within the AiiDA workflow.
55
56
 
57
+ ### ChemShell with MPI
58
+
59
+ It is important to note that the configuration of an MPI enabled ChemShell code differs slightly depending on whether the code instance uses
60
+ the `chemsh` or `chemsh.x` executable. If you have a parallel (MPI enabled) build of ChemShell but are using the `chemsh` wrapper executable
61
+ please set `with_mpi: false` as the underlying plugin will handle how to call the mpi runtime. If you are calling the `chemsh.x` executable
62
+ directly then `with_mpi: true` is required to run parallel jobs.
63
+
56
64
  ## Examples
57
65
 
58
66
  ### QM Based Single Point Energy
@@ -3,7 +3,7 @@ requires = ["setuptools"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
- version = "0.2.0"
6
+ version = "0.2.1"
7
7
  name = "aiida-chemshell"
8
8
  description = "AiiDA workflow plugin for the ChemShell chemical modelling software package"
9
9
  authors = [
@@ -27,15 +27,16 @@ Source = "https://github.com/stfc/aiida-chemshell"
27
27
 
28
28
  [project.entry-points."aiida.calculations"]
29
29
  "chemshell" = "aiida_chemshell.calculations.base:ChemShellCalculation"
30
- "chemshell.file_conversion.mlip_training" = "aiida_chemshell.calculations.file_conversion:CreateJanusTrainingInputsCalcJob"
30
+
31
31
 
32
32
  [project.entry-points."aiida.parsers"]
33
33
  "chemshell" = "aiida_chemshell.parsers.base:ChemShellParser"
34
- "chemshell.file_conversion.mlip_training" = "aiida_chemshell.parsers.file_conversion:CreateJanusTrainingInputsParser"
34
+
35
35
 
36
36
  [project.entry-points."aiida.workflows"]
37
37
  "chemshell.opt" = "aiida_chemshell.workflows.optimisation:GeometryOptimisationWorkChain"
38
38
  "chemshell.atomic_energies" = "aiida_chemshell.workflows.isolated_atoms:IsolatedAtomicEnergiesWorkChain"
39
+ "chemshell.batch" = "aiida_chemshell.workflows.batch_calculation:BatchProcessWorkChain"
39
40
 
40
41
  [tool.setuptools.packages.find]
41
42
  where = ["src"]
@@ -203,17 +203,17 @@ class ChemShellCalculation(CalcJob):
203
203
 
204
204
  spec.output(
205
205
  "trajectory_path",
206
- valid_type=SinglefileData,
206
+ valid_type=TrajectoryData,
207
207
  required=False,
208
- help="XYZ trajectory file for the geometry optimisation",
208
+ help="Trajectory with the path taken for a geometry optimisation.",
209
209
  )
210
210
  spec.output(
211
211
  "trajectory_force",
212
212
  valid_type=SinglefileData,
213
213
  required=False,
214
214
  help=(
215
- "XYZ trajectory containing forces at each step of a geometry "
216
- "optimisation"
215
+ "XYZ style trajectory file containing forces at each step of a geometry"
216
+ " optimisation."
217
217
  ),
218
218
  )
219
219
 
@@ -435,7 +435,7 @@ class ChemShellCalculation(CalcJob):
435
435
  return None
436
436
 
437
437
  @classmethod
438
- def get_valid_qm_paramater_keys(cls) -> dict[str:type]:
438
+ def get_valid_qm_parameter_keys(cls) -> dict:
439
439
  """
440
440
  Return a tuple of valid parameter keys for the ChemShell calculation.
441
441
 
@@ -455,7 +455,7 @@ class ChemShellCalculation(CalcJob):
455
455
  "damping": bool,
456
456
  "diis": bool,
457
457
  "direct": bool,
458
- "guess": str, # TODO: file???
458
+ # "guess": str, # TODO: file???
459
459
  "maxiter": int,
460
460
  "path": str,
461
461
  "pseudopotential": str | dict,
@@ -488,7 +488,7 @@ class ChemShellCalculation(CalcJob):
488
488
  "ChemShell theory interface within the AiiDA-ChemShell workflow."
489
489
  )
490
490
 
491
- valid_keys = cls.get_valid_qm_paramater_keys()
491
+ valid_keys = cls.get_valid_qm_parameter_keys()
492
492
 
493
493
  # Check for valid parameter keys
494
494
  invalid_keys = set(value.keys()).difference(set(valid_keys.keys()))
@@ -527,7 +527,7 @@ class ChemShellCalculation(CalcJob):
527
527
  return None
528
528
 
529
529
  @classmethod
530
- def get_valid_mm_paramater_keys(cls, theory: str = "") -> dict[str:type]:
530
+ def get_valid_mm_parameter_keys(cls, theory: str = "") -> dict[str:type]:
531
531
  """
532
532
  Return a tuple of valid parameter keys for the ChemShell MM interface.
533
533
 
@@ -539,8 +539,8 @@ class ChemShellCalculation(CalcJob):
539
539
  if theory == "DL_POLY":
540
540
  valid_keys = {
541
541
  "theory": str,
542
- "input": str | tuple[str],
543
- "output": str,
542
+ # "input": str | tuple[str],
543
+ # "output": str,
544
544
  # general keys -> TODO: these are files which are not supported
545
545
  # by as AiiDA nodes if in a Dict object
546
546
  "berendsen": float,
@@ -564,8 +564,8 @@ class ChemShellCalculation(CalcJob):
564
564
  elif theory == "GULP":
565
565
  valid_keys = {
566
566
  "theory": str,
567
- "input": str,
568
- "output": str,
567
+ # "input": str,
568
+ # "output": str,
569
569
  # general keys -> TODO: these are files which are not supported
570
570
  # by as AiiDA nodes if in a Dict object
571
571
  "molecule": bool,
@@ -574,8 +574,8 @@ class ChemShellCalculation(CalcJob):
574
574
  elif theory == "NAMD":
575
575
  valid_keys = {
576
576
  "theory": str,
577
- "input": str,
578
- "output": str,
577
+ # "input": str,
578
+ # "output": str,
579
579
  # general keys -> TODO: these are files which are not supported
580
580
  # by as AiiDA nodes if in a Dict object
581
581
  "binary": bool,
@@ -615,7 +615,9 @@ class ChemShellCalculation(CalcJob):
615
615
  "wrap_water": bool,
616
616
  }
617
617
  else:
618
- valid_keys = {"theory": str, "input": str, "output": str}
618
+ valid_keys = {
619
+ "theory": str,
620
+ }
619
621
  return valid_keys
620
622
 
621
623
  @classmethod
@@ -642,7 +644,7 @@ class ChemShellCalculation(CalcJob):
642
644
  "valid ChemShell MM interface within the AiiDA-ChemShell workflow."
643
645
  )
644
646
 
645
- valid_keys = cls.get_valid_mm_paramater_keys(theory)
647
+ valid_keys = cls.get_valid_mm_parameter_keys(theory)
646
648
  invalid_keys = set(value.keys()).difference(set(valid_keys.keys()))
647
649
  if invalid_keys:
648
650
  # Checks for invalid parameter keys
@@ -974,11 +976,12 @@ class ChemShellCalculation(CalcJob):
974
976
  # Setup the calculation information object
975
977
  calc_info = CalcInfo()
976
978
  calc_info.codes_info = [code_info]
977
- calc_info.retrieve_temporary_list = []
979
+ calc_info.retrieve_temporary_list = [
980
+ ChemShellCalculation.FILE_RESULTS,
981
+ ]
978
982
  calc_info.provenance_exclude_list = []
979
983
  calc_info.retrieve_list = [
980
984
  ChemShellCalculation.FILE_STDOUT,
981
- ChemShellCalculation.FILE_RESULTS,
982
985
  ]
983
986
  calc_info.local_copy_list = []
984
987
 
@@ -1033,12 +1036,14 @@ class ChemShellCalculation(CalcJob):
1033
1036
  "frozen",
1034
1037
  "perpendicular",
1035
1038
  ]:
1036
- calc_info.retrieve_list.append(ChemShellCalculation.FILE_DLFIND)
1039
+ calc_info.retrieve_temporary_list.append(
1040
+ ChemShellCalculation.FILE_DLFIND
1041
+ )
1037
1042
  if self.inputs.optimisation_parameters.get("save_path", False):
1038
- calc_info.retrieve_list.append(
1043
+ calc_info.retrieve_temporary_list.append(
1039
1044
  "_dl_find/" + ChemShellCalculation.FILE_TRJPTH
1040
1045
  )
1041
- calc_info.retrieve_list.append(
1046
+ calc_info.retrieve_temporary_list.append(
1042
1047
  "_dl_find/" + ChemShellCalculation.FILE_TRJFRC
1043
1048
  )
1044
1049
  if self.inputs.optimisation_parameters.get("neb", "no") in [
@@ -17,17 +17,17 @@ class ChemShellParser(Parser):
17
17
 
18
18
  def parse(self, **kwargs):
19
19
  """Parse the output of a ChemShell calculation."""
20
- retrieved_tmp_folder = kwargs.get("retrieved_temporary_folder", None)
20
+ retrieved_tmp_folder = Path(kwargs.get("retrieved_temporary_folder", ""))
21
21
 
22
22
  if ChemShellCalculation.FILE_STDOUT not in self.retrieved.list_object_names():
23
23
  return self.exit_codes.ERROR_STDOUT_NOT_FOUND
24
- if ChemShellCalculation.FILE_RESULTS not in self.retrieved.list_object_names():
24
+ results_path = retrieved_tmp_folder / ChemShellCalculation.FILE_RESULTS
25
+ if not (results_path).exists():
25
26
  return self.exit_codes.ERROR_RESULTS_FILE_NOT_FOUND
26
27
 
27
28
  # Read the 'json' formatted results file
28
- results = json.loads(
29
- self.retrieved.get_object_content(ChemShellCalculation.FILE_RESULTS, "rb")
30
- )
29
+ with open(results_path, "rb") as f:
30
+ results = json.loads(f.read())
31
31
 
32
32
  # Extract the final energy
33
33
  try:
@@ -70,6 +70,7 @@ class ChemShellParser(Parser):
70
70
 
71
71
  # If the calculation was a geometry optimisation, store the optimised structure
72
72
  if "optimisation_parameters" in self.node.inputs:
73
+ dl_find_path = retrieved_tmp_folder / ChemShellCalculation.FILE_DLFIND
73
74
  if self.node.inputs.optimisation_parameters.get("thermal", False):
74
75
  self.parse_vibrational_analysis(
75
76
  self.retrieved.get_object_content(
@@ -81,9 +82,9 @@ class ChemShellParser(Parser):
81
82
  "frozen",
82
83
  "perpendicular",
83
84
  ]:
84
- self.parse_neb_path(Path(retrieved_tmp_folder) / "nebpath.xyz")
85
- self.parse_neb_info(Path(retrieved_tmp_folder) / "nebinfo")
86
- elif ChemShellCalculation.FILE_DLFIND in self.retrieved.list_object_names():
85
+ self.parse_xyz_path(retrieved_tmp_folder / "nebpath.xyz", "neb_path")
86
+ self.parse_neb_info(retrieved_tmp_folder / "nebinfo")
87
+ elif dl_find_path.exists():
87
88
  descrip = "Optimised structure from a ChemShell optimisation"
88
89
  input_pk = self.node.inputs.structure.pk
89
90
  descrip += f" of node {input_pk}"
@@ -91,7 +92,7 @@ class ChemShellParser(Parser):
91
92
  input_fname = self.node.inputs.structure.filename
92
93
  descrip += f" ({input_fname})"
93
94
  # Store the optimised structure file
94
- with self.retrieved.open(ChemShellCalculation.FILE_DLFIND, "rb") as f:
95
+ with open(dl_find_path, "rb") as f:
95
96
  self.out(
96
97
  "optimised_structure",
97
98
  SinglefileData(
@@ -110,26 +111,11 @@ class ChemShellParser(Parser):
110
111
  return self.exit_codes.ERROR_MISSING_OPTIMISED_STRUCTURE_FILE
111
112
 
112
113
  if self.node.inputs.optimisation_parameters.get("save_path", False):
113
- if (
114
- ChemShellCalculation.FILE_TRJPTH
115
- in self.retrieved.list_object_names()
116
- ):
117
- with self.retrieved.open(
118
- ChemShellCalculation.FILE_TRJPTH, "r"
119
- ) as f:
120
- self.out(
121
- "trajectory_path",
122
- SinglefileData(
123
- file=f,
124
- filename=ChemShellCalculation.FILE_TRJPTH.replace(
125
- "/", "_"
126
- ),
127
- label="ChemShell optimisation trajectory.",
128
- ),
129
- )
130
- with self.retrieved.open(
131
- ChemShellCalculation.FILE_TRJFRC, "r"
132
- ) as f:
114
+ trj_path = retrieved_tmp_folder / ChemShellCalculation.FILE_TRJPTH
115
+ trj_frc_path = retrieved_tmp_folder / ChemShellCalculation.FILE_TRJFRC
116
+ if trj_path.exists():
117
+ self.parse_xyz_path(trj_path, "trajectory_path")
118
+ with open(trj_frc_path, "rb") as f:
133
119
  self.out(
134
120
  "trajectory_force",
135
121
  SinglefileData(
@@ -200,7 +186,7 @@ class ChemShellParser(Parser):
200
186
  self.out("optimisation_path", results)
201
187
  return
202
188
 
203
- def parse_neb_path(self, file_path: Path) -> None:
189
+ def parse_xyz_path(self, file_path: Path, output_link: str) -> None:
204
190
  """Parse the NEB pathway into an AiiDA TrajectoryData node."""
205
191
  with open(file_path) as f:
206
192
  lines = f.readlines()
@@ -223,7 +209,9 @@ class ChemShellParser(Parser):
223
209
  i += natoms + 2
224
210
  path = TrajectoryData()
225
211
  path.set_trajectory(symbols=symbols, positions=numpy.asarray(positions))
226
- self.out("neb_path", path)
212
+ path.label = "ChemShell (DL_FIND) optimisation path."
213
+ path.description = "Path taken for a ChemShell Optimisation or NEB calculation."
214
+ self.out(output_link, path)
227
215
  return
228
216
 
229
217
  def parse_neb_info(self, file_path: Path) -> None:
@@ -17,9 +17,14 @@ class BatchProcessWorkChain(WorkChain):
17
17
  """Define the AiiDA process specification."""
18
18
  super().define(spec)
19
19
 
20
- # Expose Chemshell inputs
20
+ # Expose Chemshell inputs in the top level namespace
21
21
  spec.expose_inputs(ChemShellCalculation, exclude=("structure", "metadata"))
22
22
 
23
+ # Expose the calculation metadata under a dedicated 'calc' namespace.
24
+ spec.expose_inputs(
25
+ ChemShellCalculation, namespace="calc", include=("metadata",)
26
+ )
27
+
23
28
  # Input structure series
24
29
  spec.input(
25
30
  "trajectory",
@@ -90,6 +95,10 @@ class BatchProcessWorkChain(WorkChain):
90
95
  """Extract all individual structures and submit their calculations."""
91
96
  futures: dict[str, ProcessNode] = {}
92
97
  inputs = {"code": self.inputs.code}
98
+ # Forward the calculation options (resources, MPI processes, wallclock, ...)
99
+ # to every job in the batch.
100
+ if "calc" in self.inputs and "options" in self.inputs.calc.metadata:
101
+ inputs["metadata"] = {"options": dict(self.inputs.calc.metadata.options)}
93
102
  if "qm_parameters" in self.inputs:
94
103
  inputs["qm_parameters"] = self.inputs.qm_parameters
95
104
  if "mm_parameters" in self.inputs:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiida-chemshell
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: AiiDA workflow plugin for the ChemShell chemical modelling software package
5
5
  Author-email: "Dr. Benjamin T. Speake" <benjamin.speake@stfc.ac.uk>
6
6
  License: BSD 3-Clause License
@@ -62,9 +62,10 @@ Dynamic: license-file
62
62
  [![Pipeline Status](https://github.com/stfc/aiida-chemshell/actions/workflows/ci-testing.yml/badge.svg?branch=main)](https://github.com/stfc/aiida-chemshell/actions)
63
63
  [![Coverage Status]( https://coveralls.io/repos/github/stfc/aiida-chemshell/badge.svg?branch=main)](https://coveralls.io/github/stfc/aiida-chemshell?branch=main)
64
64
 
65
- [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18392782.svg)](https://doi.org/10.5281/zenodo.18392782)
65
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.18392782-blue.svg)](https://doi.org/10.5281/zenodo.18392782)
66
66
 
67
- # aiida-chemshell
67
+
68
+ # AiiDA ChemShell
68
69
 
69
70
  An [AiiDA](https://www.aiida.net) plugin for the [ChemShell](https://chemshell.org/) multiscale
70
71
  computational chemistry software package.
@@ -110,6 +111,13 @@ verdi code create core.code.installed --config chemshell.yml -n
110
111
 
111
112
  If successful this will have created a code with the label `chemsh` which can then be used to run ChemShell jobs within the AiiDA workflow.
112
113
 
114
+ ### ChemShell with MPI
115
+
116
+ It is important to note that the configuration of an MPI enabled ChemShell code differs slightly depending on whether the code instance uses
117
+ the `chemsh` or `chemsh.x` executable. If you have a parallel (MPI enabled) build of ChemShell but are using the `chemsh` wrapper executable
118
+ please set `with_mpi: false` as the underlying plugin will handle how to call the mpi runtime. If you are calling the `chemsh.x` executable
119
+ directly then `with_mpi: true` is required to run parallel jobs.
120
+
113
121
  ## Examples
114
122
 
115
123
  ### QM Based Single Point Energy
@@ -1,11 +1,10 @@
1
1
  [aiida.calculations]
2
2
  chemshell = aiida_chemshell.calculations.base:ChemShellCalculation
3
- chemshell.file_conversion.mlip_training = aiida_chemshell.calculations.file_conversion:CreateJanusTrainingInputsCalcJob
4
3
 
5
4
  [aiida.parsers]
6
5
  chemshell = aiida_chemshell.parsers.base:ChemShellParser
7
- chemshell.file_conversion.mlip_training = aiida_chemshell.parsers.file_conversion:CreateJanusTrainingInputsParser
8
6
 
9
7
  [aiida.workflows]
10
8
  chemshell.atomic_energies = aiida_chemshell.workflows.isolated_atoms:IsolatedAtomicEnergiesWorkChain
9
+ chemshell.batch = aiida_chemshell.workflows.batch_calculation:BatchProcessWorkChain
11
10
  chemshell.opt = aiida_chemshell.workflows.optimisation:GeometryOptimisationWorkChain
@@ -7,6 +7,45 @@ from aiida.orm import Dict
7
7
  from aiida_chemshell.workflows.batch_calculation import BatchProcessWorkChain
8
8
 
9
9
 
10
+ def test_batch_exposes_calculation_metadata_options():
11
+ """The calculation metadata options must be exposed under the 'calc' namespace.
12
+
13
+ This allows users to specify the resources (e.g. number of MPI processes) used
14
+ by the underlying series of ChemShell calculations, without clashing with the
15
+ WorkChain's own reserved 'metadata' namespace.
16
+ """
17
+ spec = BatchProcessWorkChain.spec()
18
+ assert "options" not in spec.inputs["metadata"], (
19
+ "Calculation options must not be merged into the WorkChain metadata."
20
+ )
21
+ options = spec.inputs["calc"]["metadata"]["options"]
22
+ assert "resources" in options, "The calculation metadata options are not exposed."
23
+
24
+
25
+ def test_batch_forwards_metadata_options(chemsh_code, water_trajectory_object):
26
+ """Resources set on the WorkChain are forwarded to every sub-calculation."""
27
+ resources = {"num_machines": 1, "num_mpiprocs_per_machine": 2}
28
+ inputs = {
29
+ "code": chemsh_code(),
30
+ "trajectory": water_trajectory_object,
31
+ "qm_parameters": Dict(
32
+ {
33
+ "theory": "PySCF",
34
+ "method": "hf",
35
+ }
36
+ ),
37
+ "calc": {"metadata": {"options": {"resources": resources}}},
38
+ }
39
+ results, node = run_get_node(BatchProcessWorkChain, **inputs)
40
+
41
+ assert node.is_finished_ok, "WorkChain Failed"
42
+
43
+ sub_nodes = node.called
44
+ assert len(sub_nodes) == 3, "Incorrect number of sub processes created."
45
+ for sub_node in sub_nodes:
46
+ assert sub_node.get_option("resources") == resources
47
+
48
+
10
49
  def test_batch_from_trajectorydata(chemsh_code, water_trajectory_object):
11
50
  """DFT based single point test."""
12
51
  inputs = {
@@ -24,7 +24,7 @@ def test_sp_calculation_qm_hf(chemsh_code, get_test_data_file):
24
24
 
25
25
  ofiles = results["retrieved"].list_object_names()
26
26
  assert ChemShellCalculation.FILE_STDOUT in ofiles
27
- assert ChemShellCalculation.FILE_RESULTS in ofiles
27
+ # assert ChemShellCalculation.FILE_RESULTS in ofiles
28
28
 
29
29
  eref = -75.585287777076
30
30
  assert abs(results.get("energy") - eref) < 1e-8, (
@@ -79,7 +79,7 @@ def test_sp_calculation_qm_dft(chemsh_code, get_test_data_file, water_structure_
79
79
 
80
80
  ofiles = results.get("retrieved").list_object_names()
81
81
  assert ChemShellCalculation.FILE_STDOUT in ofiles
82
- assert ChemShellCalculation.FILE_RESULTS in ofiles
82
+ # assert ChemShellCalculation.FILE_RESULTS in ofiles
83
83
 
84
84
  # eref = -75.946889377347 # If using conversion to bohr
85
85
  eref = -75.946889436563
@@ -110,7 +110,7 @@ def test_sp_calculation_dlpoly(chemsh_code, get_test_data_file):
110
110
 
111
111
  ofiles = results.get("retrieved").list_object_names()
112
112
  assert ChemShellCalculation.FILE_STDOUT in ofiles
113
- assert ChemShellCalculation.FILE_RESULTS in ofiles
113
+ # assert ChemShellCalculation.FILE_RESULTS in ofiles
114
114
 
115
115
  eref = 0.018194285557
116
116
  assert (abs(results.get("energy") - eref)) < 1e-8, (
@@ -138,7 +138,7 @@ def test_sp_calculation_qmmm(chemsh_code, get_test_data_file):
138
138
 
139
139
  ofiles = results.get("retrieved").list_object_names()
140
140
  assert ChemShellCalculation.FILE_STDOUT in ofiles
141
- assert ChemShellCalculation.FILE_RESULTS in ofiles
141
+ # assert ChemShellCalculation.FILE_RESULTS in ofiles
142
142
 
143
143
  eref = -75.594381915214
144
144
 
@@ -164,7 +164,7 @@ def test_opt_calculation_qm_dft(chemsh_code, get_test_data_file):
164
164
 
165
165
  ofiles = results.get("retrieved").list_object_names()
166
166
  assert ChemShellCalculation.FILE_STDOUT in ofiles
167
- assert ChemShellCalculation.FILE_RESULTS in ofiles
167
+ # assert ChemShellCalculation.FILE_RESULTS in ofiles
168
168
 
169
169
  assert (
170
170
  results.get("optimised_structure").filename == ChemShellCalculation.FILE_DLFIND
@@ -205,7 +205,7 @@ def test_opt_calculation_dlpoly(chemsh_code, get_test_data_file):
205
205
  builder.structure = get_test_data_file("butanol.cjson")
206
206
  builder.mm_parameters = Dict({"theory": "DL_POLY"})
207
207
  builder.force_field_file = get_test_data_file("butanol.ff")
208
- builder.optimisation_parameters = Dict({})
208
+ builder.optimisation_parameters = Dict({"save_path": True})
209
209
 
210
210
  results, node = run.get_node(builder)
211
211
 
@@ -216,8 +216,6 @@ def test_opt_calculation_dlpoly(chemsh_code, get_test_data_file):
216
216
 
217
217
  ofiles = results.get("retrieved").list_object_names()
218
218
  assert ChemShellCalculation.FILE_STDOUT in ofiles
219
- assert ChemShellCalculation.FILE_DLFIND in ofiles
220
- assert ChemShellCalculation.FILE_RESULTS in ofiles
221
219
 
222
220
  assert (
223
221
  results.get("optimised_structure").filename == ChemShellCalculation.FILE_DLFIND
@@ -234,6 +232,10 @@ def test_opt_calculation_dlpoly(chemsh_code, get_test_data_file):
234
232
  "Incorrect energy result for DL_POLY based optimisation calculation."
235
233
  )
236
234
 
235
+ assert results.get("trajectory_path").numsteps == 13
236
+ assert results.get("trajectory_path").numsites == 15
237
+ assert results.get("trajectory_force").filename == ChemShellCalculation.FILE_TRJFRC
238
+
237
239
 
238
240
  def test_vibrational_calculation(chemsh_code, get_test_data_file):
239
241
  """MM based geometry optimisation test."""
@@ -282,7 +284,7 @@ def test_structure_from_trajectorydata(chemsh_code, water_trajectory_object):
282
284
 
283
285
  ofiles = results.get("retrieved").list_object_names()
284
286
  assert ChemShellCalculation.FILE_STDOUT in ofiles
285
- assert ChemShellCalculation.FILE_RESULTS in ofiles
287
+ # assert ChemShellCalculation.FILE_RESULTS in ofiles
286
288
 
287
289
  # eref = -75.946889377347 # Use if inputs are in bohr
288
290
  eref = -75.946889436563
@@ -311,8 +313,8 @@ def test_neb_calculation(chemsh_code, get_test_data_file):
311
313
 
312
314
  ofiles = results.get("retrieved").list_object_names()
313
315
  assert ChemShellCalculation.FILE_STDOUT in ofiles
314
- assert ChemShellCalculation.FILE_DLFIND not in ofiles
315
- assert ChemShellCalculation.FILE_RESULTS in ofiles
316
+ # assert ChemShellCalculation.FILE_DLFIND not in ofiles
317
+ # assert ChemShellCalculation.FILE_RESULTS in ofiles
316
318
 
317
319
  eref = -149.56942655605
318
320
  assert abs(results.get("energy") - eref) < 1e-8
@@ -11,8 +11,8 @@ def test_defaults(generate_calcjob):
11
11
 
12
12
  assert calc_info.retrieve_list == [
13
13
  ChemShellCalculation.FILE_STDOUT,
14
- ChemShellCalculation.FILE_RESULTS,
15
14
  ]
15
+ assert ChemShellCalculation.FILE_RESULTS in calc_info.retrieve_temporary_list
16
16
  code_info = calc_info.codes_info[0]
17
17
  assert ChemShellCalculation.FILE_SCRIPT in code_info.cmdline_params
18
18
  assert code_info.stdout_name == ChemShellCalculation.FILE_STDOUT
@@ -99,9 +99,9 @@ def test_default_qm_opt(generate_calcjob, generate_inputs):
99
99
 
100
100
  assert calc_info.retrieve_list == [
101
101
  ChemShellCalculation.FILE_STDOUT,
102
- ChemShellCalculation.FILE_RESULTS,
103
- ChemShellCalculation.FILE_DLFIND,
104
102
  ]
103
+ assert ChemShellCalculation.FILE_DLFIND in calc_info.retrieve_temporary_list
104
+ assert ChemShellCalculation.FILE_RESULTS in calc_info.retrieve_temporary_list
105
105
 
106
106
 
107
107
  def test_expanded_mm_parameters(generate_calcjob, generate_inputs):
File without changes