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,505 @@
|
|
|
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 typing import List
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
from nomad.datamodel.data import ArchiveSection
|
|
22
|
+
from nomad.metainfo import SubSection, Section, Quantity, Reference, Package
|
|
23
|
+
from nomad.datamodel.metainfo.common import FastAccess
|
|
24
|
+
from nomad.datamodel.metainfo.workflow import Workflow, Link, Task, TaskReference
|
|
25
|
+
from runschema.method import (
|
|
26
|
+
Method,
|
|
27
|
+
XCFunctional,
|
|
28
|
+
BasisSetContainer,
|
|
29
|
+
)
|
|
30
|
+
from runschema.system import System
|
|
31
|
+
from runschema.calculation import (
|
|
32
|
+
Calculation,
|
|
33
|
+
BandGap,
|
|
34
|
+
Dos,
|
|
35
|
+
BandStructure,
|
|
36
|
+
GreensFunctions,
|
|
37
|
+
MagneticShielding,
|
|
38
|
+
ElectricFieldGradient,
|
|
39
|
+
SpinSpinCoupling,
|
|
40
|
+
MagneticSusceptibility,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
m_package = Package()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def resolve_difference(values):
|
|
48
|
+
delta_values = None
|
|
49
|
+
|
|
50
|
+
for n in range(-1, -len(values), -1):
|
|
51
|
+
a = values[n]
|
|
52
|
+
b = values[n - 1]
|
|
53
|
+
if a is None or b is None:
|
|
54
|
+
continue
|
|
55
|
+
delta_values = abs(a - b)
|
|
56
|
+
if delta_values != 0.0:
|
|
57
|
+
break
|
|
58
|
+
|
|
59
|
+
return delta_values
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
INPUT_SYSTEM_NAME = 'Input system'
|
|
63
|
+
OUTPUT_SYSTEM_NAME = 'Output system'
|
|
64
|
+
INPUT_METHOD_NAME = 'Input method'
|
|
65
|
+
INPUT_CALCULATION_NAME = 'Input calculation'
|
|
66
|
+
OUTPUT_CALCULATION_NAME = 'Output calculation'
|
|
67
|
+
WORKFLOW_METHOD_NAME = 'Workflow method'
|
|
68
|
+
WORKFLOW_RESULTS_NAME = 'Workflow results'
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class SimulationWorkflowMethod(ArchiveSection):
|
|
72
|
+
m_def = Section(validate=False)
|
|
73
|
+
|
|
74
|
+
def normalize(self, archive, logger):
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class SimulationWorkflowResults(ArchiveSection):
|
|
79
|
+
m_def = Section(validate=False)
|
|
80
|
+
|
|
81
|
+
calculation_result_ref = Quantity(
|
|
82
|
+
type=Reference(Calculation.m_def),
|
|
83
|
+
shape=[],
|
|
84
|
+
description="""
|
|
85
|
+
Reference to calculation result. In the case of serial workflows, this corresponds
|
|
86
|
+
to the final step in the simulation. For the parallel case, it refers to the reference calculation.
|
|
87
|
+
""",
|
|
88
|
+
categories=[FastAccess],
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
n_calculations = Quantity(
|
|
92
|
+
type=int,
|
|
93
|
+
shape=[],
|
|
94
|
+
description="""
|
|
95
|
+
Number of calculations in workflow.
|
|
96
|
+
""",
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
calculations_ref = Quantity(
|
|
100
|
+
type=Reference(Calculation.m_def),
|
|
101
|
+
shape=['n_calculations'],
|
|
102
|
+
description="""
|
|
103
|
+
List of references to each calculation section in the simulation.
|
|
104
|
+
""",
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def normalize(self, archive, logger):
|
|
108
|
+
calculations = []
|
|
109
|
+
try:
|
|
110
|
+
calculations = archive.run[0].calculation
|
|
111
|
+
except Exception:
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
if not calculations:
|
|
115
|
+
return
|
|
116
|
+
|
|
117
|
+
if not self.calculation_result_ref:
|
|
118
|
+
self.calculation_result_ref = calculations[-1]
|
|
119
|
+
|
|
120
|
+
if not self.calculations_ref:
|
|
121
|
+
self.calculations_ref = calculations
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class SimulationWorkflow(Workflow):
|
|
125
|
+
method = SubSection(sub_section=SimulationWorkflowMethod)
|
|
126
|
+
|
|
127
|
+
results = SubSection(sub_section=SimulationWorkflowResults, categories=[FastAccess])
|
|
128
|
+
|
|
129
|
+
def normalize(self, archive, logger):
|
|
130
|
+
super().normalize(archive, logger)
|
|
131
|
+
|
|
132
|
+
self._calculations: List[Calculation] = []
|
|
133
|
+
self._systems: List[System] = []
|
|
134
|
+
self._methods: List[Method] = []
|
|
135
|
+
try:
|
|
136
|
+
self._calculations = archive.run[-1].calculation
|
|
137
|
+
self._systems = archive.run[-1].system
|
|
138
|
+
self._methods = archive.run[-1].method
|
|
139
|
+
except Exception:
|
|
140
|
+
logger.warning('System, method and calculation required for normalization.')
|
|
141
|
+
pass
|
|
142
|
+
|
|
143
|
+
if not self._calculations:
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
if not self.inputs:
|
|
147
|
+
if self._systems:
|
|
148
|
+
self.m_add_sub_section(
|
|
149
|
+
Workflow.inputs,
|
|
150
|
+
Link(name=INPUT_SYSTEM_NAME, section=self._systems[0]),
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
if self.method is not None:
|
|
154
|
+
self.m_add_sub_section(
|
|
155
|
+
Workflow.inputs,
|
|
156
|
+
Link(name=WORKFLOW_METHOD_NAME, section=self.method),
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
for link in self.inputs:
|
|
160
|
+
if isinstance(link.section, System):
|
|
161
|
+
self.input_structure = link.section
|
|
162
|
+
break
|
|
163
|
+
|
|
164
|
+
if not self.outputs:
|
|
165
|
+
if self._calculations:
|
|
166
|
+
self.m_add_sub_section(
|
|
167
|
+
Workflow.outputs,
|
|
168
|
+
Link(name=OUTPUT_CALCULATION_NAME, section=self._calculations[-1]),
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
if self.results is not None:
|
|
172
|
+
self.m_add_sub_section(
|
|
173
|
+
Workflow.outputs,
|
|
174
|
+
Link(name=WORKFLOW_RESULTS_NAME, section=self.results),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
if not self.tasks:
|
|
178
|
+
current_step = 1
|
|
179
|
+
current_time = None
|
|
180
|
+
inputs = []
|
|
181
|
+
add_inputs, add_outputs = False, False
|
|
182
|
+
tasks = []
|
|
183
|
+
for n, calc in enumerate(self._calculations):
|
|
184
|
+
if calc.time_physical is None or calc.time_calculation is None:
|
|
185
|
+
# all calculation sections should have time info inorder to create workflow tasks
|
|
186
|
+
tasks = []
|
|
187
|
+
break
|
|
188
|
+
|
|
189
|
+
task = Task(outputs=[Link(name=OUTPUT_CALCULATION_NAME, section=calc)])
|
|
190
|
+
# successive tasks in serial if overlap in time duration exists
|
|
191
|
+
if current_time is None:
|
|
192
|
+
current_time = calc.time_physical
|
|
193
|
+
start_time = calc.time_physical - calc.time_calculation
|
|
194
|
+
if start_time and (
|
|
195
|
+
start_time > current_time or np.isclose(start_time, current_time)
|
|
196
|
+
):
|
|
197
|
+
task.inputs = inputs
|
|
198
|
+
inputs = []
|
|
199
|
+
current_step += 1
|
|
200
|
+
else:
|
|
201
|
+
if tasks:
|
|
202
|
+
for input in tasks[-1].inputs:
|
|
203
|
+
if input.name == INPUT_METHOD_NAME:
|
|
204
|
+
continue
|
|
205
|
+
task.m_add_sub_section(Task.inputs, input)
|
|
206
|
+
if calc.method_ref:
|
|
207
|
+
task.m_add_sub_section(
|
|
208
|
+
Task.inputs,
|
|
209
|
+
Link(name=INPUT_METHOD_NAME, section=calc.method_ref),
|
|
210
|
+
)
|
|
211
|
+
if calc.system_ref:
|
|
212
|
+
inputs.append(Link(name=INPUT_SYSTEM_NAME, section=calc.system_ref))
|
|
213
|
+
task.m_add_sub_section(
|
|
214
|
+
Task.outputs,
|
|
215
|
+
Link(name=OUTPUT_SYSTEM_NAME, section=calc.system_ref),
|
|
216
|
+
)
|
|
217
|
+
else:
|
|
218
|
+
inputs.append(Link(name=INPUT_CALCULATION_NAME, section=calc))
|
|
219
|
+
task.name = f'Step {current_step}'
|
|
220
|
+
tasks.append(task)
|
|
221
|
+
current_time = max(current_time, calc.time_physical)
|
|
222
|
+
# add input if first calc in tasks
|
|
223
|
+
add_inputs = add_inputs or n == 0
|
|
224
|
+
# add output if last calc in tasks
|
|
225
|
+
add_outputs = add_outputs or n == len(self._calculations) - 1
|
|
226
|
+
for task in tasks:
|
|
227
|
+
# add workflow inputs to first parallel tasks
|
|
228
|
+
if task.name == 'Step 1' and add_inputs:
|
|
229
|
+
task.inputs.extend(
|
|
230
|
+
[input for input in self.inputs if input not in task.inputs]
|
|
231
|
+
)
|
|
232
|
+
# add outputs of last parallel tasks to workflow outputs
|
|
233
|
+
if task.name == f'Step {current_step}' and add_outputs:
|
|
234
|
+
self.outputs.extend(
|
|
235
|
+
[
|
|
236
|
+
output
|
|
237
|
+
for output in task.outputs
|
|
238
|
+
if output not in self.outputs
|
|
239
|
+
]
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
self.tasks = tasks
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class ParallelSimulation(SimulationWorkflow):
|
|
246
|
+
def normalize(self, archive, logger):
|
|
247
|
+
super().normalize(archive, logger)
|
|
248
|
+
|
|
249
|
+
if not self.tasks:
|
|
250
|
+
for n, calculation in enumerate(self._calculations):
|
|
251
|
+
inputs, outputs = (
|
|
252
|
+
[],
|
|
253
|
+
[Link(name=OUTPUT_CALCULATION_NAME, section=calculation)],
|
|
254
|
+
)
|
|
255
|
+
if self._calculations[n].system_ref:
|
|
256
|
+
inputs.append(
|
|
257
|
+
Link(
|
|
258
|
+
name=INPUT_SYSTEM_NAME,
|
|
259
|
+
section=self._calculations[n].system_ref,
|
|
260
|
+
)
|
|
261
|
+
)
|
|
262
|
+
elif len(self._calculations) == len(self._systems):
|
|
263
|
+
inputs.append(
|
|
264
|
+
Link(name=INPUT_SYSTEM_NAME, section=self._systems[n])
|
|
265
|
+
)
|
|
266
|
+
else:
|
|
267
|
+
continue
|
|
268
|
+
if self._calculations[n].method_ref:
|
|
269
|
+
inputs.append(
|
|
270
|
+
Link(
|
|
271
|
+
name=INPUT_METHOD_NAME,
|
|
272
|
+
section=self._calculations[n].method_ref,
|
|
273
|
+
)
|
|
274
|
+
)
|
|
275
|
+
elif len(self._calculations) == len(self._methods):
|
|
276
|
+
inputs.append(
|
|
277
|
+
Link(name=INPUT_METHOD_NAME, section=self._methods[n])
|
|
278
|
+
)
|
|
279
|
+
elif len(self._methods) == 1:
|
|
280
|
+
inputs.append(
|
|
281
|
+
Link(name=INPUT_METHOD_NAME, section=self._methods[0])
|
|
282
|
+
)
|
|
283
|
+
self.tasks.append(
|
|
284
|
+
Task(name=f'Calculation {n}', inputs=inputs, outputs=outputs)
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class SerialSimulation(SimulationWorkflow):
|
|
289
|
+
def normalize(self, archive, logger):
|
|
290
|
+
super().normalize(archive, logger)
|
|
291
|
+
|
|
292
|
+
if not self.tasks:
|
|
293
|
+
previous_structure = None
|
|
294
|
+
for n, calculation in enumerate(self._calculations):
|
|
295
|
+
inputs, outputs = (
|
|
296
|
+
[],
|
|
297
|
+
[Link(name=OUTPUT_CALCULATION_NAME, section=calculation)],
|
|
298
|
+
)
|
|
299
|
+
if calculation.system_ref:
|
|
300
|
+
input_structure = (
|
|
301
|
+
self.input_structure
|
|
302
|
+
if n == 0
|
|
303
|
+
else self._calculations[n - 1].system_ref
|
|
304
|
+
)
|
|
305
|
+
if not input_structure:
|
|
306
|
+
input_structure = previous_structure
|
|
307
|
+
if input_structure:
|
|
308
|
+
inputs.append(
|
|
309
|
+
Link(name=INPUT_SYSTEM_NAME, section=input_structure)
|
|
310
|
+
)
|
|
311
|
+
previous_structure = calculation.system_ref
|
|
312
|
+
outputs.append(
|
|
313
|
+
Link(name=OUTPUT_SYSTEM_NAME, section=calculation.system_ref)
|
|
314
|
+
)
|
|
315
|
+
elif len(self._calculations) == len(self._systems):
|
|
316
|
+
inputs.append(
|
|
317
|
+
Link(
|
|
318
|
+
name=INPUT_SYSTEM_NAME,
|
|
319
|
+
section=self.input_structure
|
|
320
|
+
if n == 0
|
|
321
|
+
else self._systems[n - 1],
|
|
322
|
+
)
|
|
323
|
+
)
|
|
324
|
+
outputs.append(
|
|
325
|
+
Link(name=OUTPUT_SYSTEM_NAME, section=self._systems[n])
|
|
326
|
+
)
|
|
327
|
+
else:
|
|
328
|
+
continue
|
|
329
|
+
if calculation.method_ref:
|
|
330
|
+
inputs.append(
|
|
331
|
+
Link(name=INPUT_METHOD_NAME, section=calculation.method_ref)
|
|
332
|
+
)
|
|
333
|
+
elif len(self._calculations) == len(self._methods):
|
|
334
|
+
inputs.append(
|
|
335
|
+
Link(name=INPUT_METHOD_NAME, section=self._methods[n])
|
|
336
|
+
)
|
|
337
|
+
elif len(self._methods) == 1:
|
|
338
|
+
inputs.append(
|
|
339
|
+
Link(name=INPUT_METHOD_NAME, section=self._methods[0])
|
|
340
|
+
)
|
|
341
|
+
self.tasks.append(
|
|
342
|
+
Task(name=f'Step {n}', inputs=inputs, outputs=outputs)
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
class BeyondDFT(SerialSimulation):
|
|
347
|
+
"""
|
|
348
|
+
Base class used to normalize standard workflows beyond DFT containing two specific
|
|
349
|
+
SinglePoint tasks (GWWorkflow = DFT + GW, DMFTWorkflow = DFT + DMFT,
|
|
350
|
+
MaxEntWorkflow = DMFT + MaxEnt, and so on) and store the outputs in the self.results
|
|
351
|
+
section.
|
|
352
|
+
"""
|
|
353
|
+
|
|
354
|
+
def _resolve_outputs_section(self, output_section, task: TaskReference) -> None:
|
|
355
|
+
"""
|
|
356
|
+
Resolves the output_section of a task and stores the results in the output_section.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
task (TaskReference): The task from which the outputs are got.
|
|
360
|
+
"""
|
|
361
|
+
for name, section in output_section.m_def.all_quantities.items():
|
|
362
|
+
name = f'{name}_electronic' if name in ['dos', 'band_structure'] else name
|
|
363
|
+
try:
|
|
364
|
+
calc_section = getattr(task.outputs[-1].section, name)
|
|
365
|
+
if calc_section:
|
|
366
|
+
output_section.m_set(section, calc_section)
|
|
367
|
+
except Exception:
|
|
368
|
+
continue
|
|
369
|
+
|
|
370
|
+
def get_electronic_structure_workflow_results(self, task_map: dict) -> None:
|
|
371
|
+
"""
|
|
372
|
+
Gets the standard electronic structure workflow results section by resolving the
|
|
373
|
+
outputs specified in the `task_map`.
|
|
374
|
+
|
|
375
|
+
Args:
|
|
376
|
+
task_map (dict): The dictionary used to resolve the outputs sections.
|
|
377
|
+
"""
|
|
378
|
+
for method, task in task_map.items():
|
|
379
|
+
outputs = ElectronicStructureOutputs()
|
|
380
|
+
self._resolve_outputs_section(outputs, task)
|
|
381
|
+
setattr(self.results, f'{method}_outputs', outputs)
|
|
382
|
+
|
|
383
|
+
def normalize(self, archive, logger):
|
|
384
|
+
super().normalize(archive, logger)
|
|
385
|
+
|
|
386
|
+
if len(self.tasks) != 2:
|
|
387
|
+
logger.error('Expected two tasks.')
|
|
388
|
+
return
|
|
389
|
+
|
|
390
|
+
# We extract the workflow name from the tasks names
|
|
391
|
+
self.name = '+'.join([task.name for task in self.tasks if task.name])
|
|
392
|
+
task_map = {
|
|
393
|
+
task.name.lower(): self.tasks[n] for n, task in enumerate(self.tasks)
|
|
394
|
+
}
|
|
395
|
+
# Resolve workflow2.results for each standard BeyondDFT workflow
|
|
396
|
+
if self.name == 'DFT+GW':
|
|
397
|
+
self.get_electronic_structure_workflow_results(task_map)
|
|
398
|
+
elif self.name == 'TB+DMFT': # TODO extend for DFT tasks
|
|
399
|
+
self.get_electronic_structure_workflow_results(task_map)
|
|
400
|
+
elif self.name == 'DMFT+MaxEnt':
|
|
401
|
+
self.get_electronic_structure_workflow_results(task_map)
|
|
402
|
+
elif self.name == 'FirstPrinciples+TB':
|
|
403
|
+
task_map['first_principles'] = task_map.pop('firstprinciples')
|
|
404
|
+
self.get_electronic_structure_workflow_results(task_map)
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
class DFTMethod(SimulationWorkflowMethod):
|
|
408
|
+
"""
|
|
409
|
+
Base class defining the DFT input methodologies: starting XC functional and electrons
|
|
410
|
+
representation (basis set).
|
|
411
|
+
"""
|
|
412
|
+
|
|
413
|
+
starting_point = Quantity(
|
|
414
|
+
type=Reference(XCFunctional),
|
|
415
|
+
description="""
|
|
416
|
+
Reference to the starting point (XC functional or HF) used.
|
|
417
|
+
""",
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
electrons_representation = Quantity(
|
|
421
|
+
type=Reference(BasisSetContainer),
|
|
422
|
+
description="""
|
|
423
|
+
Reference to the basis set used.
|
|
424
|
+
""",
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
class ElectronicStructureOutputs(SimulationWorkflowResults):
|
|
429
|
+
"""
|
|
430
|
+
Base class defining the typical output properties of any electronic structure
|
|
431
|
+
SinglePoint calculation: DFT, TB, DMFT, GW, MaxEnt, XS.
|
|
432
|
+
"""
|
|
433
|
+
|
|
434
|
+
band_gap = Quantity(
|
|
435
|
+
type=Reference(BandGap),
|
|
436
|
+
shape=['*'],
|
|
437
|
+
description="""
|
|
438
|
+
Reference to the band gap section.
|
|
439
|
+
""",
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
dos = Quantity(
|
|
443
|
+
type=Reference(Dos),
|
|
444
|
+
shape=['*'],
|
|
445
|
+
description="""
|
|
446
|
+
Reference to the density of states section.
|
|
447
|
+
""",
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
band_structure = Quantity(
|
|
451
|
+
type=Reference(BandStructure),
|
|
452
|
+
shape=['*'],
|
|
453
|
+
description="""
|
|
454
|
+
Reference to the band structure section.
|
|
455
|
+
""",
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
greens_functions = Quantity(
|
|
459
|
+
type=Reference(GreensFunctions),
|
|
460
|
+
shape=['*'],
|
|
461
|
+
description="""
|
|
462
|
+
Ref to the Green functions section.
|
|
463
|
+
""",
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
class MagneticOutputs(SimulationWorkflowResults):
|
|
468
|
+
"""
|
|
469
|
+
Base class defining the typical output properties of magnetic SinglePoint calculations.
|
|
470
|
+
"""
|
|
471
|
+
|
|
472
|
+
magnetic_shielding = Quantity(
|
|
473
|
+
type=Reference(MagneticShielding),
|
|
474
|
+
shape=['*'],
|
|
475
|
+
description="""
|
|
476
|
+
Reference to the magnetic shielding tensors.
|
|
477
|
+
""",
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
electric_field_gradient = Quantity(
|
|
481
|
+
type=Reference(ElectricFieldGradient),
|
|
482
|
+
shape=['*'],
|
|
483
|
+
description="""
|
|
484
|
+
Reference to the electric field gradient tensors.
|
|
485
|
+
""",
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
spin_spin_coupling = Quantity(
|
|
489
|
+
type=Reference(SpinSpinCoupling),
|
|
490
|
+
shape=['*'],
|
|
491
|
+
description="""
|
|
492
|
+
Reference to the spin-spin coupling tensors.
|
|
493
|
+
""",
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
magnetic_susceptibility_nmr = Quantity(
|
|
497
|
+
type=Reference(MagneticSusceptibility),
|
|
498
|
+
shape=['*'],
|
|
499
|
+
description="""
|
|
500
|
+
Reference to the magnetic susceptibility tensors.
|
|
501
|
+
""",
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
m_package.__init_metainfo__()
|