11
11
import numpy as np
12
12
from emmet .core .math import Matrix3D , Vector3D
13
13
from emmet .core .structure import MoleculeMetadata , StructureMetadata
14
+ from emmet .core .task import BaseTaskDocument
14
15
from emmet .core .tasks import get_uri
16
+ from emmet .core .vasp .calc_types .enums import TaskType
15
17
from pydantic import BaseModel , Field
16
18
from pymatgen .core import Molecule , Structure
17
19
from pymatgen .entries .computed_entries import ComputedEntry
@@ -78,56 +80,6 @@ def from_aims_calc_docs(cls, calc_docs: list[Calculation]) -> Self:
78
80
)
79
81
80
82
81
- class Species (BaseModel ):
82
- """A representation of the most important information about each type of species.
83
-
84
- Parameters
85
- ----------
86
- element: str
87
- Element assigned to this atom kind
88
- species_defaults: str
89
- Basis set for this atom kind
90
- """
91
-
92
- element : str = Field (None , description = "Element assigned to this atom kind" )
93
- species_defaults : str = Field (None , description = "Basis set for this atom kind" )
94
-
95
-
96
- class SpeciesSummary (BaseModel ):
97
- """A summary of species defaults.
98
-
99
- Parameters
100
- ----------
101
- species_defaults: Dict[str, .Species]
102
- Dictionary mapping atomic kind labels to their info
103
- """
104
-
105
- species_defaults : dict [str , Species ] = Field (
106
- None , description = "Dictionary mapping atomic kind labels to their info"
107
- )
108
-
109
- @classmethod
110
- def from_species_info (cls , species_info : dict [str , dict [str , Any ]]) -> Self :
111
- """Initialize from the atomic_kind_info dictionary.
112
-
113
- Parameters
114
- ----------
115
- species_info: Dict[str, Dict[str, Any]]
116
- The information for the basis set for the calculation
117
-
118
- Returns
119
- -------
120
- The SpeciesSummary
121
- """
122
- dct : dict [str , dict [str , Any ]] = {"species_defaults" : {}}
123
- for kind , info in species_info .items ():
124
- dct ["species_defaults" ][kind ] = {
125
- "element" : info ["element" ],
126
- "species_defaults" : info ["species_defaults" ],
127
- }
128
- return cls (** dct )
129
-
130
-
131
83
class InputDoc (BaseModel ):
132
84
"""Summary of inputs for an FHI-aims calculation.
133
85
@@ -137,19 +89,24 @@ class InputDoc(BaseModel):
137
89
The input pymatgen Structure or Molecule of the system
138
90
species_info: .SpeciesSummary
139
91
Summary of the species defaults used for each atom kind
92
+ parameters: dict[str, Any]
93
+ The parameters passed in the control.in file
140
94
xc: str
141
95
Exchange-correlation functional used if not the default
142
96
"""
143
97
144
98
structure : Union [Structure , Molecule ] = Field (
145
99
None , description = "The input structure object"
146
100
)
147
- species_info : SpeciesSummary = Field (
148
- None , description = "Summary of the species defaults used for each atom kind "
101
+ parameters : dict [ str , Any ] = Field (
102
+ {} , description = "The input parameters for FHI-aims "
149
103
)
150
104
xc : str = Field (
151
105
None , description = "Exchange-correlation functional used if not the default"
152
106
)
107
+ magnetic_moments : Optional [list [float ]] = Field (
108
+ None , description = "Magnetic moments for each atom"
109
+ )
153
110
154
111
@classmethod
155
112
def from_aims_calc_doc (cls , calc_doc : Calculation ) -> Self :
@@ -165,12 +122,16 @@ def from_aims_calc_doc(cls, calc_doc: Calculation) -> Self:
165
122
.InputDoc
166
123
A summary of the input structure and parameters.
167
124
"""
168
- summary = SpeciesSummary .from_species_info (calc_doc .input .species_info )
125
+ structure = calc_doc .input .structure
126
+ magnetic_moments = None
127
+ if "magmom" in structure .site_properties :
128
+ magnetic_moments = structure .site_properties ["magmom" ]
169
129
170
130
return cls (
171
- structure = calc_doc .input .structure ,
172
- atomic_kind_info = summary ,
173
- xc = str (calc_doc .run_type ),
131
+ structure = structure ,
132
+ parameters = calc_doc .input .parameters ,
133
+ xc = calc_doc .input .parameters ["xc" ],
134
+ magnetic_moments = magnetic_moments ,
174
135
)
175
136
176
137
@@ -383,15 +344,19 @@ def from_data(
383
344
)
384
345
385
346
386
- class AimsTaskDoc (StructureMetadata , MoleculeMetadata ):
347
+ class AimsTaskDoc (BaseTaskDocument , StructureMetadata , MoleculeMetadata ):
387
348
"""Definition of FHI-aims task document.
388
349
389
350
Parameters
390
351
----------
352
+ calc_code: str
353
+ The calculation code used to compute the task
391
354
dir_name: str
392
355
The directory for this FHI-aims task
393
356
last_updated: str
394
357
Timestamp for this task document was last updated
358
+ completed: bool
359
+ Whether this calculation completed
395
360
completed_at: str
396
361
Timestamp for when this task was completed
397
362
input: .InputDoc
@@ -430,11 +395,13 @@ class AimsTaskDoc(StructureMetadata, MoleculeMetadata):
430
395
Additional json loaded from the calculation directory
431
396
"""
432
397
398
+ calc_code : str = "aims"
433
399
dir_name : str = Field (None , description = "The directory for this FHI-aims task" )
434
400
last_updated : str = Field (
435
401
default_factory = datetime_str ,
436
402
description = "Timestamp for this task document was last updated" ,
437
403
)
404
+ completed : bool = Field (None , description = "Whether this calculation completed" )
438
405
completed_at : str = Field (
439
406
None , description = "Timestamp for when this task was completed"
440
407
)
@@ -553,7 +520,9 @@ def from_directory(
553
520
"calcs_reversed" : calcs_reversed ,
554
521
"analysis" : analysis ,
555
522
"tags" : tags ,
523
+ "completed" : calcs_reversed [- 1 ].completed ,
556
524
"completed_at" : calcs_reversed [- 1 ].completed_at ,
525
+ "input" : InputDoc .from_aims_calc_doc (calcs_reversed [- 1 ]),
557
526
"output" : OutputDoc .from_aims_calc_doc (calcs_reversed [- 1 ]),
558
527
"state" : _get_state (calcs_reversed , analysis ),
559
528
"entry" : cls .get_entry (calcs_reversed ),
@@ -597,6 +566,17 @@ def get_entry(
597
566
}
598
567
return ComputedEntry .from_dict (entry_dict )
599
568
569
+ # TARP: This is done because the mangnetism schema assume that VASP
570
+ # TaskTypes are used. I think this should be changed, but that
571
+ # would require modifications in emmet
572
+ @property
573
+ def task_type (self ) -> TaskType :
574
+ """Get the task type of the calculation."""
575
+ if "Relaxation calculation" in self .task_label :
576
+ return TaskType ("Structure Optimization" )
577
+
578
+ return TaskType ("Static" )
579
+
600
580
601
581
def _find_aims_files (
602
582
path : Path | str ,
0 commit comments