nomad-schema-plugin-simulation-workflow 1.0.1__py3-none-any.whl
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.
- nomad_schema_plugin_simulation_workflow-1.0.1.dist-info/LICENSE +202 -0
- nomad_schema_plugin_simulation_workflow-1.0.1.dist-info/METADATA +17 -0
- nomad_schema_plugin_simulation_workflow-1.0.1.dist-info/RECORD +22 -0
- nomad_schema_plugin_simulation_workflow-1.0.1.dist-info/WHEEL +5 -0
- nomad_schema_plugin_simulation_workflow-1.0.1.dist-info/entry_points.txt +2 -0
- nomad_schema_plugin_simulation_workflow-1.0.1.dist-info/top_level.txt +1 -0
- simulationworkflowschema/__init__.py +118 -0
- simulationworkflowschema/chemical_reaction.py +167 -0
- simulationworkflowschema/dmft.py +84 -0
- simulationworkflowschema/elastic.py +494 -0
- simulationworkflowschema/equation_of_state.py +213 -0
- simulationworkflowschema/general.py +505 -0
- simulationworkflowschema/geometry_optimization.py +349 -0
- simulationworkflowschema/gw.py +69 -0
- simulationworkflowschema/max_ent.py +80 -0
- simulationworkflowschema/molecular_dynamics.py +2601 -0
- simulationworkflowschema/phonon.py +196 -0
- simulationworkflowschema/photon_polarization.py +75 -0
- simulationworkflowschema/single_point.py +273 -0
- simulationworkflowschema/tb.py +77 -0
- simulationworkflowschema/thermodynamics.py +375 -0
- simulationworkflowschema/xs.py +100 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright The NOMAD Authors.
|
|
3
|
+
#
|
|
4
|
+
# This file is part of NOMAD. See https://nomad-lab.eu for further info.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
import numpy as np
|
|
19
|
+
from ase import Atoms
|
|
20
|
+
|
|
21
|
+
from nomad.metainfo import SubSection, Quantity, MEnum
|
|
22
|
+
from nomad.datamodel.metainfo.workflow import Link
|
|
23
|
+
from runschema.calculation import EnergyEntry
|
|
24
|
+
|
|
25
|
+
from .general import (
|
|
26
|
+
SimulationWorkflowMethod,
|
|
27
|
+
SimulationWorkflowResults,
|
|
28
|
+
SerialSimulation,
|
|
29
|
+
WORKFLOW_METHOD_NAME,
|
|
30
|
+
WORKFLOW_RESULTS_NAME,
|
|
31
|
+
resolve_difference,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class GeometryOptimizationMethod(SimulationWorkflowMethod):
|
|
36
|
+
type = Quantity(
|
|
37
|
+
type=MEnum('static', 'atomic', 'cell_shape', 'cell_volume'),
|
|
38
|
+
shape=[],
|
|
39
|
+
description="""
|
|
40
|
+
The type of geometry optimization, which denotes what is being optimized.
|
|
41
|
+
|
|
42
|
+
Allowed values are:
|
|
43
|
+
|
|
44
|
+
| Type | Description |
|
|
45
|
+
|
|
46
|
+
| ---------------------- | ----------------------------------------- |
|
|
47
|
+
|
|
48
|
+
| `"static"` | no optimization |
|
|
49
|
+
|
|
50
|
+
| `"atomic"` | the atomic coordinates alone are updated |
|
|
51
|
+
|
|
52
|
+
| `"cell_volume"` | `"atomic"` + cell lattice paramters are updated isotropically |
|
|
53
|
+
|
|
54
|
+
| `"cell_shape"` | `"cell_volume"` but without the isotropic constraint: all cell parameters are updated |
|
|
55
|
+
|
|
56
|
+
""",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
method = Quantity(
|
|
60
|
+
type=str,
|
|
61
|
+
shape=[],
|
|
62
|
+
description="""
|
|
63
|
+
The method used for geometry optimization. Some known possible values are:
|
|
64
|
+
`"steepest_descent"`, `"conjugant_gradient"`, `"low_memory_broyden_fletcher_goldfarb_shanno"`.
|
|
65
|
+
""",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
convergence_tolerance_energy_difference = Quantity(
|
|
69
|
+
type=np.float64,
|
|
70
|
+
shape=[],
|
|
71
|
+
unit='joule',
|
|
72
|
+
description="""
|
|
73
|
+
The input energy difference tolerance criterion.
|
|
74
|
+
""",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
convergence_tolerance_force_maximum = Quantity(
|
|
78
|
+
type=np.float64,
|
|
79
|
+
shape=[],
|
|
80
|
+
unit='newton',
|
|
81
|
+
description="""
|
|
82
|
+
The input maximum net force tolerance criterion.
|
|
83
|
+
""",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
convergence_tolerance_stress_maximum = Quantity(
|
|
87
|
+
type=np.float64,
|
|
88
|
+
shape=[],
|
|
89
|
+
unit='pascal',
|
|
90
|
+
description="""
|
|
91
|
+
The input maximum stress tolerance criterion.
|
|
92
|
+
""",
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
convergence_tolerance_displacement_maximum = Quantity(
|
|
96
|
+
type=np.float64,
|
|
97
|
+
shape=[],
|
|
98
|
+
unit='meter',
|
|
99
|
+
description="""
|
|
100
|
+
The input maximum displacement tolerance criterion.
|
|
101
|
+
""",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
optimization_steps_maximum = Quantity(
|
|
105
|
+
type=int,
|
|
106
|
+
shape=[],
|
|
107
|
+
description="""
|
|
108
|
+
Maximum number of optimization steps.
|
|
109
|
+
""",
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
save_frequency = Quantity(
|
|
113
|
+
type=int,
|
|
114
|
+
shape=[],
|
|
115
|
+
description="""
|
|
116
|
+
The number of optimization steps between saving the calculation.
|
|
117
|
+
""",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class GeometryOptimizationResults(SimulationWorkflowResults):
|
|
122
|
+
optimization_steps = Quantity(
|
|
123
|
+
type=int,
|
|
124
|
+
shape=[],
|
|
125
|
+
description="""
|
|
126
|
+
Number of saved optimization steps.
|
|
127
|
+
""",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
energies = Quantity(
|
|
131
|
+
type=np.float64,
|
|
132
|
+
unit='joule',
|
|
133
|
+
shape=['optimization_steps'],
|
|
134
|
+
description="""
|
|
135
|
+
List of energy_total values gathered from the single configuration
|
|
136
|
+
calculations that are a part of the optimization trajectory.
|
|
137
|
+
""",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
steps = Quantity(
|
|
141
|
+
type=np.int32,
|
|
142
|
+
shape=['optimization_steps'],
|
|
143
|
+
description="""
|
|
144
|
+
The step index corresponding to each saved configuration.
|
|
145
|
+
""",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
final_energy_difference = Quantity(
|
|
149
|
+
type=np.float64,
|
|
150
|
+
shape=[],
|
|
151
|
+
unit='joule',
|
|
152
|
+
description="""
|
|
153
|
+
The difference in the energy_total between the last two steps during
|
|
154
|
+
optimization.
|
|
155
|
+
""",
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
final_force_maximum = Quantity(
|
|
159
|
+
type=np.float64,
|
|
160
|
+
shape=[],
|
|
161
|
+
unit='newton',
|
|
162
|
+
description="""
|
|
163
|
+
The maximum net force in the last optimization step.
|
|
164
|
+
""",
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
final_displacement_maximum = Quantity(
|
|
168
|
+
type=np.float64,
|
|
169
|
+
shape=[],
|
|
170
|
+
unit='meter',
|
|
171
|
+
description="""
|
|
172
|
+
The maximum displacement in the last optimization step with respect to previous.
|
|
173
|
+
""",
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
is_converged_geometry = Quantity(
|
|
177
|
+
type=bool,
|
|
178
|
+
shape=[],
|
|
179
|
+
description="""
|
|
180
|
+
Indicates if the geometry convergence criteria were fulfilled.
|
|
181
|
+
""",
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class GeometryOptimization(SerialSimulation):
|
|
186
|
+
method = SubSection(sub_section=GeometryOptimizationMethod)
|
|
187
|
+
|
|
188
|
+
results = SubSection(sub_section=GeometryOptimizationResults)
|
|
189
|
+
|
|
190
|
+
def _get_geometry_optimization_type(self):
|
|
191
|
+
if not self._systems:
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
def compare_cell(cell1, cell2):
|
|
195
|
+
if (cell1 == cell2).all():
|
|
196
|
+
return None
|
|
197
|
+
else:
|
|
198
|
+
cell1_normed = cell1 / np.linalg.norm(cell1)
|
|
199
|
+
cell2_normed = cell2 / np.linalg.norm(cell2)
|
|
200
|
+
if (cell1_normed == cell2_normed).all():
|
|
201
|
+
return 'cell_volume'
|
|
202
|
+
else:
|
|
203
|
+
return 'cell_shape'
|
|
204
|
+
|
|
205
|
+
if len(self._systems) < 2:
|
|
206
|
+
return 'static'
|
|
207
|
+
|
|
208
|
+
else:
|
|
209
|
+
if self._systems[0].atoms is None or self._systems[-1].atoms is None:
|
|
210
|
+
return 'static'
|
|
211
|
+
|
|
212
|
+
cell_init = self._systems[0].atoms.lattice_vectors
|
|
213
|
+
cell_final = self._systems[-1].atoms.lattice_vectors
|
|
214
|
+
if cell_init is None or cell_final is None:
|
|
215
|
+
return 'static'
|
|
216
|
+
|
|
217
|
+
cell_relaxation = compare_cell(cell_init.magnitude, cell_final.magnitude)
|
|
218
|
+
|
|
219
|
+
if cell_relaxation is not None:
|
|
220
|
+
return cell_relaxation
|
|
221
|
+
|
|
222
|
+
atom_pos_init = self._systems[0].atoms.positions
|
|
223
|
+
atom_pos_final = self._systems[-1].atoms.positions
|
|
224
|
+
if atom_pos_init is None or atom_pos_final is None:
|
|
225
|
+
return 'static'
|
|
226
|
+
|
|
227
|
+
if (atom_pos_init.magnitude == atom_pos_final.magnitude).all():
|
|
228
|
+
return 'static'
|
|
229
|
+
|
|
230
|
+
return 'atomic'
|
|
231
|
+
|
|
232
|
+
def normalize(self, archive, logger):
|
|
233
|
+
super().normalize(archive, logger)
|
|
234
|
+
|
|
235
|
+
if not self.method:
|
|
236
|
+
self.method = GeometryOptimizationMethod()
|
|
237
|
+
self.inputs.append(Link(name=WORKFLOW_METHOD_NAME, section=self.method))
|
|
238
|
+
|
|
239
|
+
if not self.results:
|
|
240
|
+
self.results = GeometryOptimizationResults()
|
|
241
|
+
self.outputs.append(Link(name=WORKFLOW_RESULTS_NAME, section=self.results))
|
|
242
|
+
|
|
243
|
+
if not self.method.type and self._systems:
|
|
244
|
+
self.method.type = self._get_geometry_optimization_type()
|
|
245
|
+
|
|
246
|
+
if not self.results.optimization_steps:
|
|
247
|
+
self.results.optimization_steps = len(self._calculations)
|
|
248
|
+
|
|
249
|
+
energies = []
|
|
250
|
+
invalid = False
|
|
251
|
+
for calc in self._calculations:
|
|
252
|
+
try:
|
|
253
|
+
energy = calc.energy.total.value
|
|
254
|
+
except (IndexError, AttributeError):
|
|
255
|
+
invalid = True
|
|
256
|
+
break
|
|
257
|
+
if energy is None:
|
|
258
|
+
invalid = True
|
|
259
|
+
break
|
|
260
|
+
energies.append(energy.magnitude)
|
|
261
|
+
if invalid:
|
|
262
|
+
logger.warning(
|
|
263
|
+
'Energy not reported for an calculation that is part of a geometry optimization'
|
|
264
|
+
)
|
|
265
|
+
if energies:
|
|
266
|
+
self.results.energies = energies * EnergyEntry.value.unit
|
|
267
|
+
|
|
268
|
+
energy_difference = resolve_difference(energies)
|
|
269
|
+
if not self.results.final_energy_difference and energy_difference is not None:
|
|
270
|
+
self.results.final_energy_difference = (
|
|
271
|
+
energy_difference * EnergyEntry.value.unit
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
if not self.results.final_force_maximum:
|
|
275
|
+
if len(self._calculations) > 0:
|
|
276
|
+
if (
|
|
277
|
+
self._calculations[-1].forces is not None
|
|
278
|
+
and self._calculations[-1].forces.total is not None
|
|
279
|
+
):
|
|
280
|
+
forces = self._calculations[-1].forces.total.value
|
|
281
|
+
if forces is not None:
|
|
282
|
+
max_force = np.max(np.linalg.norm(forces.magnitude, axis=1))
|
|
283
|
+
self.results.final_force_maximum = max_force * forces.units
|
|
284
|
+
|
|
285
|
+
if not self.results.final_displacement_maximum and self._systems:
|
|
286
|
+
|
|
287
|
+
def get_atoms_positions(index):
|
|
288
|
+
system = self._systems[index]
|
|
289
|
+
if (
|
|
290
|
+
not system.atoms
|
|
291
|
+
or system.atoms.positions is None
|
|
292
|
+
or system.atoms.lattice_vectors is None
|
|
293
|
+
):
|
|
294
|
+
return
|
|
295
|
+
try:
|
|
296
|
+
atoms = Atoms(
|
|
297
|
+
positions=system.atoms.positions.magnitude,
|
|
298
|
+
cell=system.atoms.lattice_vectors.magnitude,
|
|
299
|
+
pbc=system.atoms.periodic,
|
|
300
|
+
)
|
|
301
|
+
atoms.wrap()
|
|
302
|
+
return atoms.get_positions()
|
|
303
|
+
except Exception:
|
|
304
|
+
return
|
|
305
|
+
|
|
306
|
+
n_systems = len(self._systems)
|
|
307
|
+
a_pos = get_atoms_positions(n_systems - 1)
|
|
308
|
+
if a_pos is not None:
|
|
309
|
+
for i in range(n_systems - 2, -1, -1):
|
|
310
|
+
b_pos = get_atoms_positions(i)
|
|
311
|
+
if b_pos is None:
|
|
312
|
+
continue
|
|
313
|
+
displacement_maximum = np.max(np.abs(a_pos - b_pos))
|
|
314
|
+
if displacement_maximum > 0:
|
|
315
|
+
self.results.final_displacement_maximum = displacement_maximum
|
|
316
|
+
break
|
|
317
|
+
|
|
318
|
+
if not self.results.is_converged_geometry:
|
|
319
|
+
# we can have several criteria for convergence: energy, force, displacement
|
|
320
|
+
criteria = []
|
|
321
|
+
try:
|
|
322
|
+
criteria.append(
|
|
323
|
+
self.results.final_energy_difference
|
|
324
|
+
<= self.method.convergence_tolerance_energy_difference
|
|
325
|
+
)
|
|
326
|
+
except Exception:
|
|
327
|
+
pass
|
|
328
|
+
|
|
329
|
+
try:
|
|
330
|
+
criteria.append(
|
|
331
|
+
self.results.final_force_maximum
|
|
332
|
+
<= self.method.convergence_tolerance_force_maximum
|
|
333
|
+
)
|
|
334
|
+
except Exception:
|
|
335
|
+
pass
|
|
336
|
+
|
|
337
|
+
try:
|
|
338
|
+
criteria.append(
|
|
339
|
+
self.results.final_displacement_maximum
|
|
340
|
+
<= self.method.convergence_tolerance_displacement_maximum
|
|
341
|
+
)
|
|
342
|
+
except Exception:
|
|
343
|
+
pass
|
|
344
|
+
|
|
345
|
+
# converged when either criterion is met
|
|
346
|
+
if criteria:
|
|
347
|
+
self.results.is_converged_geometry = True in criteria
|
|
348
|
+
|
|
349
|
+
SimulationWorkflowResults.normalize(self.results, archive, logger)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright The NOMAD Authors.
|
|
3
|
+
#
|
|
4
|
+
# This file is part of NOMAD. See https://nomad-lab.eu for further info.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
from nomad.metainfo import SubSection, Quantity, Reference
|
|
19
|
+
from runschema.method import GW as GWMethodology
|
|
20
|
+
from .general import (
|
|
21
|
+
SimulationWorkflowResults,
|
|
22
|
+
ElectronicStructureOutputs,
|
|
23
|
+
DFTMethod,
|
|
24
|
+
BeyondDFT,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class DFTPlusGWResults(SimulationWorkflowResults):
|
|
29
|
+
"""
|
|
30
|
+
Groups DFT and GW outputs: band gaps, DOS, band structures. The ResultsNormalizer
|
|
31
|
+
takes care of adding a label 'DFT' or 'GW' in the method `get_gw_workflow_properties`.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
dft_outputs = SubSection(
|
|
35
|
+
sub_section=ElectronicStructureOutputs.m_def, repeats=False
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
gw_outputs = SubSection(sub_section=ElectronicStructureOutputs.m_def, repeats=False)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class DFTPlusGWMethod(DFTMethod):
|
|
42
|
+
"""
|
|
43
|
+
Specifies both DFT and GW input methodologies: starting XC functional, electrons
|
|
44
|
+
representation (basis set), GW method reference.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
gw_method_ref = Quantity(
|
|
48
|
+
type=Reference(GWMethodology),
|
|
49
|
+
description="""
|
|
50
|
+
Reference to the GW methodology.
|
|
51
|
+
""",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class DFTPlusGW(BeyondDFT):
|
|
56
|
+
"""
|
|
57
|
+
The GW workflow is generated in an extra EntryArchive IF both the DFT SinglePoint
|
|
58
|
+
and the GW SinglePoint EntryArchives are present in the upload.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
method = SubSection(sub_section=DFTPlusGWMethod)
|
|
62
|
+
|
|
63
|
+
results = SubSection(sub_section=DFTPlusGWResults)
|
|
64
|
+
|
|
65
|
+
def normalize(self, archive, logger):
|
|
66
|
+
if not self.results: # creates Results section if not present
|
|
67
|
+
self.results = DFTPlusGWResults()
|
|
68
|
+
|
|
69
|
+
super().normalize(archive, logger)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright The NOMAD Authors.
|
|
3
|
+
#
|
|
4
|
+
# This file is part of NOMAD. See https://nomad-lab.eu for further info.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
from nomad.metainfo import SubSection, Quantity, Reference
|
|
19
|
+
from runschema.method import Method, DMFT as DMFTMethodology
|
|
20
|
+
from .general import (
|
|
21
|
+
SimulationWorkflowResults,
|
|
22
|
+
ElectronicStructureOutputs,
|
|
23
|
+
SimulationWorkflowMethod,
|
|
24
|
+
BeyondDFT,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class DMFTPlusMaxEntResults(SimulationWorkflowResults):
|
|
29
|
+
"""
|
|
30
|
+
Groups DMFT and MaxEnt outputs: greens functions (DMFT, MaxEnt), band gaps (MaxEnt),
|
|
31
|
+
DOS (MaxEnt), band structures (MaxEnt). The ResultsNormalizer takes care of adding a
|
|
32
|
+
label 'DMFT' or 'MaxEnt' in the method `get_maxent_workflow_properties`.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
dmft_outputs = SubSection(
|
|
36
|
+
sub_section=ElectronicStructureOutputs.m_def, repeats=False
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
maxent_outputs = SubSection(
|
|
40
|
+
sub_section=ElectronicStructureOutputs.m_def, repeats=False
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class DMFTPlusMaxEntMethod(SimulationWorkflowMethod):
|
|
45
|
+
"""
|
|
46
|
+
Specifies both DMFT and MaxEnt input methodologies: DMFT method references, MaxEnt method
|
|
47
|
+
reference.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
dmft_method_ref = Quantity(
|
|
51
|
+
type=Reference(DMFTMethodology),
|
|
52
|
+
description="""
|
|
53
|
+
DMFT methodology reference.
|
|
54
|
+
""",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# TODO define MaxEnt metainfo in Method
|
|
58
|
+
maxent_method_ref = Quantity(
|
|
59
|
+
type=Reference(Method),
|
|
60
|
+
description="""
|
|
61
|
+
MaxEnt methodology reference.
|
|
62
|
+
""",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class DMFTPlusMaxEnt(BeyondDFT):
|
|
67
|
+
"""
|
|
68
|
+
The MaxEnt (Maximum Entropy) workflow is generated in an extra EntryArchive IF both
|
|
69
|
+
the DMFT SinglePoint and the MaxEnt SinglePoint EntryArchives are present in the upload.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
method = SubSection(sub_section=DMFTPlusMaxEntMethod)
|
|
73
|
+
|
|
74
|
+
results = SubSection(sub_section=DMFTPlusMaxEntResults)
|
|
75
|
+
|
|
76
|
+
def normalize(self, archive, logger):
|
|
77
|
+
if not self.results: # creates Results section if not present
|
|
78
|
+
self.results = DMFTPlusMaxEntResults()
|
|
79
|
+
|
|
80
|
+
super().normalize(archive, logger)
|