osiris-utils 1.1.10a0__py3-none-any.whl → 1.2.0__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.
- benchmarks/benchmark_hdf5_io.py +46 -0
- benchmarks/benchmark_load_all.py +54 -0
- docs/source/api/decks.rst +48 -0
- docs/source/api/postprocess.rst +66 -2
- docs/source/api/sim_diag.rst +1 -1
- docs/source/api/utilities.rst +1 -1
- docs/source/conf.py +2 -1
- docs/source/examples/example_Derivatives.md +78 -0
- docs/source/examples/example_FFT.md +152 -0
- docs/source/examples/example_InputDeck.md +148 -0
- docs/source/examples/example_Simulation_Diagnostic.md +213 -0
- docs/source/examples/quick_start.md +51 -0
- docs/source/examples.rst +14 -0
- docs/source/index.rst +8 -0
- examples/edited-deck.1d +1 -1
- examples/example_Derivatives.ipynb +24 -36
- examples/example_FFT.ipynb +44 -23
- examples/example_InputDeck.ipynb +24 -277
- examples/example_Simulation_Diagnostic.ipynb +27 -17
- examples/quick_start.ipynb +17 -1
- osiris_utils/__init__.py +10 -6
- osiris_utils/cli/__init__.py +6 -0
- osiris_utils/cli/__main__.py +85 -0
- osiris_utils/cli/export.py +199 -0
- osiris_utils/cli/info.py +156 -0
- osiris_utils/cli/plot.py +189 -0
- osiris_utils/cli/validate.py +247 -0
- osiris_utils/data/__init__.py +15 -0
- osiris_utils/data/data.py +41 -171
- osiris_utils/data/diagnostic.py +285 -274
- osiris_utils/data/simulation.py +20 -13
- osiris_utils/decks/__init__.py +4 -0
- osiris_utils/decks/decks.py +83 -8
- osiris_utils/decks/species.py +12 -9
- osiris_utils/postprocessing/__init__.py +28 -0
- osiris_utils/postprocessing/derivative.py +317 -106
- osiris_utils/postprocessing/fft.py +135 -24
- osiris_utils/postprocessing/field_centering.py +28 -14
- osiris_utils/postprocessing/heatflux_correction.py +39 -18
- osiris_utils/postprocessing/mft.py +10 -2
- osiris_utils/postprocessing/postprocess.py +8 -5
- osiris_utils/postprocessing/pressure_correction.py +29 -17
- osiris_utils/utils.py +26 -17
- osiris_utils/vis/__init__.py +3 -0
- osiris_utils/vis/plot3d.py +148 -0
- {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.0.dist-info}/METADATA +55 -7
- {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.0.dist-info}/RECORD +51 -34
- {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.0.dist-info}/WHEEL +1 -1
- osiris_utils-1.2.0.dist-info/entry_points.txt +2 -0
- {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.0.dist-info}/top_level.txt +1 -0
- osiris_utils/postprocessing/mft_for_gridfile.py +0 -55
- {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.0.dist-info}/licenses/LICENSE.txt +0 -0
osiris_utils/data/simulation.py
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import os
|
|
4
|
+
from typing import Any
|
|
2
5
|
|
|
3
6
|
from ..data.diagnostic import Diagnostic
|
|
4
7
|
from ..decks.decks import InputDeckIO
|
|
5
8
|
|
|
9
|
+
__all__ = ["Simulation", "Species_Handler"]
|
|
10
|
+
|
|
6
11
|
|
|
7
12
|
class Simulation:
|
|
8
13
|
"""
|
|
@@ -17,7 +22,7 @@ class Simulation:
|
|
|
17
22
|
----------
|
|
18
23
|
simulation_folder : str
|
|
19
24
|
The simulation folder.
|
|
20
|
-
species :
|
|
25
|
+
species : Species object
|
|
21
26
|
The species to analyze.
|
|
22
27
|
diagnostics : dict
|
|
23
28
|
Dictionary to store diagnostics for each quantity when `load_all` method is used.
|
|
@@ -34,7 +39,7 @@ class Simulation:
|
|
|
34
39
|
|
|
35
40
|
"""
|
|
36
41
|
|
|
37
|
-
def __init__(self, input_deck_path):
|
|
42
|
+
def __init__(self, input_deck_path: str) -> None:
|
|
38
43
|
folder_path = os.path.dirname(input_deck_path)
|
|
39
44
|
self._input_deck_path = input_deck_path
|
|
40
45
|
self._input_deck = InputDeckIO(self._input_deck_path, verbose=False)
|
|
@@ -60,7 +65,7 @@ class Simulation:
|
|
|
60
65
|
else:
|
|
61
66
|
print(f"Diagnostic {key} not found in simulation")
|
|
62
67
|
|
|
63
|
-
def __getitem__(self, key):
|
|
68
|
+
def __getitem__(self, key: str) -> Diagnostic | Species_Handler:
|
|
64
69
|
# check if key is a species
|
|
65
70
|
if key in self._species:
|
|
66
71
|
# check if species handler already exists
|
|
@@ -94,7 +99,7 @@ class Simulation:
|
|
|
94
99
|
|
|
95
100
|
return diag
|
|
96
101
|
|
|
97
|
-
def add_diagnostic(self, diagnostic, name=None):
|
|
102
|
+
def add_diagnostic(self, diagnostic: Diagnostic, name: str | None = None) -> str:
|
|
98
103
|
"""
|
|
99
104
|
Add a custom diagnostic to the simulation.
|
|
100
105
|
|
|
@@ -130,27 +135,28 @@ class Simulation:
|
|
|
130
135
|
# If already a Diagnostic, store directly
|
|
131
136
|
if isinstance(diagnostic, Diagnostic):
|
|
132
137
|
self._diagnostics[name] = diagnostic
|
|
138
|
+
return name
|
|
133
139
|
else:
|
|
134
140
|
raise ValueError("Only Diagnostic objects are supported for now")
|
|
135
141
|
|
|
136
142
|
@property
|
|
137
|
-
def species(self):
|
|
143
|
+
def species(self) -> list[str]:
|
|
138
144
|
return self._species
|
|
139
145
|
|
|
140
146
|
@property
|
|
141
|
-
def loaded_diagnostics(self):
|
|
147
|
+
def loaded_diagnostics(self) -> dict[str, Diagnostic]:
|
|
142
148
|
return self._diagnostics
|
|
143
149
|
|
|
144
150
|
|
|
145
151
|
# This is to handle species related diagnostics
|
|
146
152
|
class Species_Handler:
|
|
147
|
-
def __init__(self, simulation_folder, species_name, input_deck):
|
|
153
|
+
def __init__(self, simulation_folder: str, species_name: Any, input_deck: Any) -> None:
|
|
148
154
|
self._simulation_folder = simulation_folder
|
|
149
155
|
self._species_name = species_name
|
|
150
156
|
self._input_deck = input_deck
|
|
151
157
|
self._diagnostics = {}
|
|
152
158
|
|
|
153
|
-
def __getitem__(self, key):
|
|
159
|
+
def __getitem__(self, key: str) -> Diagnostic:
|
|
154
160
|
if key in self._diagnostics:
|
|
155
161
|
return self._diagnostics[key]
|
|
156
162
|
|
|
@@ -173,7 +179,7 @@ class Species_Handler:
|
|
|
173
179
|
|
|
174
180
|
return diag
|
|
175
181
|
|
|
176
|
-
def add_diagnostic(self, diagnostic, name=None):
|
|
182
|
+
def add_diagnostic(self, diagnostic: Diagnostic, name: str | None = None) -> str:
|
|
177
183
|
"""
|
|
178
184
|
Add a custom diagnostic to the simulation.
|
|
179
185
|
|
|
@@ -203,10 +209,11 @@ class Species_Handler:
|
|
|
203
209
|
# If already a Diagnostic, store directly
|
|
204
210
|
if isinstance(diagnostic, Diagnostic):
|
|
205
211
|
self._diagnostics[name] = diagnostic
|
|
212
|
+
return name
|
|
206
213
|
else:
|
|
207
214
|
raise ValueError("Only Diagnostic objects are supported for now")
|
|
208
215
|
|
|
209
|
-
def delete_diagnostic(self, key):
|
|
216
|
+
def delete_diagnostic(self, key: str) -> None:
|
|
210
217
|
"""
|
|
211
218
|
Delete a diagnostic.
|
|
212
219
|
"""
|
|
@@ -216,16 +223,16 @@ class Species_Handler:
|
|
|
216
223
|
print(f"Diagnostic {key} not found in species {self._species_name}")
|
|
217
224
|
return None
|
|
218
225
|
|
|
219
|
-
def delete_all_diagnostics(self):
|
|
226
|
+
def delete_all_diagnostics(self) -> None:
|
|
220
227
|
"""
|
|
221
228
|
Delete all diagnostics.
|
|
222
229
|
"""
|
|
223
230
|
self._diagnostics = {}
|
|
224
231
|
|
|
225
232
|
@property
|
|
226
|
-
def species(self):
|
|
233
|
+
def species(self) -> Any:
|
|
227
234
|
return self._species_name
|
|
228
235
|
|
|
229
236
|
@property
|
|
230
|
-
def loaded_diagnostics(self):
|
|
237
|
+
def loaded_diagnostics(self) -> dict[str, Diagnostic]:
|
|
231
238
|
return self._diagnostics
|
osiris_utils/decks/__init__.py
CHANGED
osiris_utils/decks/decks.py
CHANGED
|
@@ -4,7 +4,9 @@ import re
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
|
|
7
|
-
from .species import
|
|
7
|
+
from .species import Species
|
|
8
|
+
|
|
9
|
+
__all__ = ["InputDeckIO", "deval"]
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
def deval(x):
|
|
@@ -42,7 +44,7 @@ class InputDeckIO:
|
|
|
42
44
|
Number of dimensions in the simulation (1, 2, or 3).
|
|
43
45
|
"""
|
|
44
46
|
|
|
45
|
-
def __init__(self, filename: str, verbose: bool =
|
|
47
|
+
def __init__(self, filename: str, verbose: bool = False):
|
|
46
48
|
self._filename = str(filename)
|
|
47
49
|
self._sections = self._parse_input_deck(verbose)
|
|
48
50
|
self._dim = self._get_dim()
|
|
@@ -54,7 +56,7 @@ class InputDeckIO:
|
|
|
54
56
|
if verbose:
|
|
55
57
|
print(f"\nParsing input deck : {self._filename}")
|
|
56
58
|
|
|
57
|
-
with open(self._filename,
|
|
59
|
+
with open(self._filename, encoding="utf-8") as f:
|
|
58
60
|
lines = f.readlines()
|
|
59
61
|
|
|
60
62
|
# remove comments
|
|
@@ -162,14 +164,14 @@ class InputDeckIO:
|
|
|
162
164
|
s_qreal = np.ones(len(s_names))
|
|
163
165
|
# check if we have information for all species
|
|
164
166
|
if len(s_names) != self.n_species:
|
|
165
|
-
raise RuntimeError("Number of specie names does not match number of species:
|
|
167
|
+
raise RuntimeError(f"Number of specie names does not match number of species: {len(s_names)} != {len(self.n_species)}.")
|
|
166
168
|
if len(s_rqm) != self.n_species:
|
|
167
|
-
raise RuntimeError("Number of specie rqm does not match number of species:
|
|
169
|
+
raise RuntimeError(f"Number of specie rqm does not match number of species: {len(s_rqm)} != {len(self.n_species)}.")
|
|
168
170
|
if len(s_qreal) != self.n_species:
|
|
169
|
-
raise RuntimeError("Number of specie rqm does not match number of species:
|
|
171
|
+
raise RuntimeError(f"Number of specie rqm does not match number of species: {len(s_qreal)} != {len(self.n_species)}.")
|
|
170
172
|
|
|
171
173
|
return {
|
|
172
|
-
ast.literal_eval(s_names[i]):
|
|
174
|
+
ast.literal_eval(s_names[i]): Species(
|
|
173
175
|
name=ast.literal_eval(s_names[i]),
|
|
174
176
|
rqm=float(s_rqm[i]),
|
|
175
177
|
q=int(s_qreal[0]) * np.sign(float(s_rqm[i])),
|
|
@@ -178,6 +180,29 @@ class InputDeckIO:
|
|
|
178
180
|
}
|
|
179
181
|
|
|
180
182
|
def set_param(self, section, param, value, i_use=None, unexistent_ok=False):
|
|
183
|
+
"""
|
|
184
|
+
Set a parameter value in the input deck.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
section : str
|
|
189
|
+
The name of the section where the parameter is located.
|
|
190
|
+
param : str
|
|
191
|
+
The name of the parameter to set.
|
|
192
|
+
value : str or list or int or float
|
|
193
|
+
The value to set. If a list, it is converted to a comma-separated string.
|
|
194
|
+
i_use : int or list of int, optional
|
|
195
|
+
The index(es) of the section(s) to modify if multiple sections with the same name exist.
|
|
196
|
+
If None, all sections with the matching name are modified.
|
|
197
|
+
unexistent_ok : bool, optional
|
|
198
|
+
If True, allows setting a parameter that does not currently exist in the section.
|
|
199
|
+
Default is False.
|
|
200
|
+
|
|
201
|
+
Raises
|
|
202
|
+
------
|
|
203
|
+
KeyError
|
|
204
|
+
If the section is not found, or if the parameter is not found (and unexistent_ok is False).
|
|
205
|
+
"""
|
|
181
206
|
# get all sections with the same name
|
|
182
207
|
# (e.g. there might be multiple 'species')
|
|
183
208
|
i_sections = [i for i, m in enumerate(self._sections) if m[0] == section]
|
|
@@ -193,7 +218,7 @@ class InputDeckIO:
|
|
|
193
218
|
|
|
194
219
|
for i in i_sections:
|
|
195
220
|
if not unexistent_ok and param not in self._sections[i][1]:
|
|
196
|
-
raise KeyError(f'"{param}" not yet inside section "{section}"
|
|
221
|
+
raise KeyError(f'"{param}" not yet inside section "{section}" (set unexistent_ok=True to ignore).')
|
|
197
222
|
if isinstance(value, str):
|
|
198
223
|
self._sections[i][1][param] = str(f'"{value}"')
|
|
199
224
|
elif isinstance(value, list):
|
|
@@ -202,11 +227,43 @@ class InputDeckIO:
|
|
|
202
227
|
self._sections[i][1][param] = str(value)
|
|
203
228
|
|
|
204
229
|
def set_tag(self, tag, value):
|
|
230
|
+
"""
|
|
231
|
+
Replace a tag in all parameters within the input deck.
|
|
232
|
+
This is useful for template replacement.
|
|
233
|
+
|
|
234
|
+
Parameters
|
|
235
|
+
----------
|
|
236
|
+
tag : str
|
|
237
|
+
The tag substring to search for (e.g., "<TAG>").
|
|
238
|
+
value : str or int or float
|
|
239
|
+
The value to replace the tag with.
|
|
240
|
+
"""
|
|
205
241
|
for im, (_, params) in enumerate(self._sections):
|
|
206
242
|
for p, v in params.items():
|
|
207
243
|
self._sections[im][1][p] = v.replace(tag, str(value))
|
|
208
244
|
|
|
209
245
|
def get_param(self, section, param):
|
|
246
|
+
"""
|
|
247
|
+
Get the value(s) of a parameter from a specific section.
|
|
248
|
+
|
|
249
|
+
Parameters
|
|
250
|
+
----------
|
|
251
|
+
section : str
|
|
252
|
+
The name of the section.
|
|
253
|
+
param : str
|
|
254
|
+
The name of the parameter.
|
|
255
|
+
|
|
256
|
+
Returns
|
|
257
|
+
-------
|
|
258
|
+
values : list
|
|
259
|
+
A list of values for the parameter. Returns a list because there can be multiple
|
|
260
|
+
sections with the same name.
|
|
261
|
+
|
|
262
|
+
Raises
|
|
263
|
+
------
|
|
264
|
+
KeyError
|
|
265
|
+
If the parameter is not found in one of the sections.
|
|
266
|
+
"""
|
|
210
267
|
i_sections = [i for i, m in enumerate(self._sections) if m[0] == section]
|
|
211
268
|
|
|
212
269
|
if len(i_sections) == 0:
|
|
@@ -222,6 +279,16 @@ class InputDeckIO:
|
|
|
222
279
|
return values
|
|
223
280
|
|
|
224
281
|
def delete_param(self, section, param):
|
|
282
|
+
"""
|
|
283
|
+
Delete a parameter from a specific section.
|
|
284
|
+
|
|
285
|
+
Parameters
|
|
286
|
+
----------
|
|
287
|
+
section : str
|
|
288
|
+
The name of the section.
|
|
289
|
+
param : str
|
|
290
|
+
The name of the parameter to delete.
|
|
291
|
+
"""
|
|
225
292
|
sections_new = []
|
|
226
293
|
for m_name, m_dict in self._sections:
|
|
227
294
|
if m_name == section and param in m_dict:
|
|
@@ -230,6 +297,14 @@ class InputDeckIO:
|
|
|
230
297
|
self._sections = sections_new
|
|
231
298
|
|
|
232
299
|
def print_to_file(self, filename):
|
|
300
|
+
"""
|
|
301
|
+
Write the current state of the input deck to a file.
|
|
302
|
+
|
|
303
|
+
Parameters
|
|
304
|
+
----------
|
|
305
|
+
filename : str
|
|
306
|
+
The path to the output file.
|
|
307
|
+
"""
|
|
233
308
|
with open(filename, "w", encoding="utf-8") as f:
|
|
234
309
|
for section, section_dict in self._sections:
|
|
235
310
|
f.write(f"{section}\n{{\n")
|
osiris_utils/decks/species.py
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
__all__ = ["Species"]
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Species:
|
|
2
5
|
"""
|
|
3
6
|
Class to store OSIRIS species object.
|
|
4
7
|
|
|
5
8
|
Parameters
|
|
6
9
|
----------
|
|
7
10
|
name : str
|
|
8
|
-
|
|
11
|
+
Species name.
|
|
9
12
|
|
|
10
13
|
rqm : float
|
|
11
|
-
|
|
14
|
+
Species charge to mass ratio.
|
|
12
15
|
|
|
13
16
|
q : int
|
|
14
|
-
|
|
17
|
+
Species charge in units of the electron charge.
|
|
15
18
|
Electrons would be represented by q=-1 and protons q=1.
|
|
16
19
|
|
|
17
20
|
Attributes
|
|
18
21
|
----------
|
|
19
22
|
name : str
|
|
20
|
-
|
|
23
|
+
Species name.
|
|
21
24
|
|
|
22
25
|
rqm : float
|
|
23
|
-
|
|
26
|
+
Species charge to mass ratio.
|
|
24
27
|
|
|
25
28
|
q : int
|
|
26
|
-
|
|
29
|
+
Species charge in units of the electron charge.
|
|
27
30
|
|
|
28
31
|
m : float
|
|
29
|
-
|
|
32
|
+
Species mass in units of the electron mass.
|
|
30
33
|
"""
|
|
31
34
|
|
|
32
35
|
def __init__(self, name, rqm, q: int = 1):
|
|
@@ -36,7 +39,7 @@ class Specie:
|
|
|
36
39
|
self._m = rqm * q
|
|
37
40
|
|
|
38
41
|
def __repr__(self) -> str:
|
|
39
|
-
return f"
|
|
42
|
+
return f"Species(name={self._name}, rqm={self._rqm}, q={self._q}, m={self._m})"
|
|
40
43
|
|
|
41
44
|
@property
|
|
42
45
|
def name(self):
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from .derivative import Derivative_Diagnostic, Derivative_Simulation, Derivative_Species_Handler
|
|
2
|
+
from .fft import FFT_Diagnostic, FFT_Simulation, FFT_Species_Handler
|
|
3
|
+
from .field_centering import FieldCentering_Diagnostic, FieldCentering_Simulation
|
|
4
|
+
from .heatflux_correction import HeatfluxCorrection_Diagnostic, HeatfluxCorrection_Simulation, HeatfluxCorrection_Species_Handler
|
|
5
|
+
from .mft import MFT_Diagnostic, MFT_Simulation, MFT_Species_Handler
|
|
6
|
+
from .postprocess import PostProcess
|
|
7
|
+
from .pressure_correction import PressureCorrection_Diagnostic, PressureCorrection_Simulation, PressureCorrection_Species_Handler
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"Derivative_Simulation",
|
|
11
|
+
"Derivative_Diagnostic",
|
|
12
|
+
"Derivative_Species_Handler",
|
|
13
|
+
"FFT_Simulation",
|
|
14
|
+
"FFT_Diagnostic",
|
|
15
|
+
"FFT_Species_Handler",
|
|
16
|
+
"FieldCentering_Simulation",
|
|
17
|
+
"FieldCentering_Diagnostic",
|
|
18
|
+
"HeatfluxCorrection_Simulation",
|
|
19
|
+
"HeatfluxCorrection_Diagnostic",
|
|
20
|
+
"HeatfluxCorrection_Species_Handler",
|
|
21
|
+
"MFT_Simulation",
|
|
22
|
+
"MFT_Diagnostic",
|
|
23
|
+
"MFT_Species_Handler",
|
|
24
|
+
"PostProcess",
|
|
25
|
+
"PressureCorrection_Simulation",
|
|
26
|
+
"PressureCorrection_Diagnostic",
|
|
27
|
+
"PressureCorrection_Species_Handler",
|
|
28
|
+
]
|