qupled 1.3.2__cp312-cp312-macosx_14_0_arm64.whl → 1.3.4__cp312-cp312-macosx_14_0_arm64.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.
- qupled/.dylibs/libSQLiteCpp.0.dylib +0 -0
- qupled/.dylibs/{libsqlite3.3.50.1.dylib → libsqlite3.3.50.2.dylib} +0 -0
- qupled/database.py +66 -28
- qupled/esa.py +11 -5
- qupled/hf.py +134 -73
- qupled/include/fmt/args.h +235 -0
- qupled/include/fmt/chrono.h +2240 -0
- qupled/include/fmt/color.h +643 -0
- qupled/include/fmt/compile.h +535 -0
- qupled/include/fmt/core.h +2969 -0
- qupled/include/fmt/format-inl.h +1678 -0
- qupled/include/fmt/format.h +4535 -0
- qupled/include/fmt/os.h +455 -0
- qupled/include/fmt/ostream.h +245 -0
- qupled/include/fmt/printf.h +675 -0
- qupled/include/fmt/ranges.h +738 -0
- qupled/include/fmt/std.h +537 -0
- qupled/include/fmt/xchar.h +259 -0
- qupled/lib/cmake/fmt/fmt-config-version.cmake +43 -0
- qupled/lib/cmake/fmt/fmt-config.cmake +31 -0
- qupled/lib/cmake/fmt/fmt-targets-release.cmake +19 -0
- qupled/lib/cmake/fmt/fmt-targets.cmake +116 -0
- qupled/lib/libfmt.a +0 -0
- qupled/lib/pkgconfig/fmt.pc +11 -0
- qupled/mpi.py +104 -69
- qupled/native.cpython-312-darwin.so +0 -0
- qupled/qstls.py +13 -10
- qupled/qstlsiet.py +13 -10
- qupled/qvsstls.py +13 -11
- qupled/rpa.py +11 -7
- qupled/serialize.py +43 -0
- qupled/stls.py +29 -26
- qupled/stlsiet.py +34 -25
- qupled/timer.py +33 -0
- qupled/vsstls.py +44 -42
- {qupled-1.3.2.dist-info → qupled-1.3.4.dist-info}/METADATA +1 -1
- qupled-1.3.4.dist-info/RECORD +45 -0
- qupled-1.3.2.dist-info/RECORD +0 -24
- {qupled-1.3.2.dist-info → qupled-1.3.4.dist-info}/WHEEL +0 -0
- {qupled-1.3.2.dist-info → qupled-1.3.4.dist-info}/licenses/LICENSE +0 -0
- {qupled-1.3.2.dist-info → qupled-1.3.4.dist-info}/top_level.txt +0 -0
Binary file
|
Binary file
|
qupled/database.py
CHANGED
@@ -10,8 +10,6 @@ import sqlalchemy as sql
|
|
10
10
|
from sqlalchemy.dialects.sqlite import insert as sqlite_insert
|
11
11
|
import blosc2
|
12
12
|
|
13
|
-
from . import mpi
|
14
|
-
|
15
13
|
|
16
14
|
class DataBaseHandler:
|
17
15
|
"""
|
@@ -42,10 +40,9 @@ class DataBaseHandler:
|
|
42
40
|
SUCCESS = "SUCCESS"
|
43
41
|
FAILED = "FAILED"
|
44
42
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
}
|
43
|
+
class ConflictMode(Enum):
|
44
|
+
FAIL = "FAIL"
|
45
|
+
UPDATE = "UPDATE"
|
49
46
|
|
50
47
|
def __init__(self, database_name: str | None = None):
|
51
48
|
"""
|
@@ -76,7 +73,6 @@ class DataBaseHandler:
|
|
76
73
|
self.result_table = self._build_results_table()
|
77
74
|
self.run_id: int | None = None
|
78
75
|
|
79
|
-
@mpi.MPI.run_only_on_root
|
80
76
|
def insert_run(self, inputs):
|
81
77
|
"""
|
82
78
|
Inserts a new run into the database by storing the provided inputs and results.
|
@@ -91,7 +87,6 @@ class DataBaseHandler:
|
|
91
87
|
self._insert_run(inputs, self.RunStatus.RUNNING)
|
92
88
|
self.insert_inputs(inputs.__dict__)
|
93
89
|
|
94
|
-
@mpi.MPI.run_only_on_root
|
95
90
|
def insert_inputs(self, inputs: dict[str, any]):
|
96
91
|
"""
|
97
92
|
Inserts input data into the database for the current run.
|
@@ -114,8 +109,11 @@ class DataBaseHandler:
|
|
114
109
|
sql_mapping = lambda value: (self._to_json(value))
|
115
110
|
self._insert_from_dict(self.input_table, inputs, sql_mapping)
|
116
111
|
|
117
|
-
|
118
|
-
|
112
|
+
def insert_results(
|
113
|
+
self,
|
114
|
+
results: dict[str, any],
|
115
|
+
conflict_mode: ConflictMode = ConflictMode.FAIL,
|
116
|
+
):
|
119
117
|
"""
|
120
118
|
Inserts the given results into the database table associated with this instance.
|
121
119
|
|
@@ -130,7 +128,9 @@ class DataBaseHandler:
|
|
130
128
|
"""
|
131
129
|
if self.run_id is not None:
|
132
130
|
sql_mapping = lambda value: (self._to_bytes(value))
|
133
|
-
self._insert_from_dict(
|
131
|
+
self._insert_from_dict(
|
132
|
+
self.result_table, results, sql_mapping, conflict_mode
|
133
|
+
)
|
134
134
|
|
135
135
|
def inspect_runs(self) -> list[dict[str, any]]:
|
136
136
|
"""
|
@@ -149,26 +149,27 @@ class DataBaseHandler:
|
|
149
149
|
rows = self._execute(statement).mappings().all()
|
150
150
|
return [{key: row[key] for key in row.keys()} for row in rows]
|
151
151
|
|
152
|
-
def update_run_status(self, status:
|
152
|
+
def update_run_status(self, status: RunStatus) -> None:
|
153
153
|
"""
|
154
|
-
|
154
|
+
Update the status of a run in the database.
|
155
155
|
|
156
156
|
Args:
|
157
|
-
status (
|
158
|
-
code is not found in the INT_TO_RUN_STATUS mapping, the
|
159
|
-
status will default to RunStatus.FAILED.
|
157
|
+
status (RunStatus): The new status to set for the run.
|
160
158
|
|
161
159
|
Returns:
|
162
160
|
None
|
161
|
+
|
162
|
+
Notes:
|
163
|
+
This method updates the status of the run identified by `self.run_id` in the run table.
|
164
|
+
If `self.run_id` is None, no update is performed.
|
163
165
|
"""
|
164
166
|
if self.run_id is not None:
|
165
|
-
new_status = self.INT_TO_RUN_STATUS.get(status, self.RunStatus.FAILED)
|
166
167
|
statement = (
|
167
168
|
sql.update(self.run_table)
|
168
169
|
.where(
|
169
170
|
self.run_table.c[self.TableKeys.PRIMARY_KEY.value] == self.run_id
|
170
171
|
)
|
171
|
-
.values({self.TableKeys.STATUS.value:
|
172
|
+
.values({self.TableKeys.STATUS.value: status.value})
|
172
173
|
)
|
173
174
|
self._execute(statement)
|
174
175
|
|
@@ -241,8 +242,6 @@ class DataBaseHandler:
|
|
241
242
|
sql_mapping = lambda value: (self._from_bytes(value))
|
242
243
|
return self._get(self.result_table, run_id, names, sql_mapping)
|
243
244
|
|
244
|
-
@mpi.MPI.synchronize_ranks
|
245
|
-
@mpi.MPI.run_only_on_root
|
246
245
|
def delete_run(self, run_id: int) -> None:
|
247
246
|
"""
|
248
247
|
Deletes a run entry from the database based on the provided run ID.
|
@@ -390,16 +389,15 @@ class DataBaseHandler:
|
|
390
389
|
sql.PrimaryKeyConstraint(
|
391
390
|
self.TableKeys.RUN_ID.value, self.TableKeys.NAME.value
|
392
391
|
),
|
392
|
+
sql.Index(f"idx_{table_name}_run_id", self.TableKeys.RUN_ID.value),
|
393
|
+
sql.Index(f"idx_{table_name}_name", self.TableKeys.NAME.value),
|
393
394
|
)
|
394
395
|
self._create_table(table)
|
395
396
|
return table
|
396
397
|
|
397
|
-
@mpi.MPI.synchronize_ranks
|
398
|
-
@mpi.MPI.run_only_on_root
|
399
398
|
def _create_table(self, table):
|
400
399
|
table.create(self.engine, checkfirst=True)
|
401
400
|
|
402
|
-
@mpi.MPI.run_only_on_root
|
403
401
|
def _insert_run(self, inputs: any, status: RunStatus):
|
404
402
|
"""
|
405
403
|
Inserts a new run entry into the database.
|
@@ -454,11 +452,15 @@ class DataBaseHandler:
|
|
454
452
|
def _set_pragma(dbapi_connection, connection_record):
|
455
453
|
cursor = dbapi_connection.cursor()
|
456
454
|
cursor.execute("PRAGMA foreign_keys=ON")
|
455
|
+
cursor.execute("PRAGMA journal_mode=WAL")
|
457
456
|
cursor.close()
|
458
457
|
|
459
|
-
@mpi.MPI.run_only_on_root
|
460
458
|
def _insert_from_dict(
|
461
|
-
self,
|
459
|
+
self,
|
460
|
+
table,
|
461
|
+
data: dict[str, any],
|
462
|
+
sql_mapping: Callable[[any], any],
|
463
|
+
conflict_mode: ConflictMode = ConflictMode.FAIL,
|
462
464
|
) -> None:
|
463
465
|
"""
|
464
466
|
Inserts data into a specified table by mapping values through a provided SQL mapping function.
|
@@ -473,10 +475,46 @@ class DataBaseHandler:
|
|
473
475
|
"""
|
474
476
|
for name, value in data.items():
|
475
477
|
if mapped_value := sql_mapping(value):
|
476
|
-
self._insert(table, name, mapped_value)
|
478
|
+
self._insert(table, name, mapped_value, conflict_mode)
|
479
|
+
|
480
|
+
def _insert(
|
481
|
+
self,
|
482
|
+
table: sql.Table,
|
483
|
+
name: str,
|
484
|
+
value: any,
|
485
|
+
conflict_mode: ConflictMode = ConflictMode.FAIL,
|
486
|
+
):
|
487
|
+
"""
|
488
|
+
Inserts a record into the specified SQL table with the given name and value, handling conflicts according to the specified mode.
|
489
|
+
Args:
|
490
|
+
table (sql.Table): The SQLAlchemy table object where the record will be inserted.
|
491
|
+
name (str): The name/key associated with the value to insert.
|
492
|
+
value (any): The value to be inserted into the table.
|
493
|
+
conflict_mode (ConflictMode, optional): Specifies how to handle conflicts on unique constraints.
|
494
|
+
Defaults to ConflictMode.FAIL. If set to ConflictMode.UPDATE, existing records with the same
|
495
|
+
run_id and name will be updated with the new value.
|
496
|
+
Returns:
|
497
|
+
None
|
498
|
+
Raises:
|
499
|
+
Any exceptions raised by the underlying database execution.
|
500
|
+
"""
|
501
|
+
data = {
|
502
|
+
self.TableKeys.RUN_ID.value: self.run_id,
|
503
|
+
self.TableKeys.NAME.value: name,
|
504
|
+
self.TableKeys.VALUE.value: value,
|
505
|
+
}
|
506
|
+
statement = sqlite_insert(table).values(data)
|
507
|
+
if conflict_mode == self.ConflictMode.UPDATE:
|
508
|
+
statement = statement.on_conflict_do_update(
|
509
|
+
index_elements=[
|
510
|
+
self.TableKeys.RUN_ID.value,
|
511
|
+
self.TableKeys.NAME.value,
|
512
|
+
],
|
513
|
+
set_={self.TableKeys.VALUE.value: value},
|
514
|
+
)
|
515
|
+
self._execute(statement)
|
477
516
|
|
478
|
-
|
479
|
-
def _insert(self, table: sql.Table, name: str, value: any):
|
517
|
+
def _insert_with_update(self, table: sql.Table, name: str, value: any):
|
480
518
|
"""
|
481
519
|
Inserts a record into the specified SQL table or updates it if a conflict occurs.
|
482
520
|
|
qupled/esa.py
CHANGED
@@ -2,13 +2,17 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from . import hf
|
4
4
|
from . import native
|
5
|
+
from . import serialize
|
5
6
|
|
6
7
|
|
7
|
-
class
|
8
|
+
class Solver(hf.Solver):
|
8
9
|
"""
|
9
10
|
Class used to solve the ESA scheme.
|
10
11
|
"""
|
11
12
|
|
13
|
+
# Native classes used to solve the scheme
|
14
|
+
native_scheme_cls = native.ESA
|
15
|
+
|
12
16
|
def __init__(self):
|
13
17
|
super().__init__()
|
14
18
|
self.results: hf.Result = hf.Result()
|
@@ -16,12 +20,14 @@ class ESA(hf.HF):
|
|
16
20
|
self.native_scheme_cls = native.ESA
|
17
21
|
|
18
22
|
|
23
|
+
@serialize.serializable_dataclass
|
19
24
|
class Input(hf.Input):
|
20
25
|
"""
|
21
26
|
Class used to manage the input for the :obj:`qupled.esa.ESA` class.
|
22
27
|
"""
|
23
28
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
29
|
+
theory: str = "ESA"
|
30
|
+
|
31
|
+
|
32
|
+
if __name__ == "__main__":
|
33
|
+
Solver.run_mpi_worker(Input, hf.Result)
|
qupled/hf.py
CHANGED
@@ -1,17 +1,34 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import json
|
4
|
+
|
5
|
+
from dataclasses import field
|
6
|
+
from pathlib import Path
|
7
|
+
|
3
8
|
import numpy as np
|
4
9
|
|
5
10
|
from . import database
|
6
11
|
from . import mpi
|
7
12
|
from . import native
|
13
|
+
from . import serialize
|
14
|
+
from . import timer
|
8
15
|
|
9
16
|
|
10
|
-
class
|
17
|
+
class Solver:
|
11
18
|
"""
|
12
19
|
Class used to solve the HF scheme.
|
13
20
|
"""
|
14
21
|
|
22
|
+
# Mapping of native scheme status to run status in the database
|
23
|
+
NATIVE_TO_RUN_STATUS = {
|
24
|
+
0: database.DataBaseHandler.RunStatus.SUCCESS,
|
25
|
+
1: database.DataBaseHandler.RunStatus.FAILED,
|
26
|
+
}
|
27
|
+
|
28
|
+
# Native classes used to solve the scheme
|
29
|
+
native_scheme_cls = native.HF
|
30
|
+
native_inputs_cls = native.Input
|
31
|
+
|
15
32
|
def __init__(self):
|
16
33
|
self.inputs: Input = None
|
17
34
|
"""The inputs used to solve the scheme. Default = ``None``"""
|
@@ -19,8 +36,6 @@ class HF:
|
|
19
36
|
"""The results obtained by solving the scheme"""
|
20
37
|
# Undocumented properties
|
21
38
|
self.db_handler = database.DataBaseHandler()
|
22
|
-
self.native_scheme_cls = native.HF
|
23
|
-
self.native_inputs_cls = native.Input
|
24
39
|
self.native_scheme_status = None
|
25
40
|
|
26
41
|
@property
|
@@ -33,8 +48,7 @@ class HF:
|
|
33
48
|
"""
|
34
49
|
return self.db_handler.run_id
|
35
50
|
|
36
|
-
@
|
37
|
-
@mpi.MPI.synchronize_ranks
|
51
|
+
@timer.timer
|
38
52
|
def compute(self, inputs: Input):
|
39
53
|
"""
|
40
54
|
Solves the scheme and saves the results.
|
@@ -47,7 +61,6 @@ class HF:
|
|
47
61
|
self._compute_native()
|
48
62
|
self._save()
|
49
63
|
|
50
|
-
@mpi.MPI.run_only_on_root
|
51
64
|
def compute_rdf(self, rdf_grid: np.ndarray = None):
|
52
65
|
"""
|
53
66
|
Computes the radial distribution function (RDF) using the provided RDF grid.
|
@@ -61,7 +74,8 @@ class HF:
|
|
61
74
|
if self.results is not None:
|
62
75
|
self.results.compute_rdf(rdf_grid)
|
63
76
|
self.db_handler.insert_results(
|
64
|
-
{"rdf": self.results.rdf, "rdf_grid": self.results.rdf_grid}
|
77
|
+
{"rdf": self.results.rdf, "rdf_grid": self.results.rdf_grid},
|
78
|
+
conflict_mode=database.DataBaseHandler.ConflictMode.UPDATE,
|
65
79
|
)
|
66
80
|
|
67
81
|
def _add_run_to_database(self):
|
@@ -76,6 +90,19 @@ class HF:
|
|
76
90
|
self.inputs.database_info.run_id = self.run_id
|
77
91
|
|
78
92
|
def _compute_native(self):
|
93
|
+
"""
|
94
|
+
Determines whether to execute the native computation in parallel or serial mode.
|
95
|
+
|
96
|
+
Checks if MPI (Message Passing Interface) is available and if the number of requested processes
|
97
|
+
is greater than one. If both conditions are met, runs the computation in parallel; otherwise,
|
98
|
+
runs it in serial mode.
|
99
|
+
"""
|
100
|
+
if native.uses_mpi:
|
101
|
+
self._compute_native_mpi()
|
102
|
+
else:
|
103
|
+
self._compute_native_serial()
|
104
|
+
|
105
|
+
def _compute_native_serial(self):
|
79
106
|
"""
|
80
107
|
Computes the native representation of the inputs and processes the results.
|
81
108
|
|
@@ -91,7 +118,32 @@ class HF:
|
|
91
118
|
self.native_scheme_status = scheme.compute()
|
92
119
|
self.results.from_native(scheme)
|
93
120
|
|
94
|
-
|
121
|
+
def _compute_native_mpi(self):
|
122
|
+
"""
|
123
|
+
Executes a native MPI computation workflow.
|
124
|
+
|
125
|
+
This method performs the following steps:
|
126
|
+
1. Writes the necessary input files for the MPI computation using `mpi.write_inputs`.
|
127
|
+
2. Launches the MPI execution by calling `mpi.launch_mpi_execution` with the current module and the specified number of processes.
|
128
|
+
3. Reads the computation results using `mpi.read_results` and assigns them to `self.results`.
|
129
|
+
4. Cleans up any temporary files generated during the computation with `mpi.clean_files`.
|
130
|
+
"""
|
131
|
+
mpi.write_inputs(self.inputs)
|
132
|
+
mpi.launch_mpi_execution(self.__module__, self.inputs.processes)
|
133
|
+
self.native_scheme_status = mpi.read_status()
|
134
|
+
self.results = mpi.read_results(type(self.results))
|
135
|
+
mpi.clean_files()
|
136
|
+
|
137
|
+
@classmethod
|
138
|
+
def run_mpi_worker(cls, InputCls, ResultCls):
|
139
|
+
inputs = mpi.read_inputs(InputCls)
|
140
|
+
native_inputs = cls.native_inputs_cls()
|
141
|
+
inputs.to_native(native_inputs)
|
142
|
+
scheme = cls.native_scheme_cls(native_inputs)
|
143
|
+
status = scheme.compute()
|
144
|
+
mpi.write_results(scheme, ResultCls)
|
145
|
+
mpi.write_status(scheme, status)
|
146
|
+
|
95
147
|
def _save(self):
|
96
148
|
"""
|
97
149
|
Saves the current state and results to the database.
|
@@ -99,56 +151,53 @@ class HF:
|
|
99
151
|
This method updates the run status in the database using the current
|
100
152
|
native scheme status and inserts the results into the database.
|
101
153
|
"""
|
102
|
-
self.
|
154
|
+
run_status = self.NATIVE_TO_RUN_STATUS.get(
|
155
|
+
self.native_scheme_status, database.DataBaseHandler.RunStatus.FAILED
|
156
|
+
)
|
157
|
+
self.db_handler.update_run_status(run_status)
|
103
158
|
self.db_handler.insert_results(self.results.__dict__)
|
104
159
|
|
105
160
|
|
161
|
+
@serialize.serializable_dataclass
|
106
162
|
class Input:
|
107
163
|
"""
|
108
164
|
Class used to store the inputs for the :obj:`qupled.hf.HF` class.
|
109
165
|
"""
|
110
166
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
self.frequency_cutoff: float = 10.0
|
128
|
-
"""Cutoff for the frequency (applies only in the ground state). Default = ``10.0``"""
|
129
|
-
self.integral_error: float = 1.0e-5
|
130
|
-
"""Accuracy (relative error) in the computation of integrals. Default = ``1.0e-5``"""
|
131
|
-
self.integral_strategy: str = "full"
|
132
|
-
"""
|
133
|
-
Scheme used to solve two-dimensional integrals
|
134
|
-
allowed options include:
|
167
|
+
coupling: float
|
168
|
+
"""Coupling parameter."""
|
169
|
+
degeneracy: float
|
170
|
+
"""Degeneracy parameter."""
|
171
|
+
chemical_potential: list[float] = field(default_factory=lambda: [-10.0, 10.0])
|
172
|
+
"""Initial guess for the chemical potential. Default = ``[-10, 10]``"""
|
173
|
+
cutoff: float = 10.0
|
174
|
+
"""Cutoff for the wave-vector grid. Default = ``10.0``"""
|
175
|
+
frequency_cutoff: float = 10.0
|
176
|
+
"""Cutoff for the frequency (applies only in the ground state). Default = ``10.0``"""
|
177
|
+
integral_error: float = 1.0e-5
|
178
|
+
"""Accuracy (relative error) in the computation of integrals. Default = ``1.0e-5``"""
|
179
|
+
integral_strategy: str = "full"
|
180
|
+
"""
|
181
|
+
Scheme used to solve two-dimensional integrals
|
182
|
+
allowed options include:
|
135
183
|
|
136
|
-
|
184
|
+
- full: the inner integral is evaluated at arbitrary points selected automatically by the quadrature rule
|
137
185
|
|
138
|
-
|
186
|
+
- segregated: the inner integral is evaluated on a fixed grid that depends on the integrand that is being processed
|
139
187
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
188
|
+
Segregated is usually faster than full but it could become
|
189
|
+
less accurate if the fixed points are not chosen correctly. Default = ``'full'``
|
190
|
+
"""
|
191
|
+
matsubara: int = 128
|
192
|
+
"""Number of Matsubara frequencies. Default = ``128``"""
|
193
|
+
resolution: float = 0.1
|
194
|
+
"""Resolution of the wave-vector grid. Default = ``0.1``"""
|
195
|
+
threads: int = 1
|
196
|
+
"""Number of OMP threads for parallel calculations. Default = ``1``"""
|
197
|
+
processes: int = 1
|
198
|
+
"""Number of MPI processes for parallel calculations. Default = ``1``"""
|
199
|
+
theory: str = "HF"
|
200
|
+
database_info: DatabaseInfo = field(default_factory=lambda: DatabaseInfo())
|
152
201
|
|
153
202
|
def to_native(self, native_input: any):
|
154
203
|
"""
|
@@ -176,28 +225,28 @@ class Input:
|
|
176
225
|
setattr(native_input, attr, value_to_set)
|
177
226
|
|
178
227
|
|
228
|
+
@serialize.serializable_dataclass
|
179
229
|
class Result:
|
180
230
|
"""
|
181
231
|
Class used to store the results for the :obj:`qupled.hf.HF` class.
|
182
232
|
"""
|
183
233
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
"""Wave-vector grid"""
|
234
|
+
idr: np.ndarray = None
|
235
|
+
"""Ideal density response"""
|
236
|
+
lfc: np.ndarray = None
|
237
|
+
"""Local field correction"""
|
238
|
+
rdf: np.ndarray = None
|
239
|
+
"""Radial distribution function"""
|
240
|
+
rdf_grid: np.ndarray = None
|
241
|
+
"""Radial distribution function grid"""
|
242
|
+
sdr: np.ndarray = None
|
243
|
+
"""Static density response"""
|
244
|
+
ssf: np.ndarray = None
|
245
|
+
"""Static structure factor"""
|
246
|
+
uint: float = None
|
247
|
+
"""Internal energy"""
|
248
|
+
wvg: np.ndarray = None
|
249
|
+
"""Wave-vector grid"""
|
201
250
|
|
202
251
|
def from_native(self, native_scheme: any):
|
203
252
|
"""
|
@@ -210,10 +259,11 @@ class Result:
|
|
210
259
|
- Only attributes that exist in both the current object and the native_scheme object will be updated.
|
211
260
|
- Attributes with a value of `None` in the native_scheme object will not overwrite the current object's attributes.
|
212
261
|
"""
|
213
|
-
for attr in self.
|
262
|
+
for attr in self.__dataclass_fields__:
|
214
263
|
if hasattr(native_scheme, attr):
|
215
264
|
value = getattr(native_scheme, attr)
|
216
|
-
|
265
|
+
valid_value = value is not None and not callable(value)
|
266
|
+
setattr(self, attr, value) if valid_value else None
|
217
267
|
|
218
268
|
def compute_rdf(self, rdf_grid: np.ndarray | None = None):
|
219
269
|
"""
|
@@ -234,18 +284,18 @@ class Result:
|
|
234
284
|
self.rdf = native.compute_rdf(self.rdf_grid, self.wvg, self.ssf)
|
235
285
|
|
236
286
|
|
287
|
+
@serialize.serializable_dataclass
|
237
288
|
class DatabaseInfo:
|
238
289
|
"""
|
239
290
|
Class used to store the database information passed to the native code.
|
240
291
|
"""
|
241
292
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
"""Name of the table used to store the runs in the database"""
|
293
|
+
name: str = database.DataBaseHandler.DEFAULT_DATABASE_NAME
|
294
|
+
"""Database name"""
|
295
|
+
run_id: int = None
|
296
|
+
"""ID of the run in the database"""
|
297
|
+
run_table_name: str = database.DataBaseHandler.RUN_TABLE_NAME
|
298
|
+
"""Name of the table used to store the runs in the database"""
|
249
299
|
|
250
300
|
def to_native(self) -> native.DatabaseInfo:
|
251
301
|
"""
|
@@ -261,3 +311,14 @@ class DatabaseInfo:
|
|
261
311
|
if value is not None:
|
262
312
|
setattr(native_database_info, attr, value)
|
263
313
|
return native_database_info
|
314
|
+
|
315
|
+
@classmethod
|
316
|
+
def from_dict(cls, d):
|
317
|
+
obj = cls.__new__(cls)
|
318
|
+
for key, value in d.items():
|
319
|
+
setattr(obj, key, value)
|
320
|
+
return obj
|
321
|
+
|
322
|
+
|
323
|
+
if __name__ == "__main__":
|
324
|
+
Solver.run_mpi_worker(Input, Result)
|