osiris-utils 1.1.10__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.10.dist-info → osiris_utils-1.2.0.dist-info}/METADATA +55 -7
- {osiris_utils-1.1.10.dist-info → osiris_utils-1.2.0.dist-info}/RECORD +51 -34
- {osiris_utils-1.1.10.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.10.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.10.dist-info → osiris_utils-1.2.0.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
```python
|
|
2
|
+
%load_ext autoreload
|
|
3
|
+
%autoreload 2
|
|
4
|
+
```
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
import matplotlib.pyplot as plt
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
import osiris_utils as ou
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
# Example notebook for the `Simulation` and `Diagnostic` classes
|
|
15
|
+
|
|
16
|
+
### `Simulation`
|
|
17
|
+
The `Simulation` class takes in:
|
|
18
|
+
- `simulation_folder`: the folder where the input deck is located
|
|
19
|
+
- `species`: the species in case we are interested in diagnostics that are species-specific (such as vfl1, T11, etc.)
|
|
20
|
+
|
|
21
|
+
Acts as a wrapper for the `Diagnostic` class, allowing for an easy access to diagnostics of the simulation using a **dictionary-like** syntax.
|
|
22
|
+
|
|
23
|
+
### `Diagnostic`
|
|
24
|
+
|
|
25
|
+
The `Diagnostic` class takes in:
|
|
26
|
+
- `simulation_folder`: the folder where the input deck is located
|
|
27
|
+
- `species`: the species in case we are interested in diagnostics that are species-specific (such as vfl1, T11, etc.)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
The `Diagnostic` class has the some relevant methods and properties that you should be aware of:
|
|
31
|
+
- `get_quantity`: "loads" the quantity. Accessing the diagnostic through the `Simulations` using the dictionary-like syntax this will be called automatically.
|
|
32
|
+
- once the quantity is loaded, you can access the data at a specific time through indexing (e.g. `diag['vfl1'][0]` for the first time step). This doesn't store the data in memory, only uses a data generator to access the data (lazy loading).
|
|
33
|
+
- `load_all`: loads all the time steps of the quantity, storing it in memory
|
|
34
|
+
- `unload`: unloads the data from memory
|
|
35
|
+
- `time`: the time steps of the quantity at a specific index
|
|
36
|
+
- Has operator overloading for the `+`, `-`, `*`, `/` operators, allowing for easy manipulation of the data, even when it is not loaded in memory and is accessed through indexing.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
# sim is a Simulation object
|
|
41
|
+
sim = ou.Simulation(input_deck_path="example_data/thermal.1d")
|
|
42
|
+
|
|
43
|
+
print("Simulation:")
|
|
44
|
+
print(sim)
|
|
45
|
+
print(sim.__dict__.keys())
|
|
46
|
+
print(f"\n")
|
|
47
|
+
|
|
48
|
+
# e3 is a Diagnostic object
|
|
49
|
+
e3 = ou.Diagnostic("example_data", "electrons")
|
|
50
|
+
# now we need to load the data
|
|
51
|
+
e3.get_quantity("e3") # it knows the path there since OSIRIS always saves the data in the same way
|
|
52
|
+
|
|
53
|
+
print("Diagnostic: (e3)")
|
|
54
|
+
print(e3)
|
|
55
|
+
print(e3.__dict__.keys())
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If the diagnostic that you want to access if related to a species, you need to access it by using the species name as the first key.
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
# An electric field if not relatec to a species, so you can access it by doing:
|
|
63
|
+
sim["e3"]
|
|
64
|
+
|
|
65
|
+
# To access a species-related diagnostic, you can do:
|
|
66
|
+
sim["electrons"]["vfl1"]
|
|
67
|
+
|
|
68
|
+
# To see the available species of a simulation, you can do:
|
|
69
|
+
sim.species
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Notice that the `Diagnostic` class does not have `data` as the data is not saved in memory if `load_all` is not called. The data is accessed through the `__getitem__` method using indexing.
|
|
73
|
+
|
|
74
|
+
To get a `Diagnostic` from a `Simulation`, you can access it through the dictionary-like syntax, where the key is the name of the diagnostic (e.g. `sim['vfl1']` is a `Diagnostic` with the `vfl1` quantity).
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
sim["e3"] # This is equivalent to e3
|
|
79
|
+
|
|
80
|
+
print(sim["e3"])
|
|
81
|
+
print(sim["e3"].__dict__.keys())
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If we want to access the data of the diagnostic at a specific time, we can use the indexing syntax (e.g. `sim['vfl1'][0]` for the first time step, using a `Simulation`, or `e3[0]`, using the `Diagnostic` directly).
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
print(sim["e3"][100].shape) # nx
|
|
89
|
+
print(e3[100].shape) # nx
|
|
90
|
+
|
|
91
|
+
print("Are they the same?", np.isclose(sim["e3"][100], e3[100]).all())
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
This is useful when we want to access a specific iteration of the diagnostic, without loading all the data in memory.
|
|
95
|
+
|
|
96
|
+
For a quick plot, we can even use the other attributes of the `Diagnostic` class, such as `time`, `x` for the axis, of `axis` for info about the axis.
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
plt.figure(figsize=(12, 4))
|
|
101
|
+
plt.subplot(121)
|
|
102
|
+
plt.plot(sim["e3"].x, sim["e3"][100], label="Simulation", c="tab:orange")
|
|
103
|
+
plt.title("Using Simulation")
|
|
104
|
+
plt.xlabel(sim["e3"].axis[0]["plot_label"])
|
|
105
|
+
plt.legend()
|
|
106
|
+
|
|
107
|
+
plt.subplot(122)
|
|
108
|
+
plt.plot(e3.x, e3[100], label="Diagnostic", c="tab:blue")
|
|
109
|
+
plt.title("Using Diagnostic")
|
|
110
|
+
plt.xlabel(e3.axis[0]["plot_label"])
|
|
111
|
+
plt.legend()
|
|
112
|
+
plt.show()
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If we want to load all the data in memory, we can use the `load_all` method, which will load all the data in memory. This is useful to study how diagnostics vary in time, for example.
|
|
116
|
+
|
|
117
|
+
The data is stored in the `data` attribute of the `Diagnostic` class.
|
|
118
|
+
|
|
119
|
+
If we want to unload the data from memory, we can use the `unload` method.
|
|
120
|
+
|
|
121
|
+
From now on, I'll only use `sim[diagnostic]` to show what can be done with `Diagnostic` objects, but remember that you can access the `Diagnostic` object directly if you want to use the `load_all`, `unload`, `time`, `x`, and `axis` attributes.
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
sim["e3"].load_all()
|
|
126
|
+
|
|
127
|
+
# now, the data is loaded in memory
|
|
128
|
+
print(sim["e3"].data.shape) # (n_steps, nx)
|
|
129
|
+
|
|
130
|
+
sim["e3"].unload()
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Since diagnostics have operator overloading, we can easily manipulate the data, even when it is not loaded in memory. For example, we can do `sim['vfl1'] + sim['e1']` to get the sum of the two diagnostics, or `sim['vfl1'] / sim['e1']` to get the division of the two diagnostics.
|
|
134
|
+
|
|
135
|
+
When operations are done, a new `Diagnostic` is created, with the new data. This new `Diagnostic` can be accessed through the indexing syntax, and the data can be loaded in memory using the `load_all` method.
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
sum_of_diag = sim["electrons"]["T11"] + sim["electrons"]["vfl1"]
|
|
140
|
+
|
|
141
|
+
print(sum_of_diag)
|
|
142
|
+
print(sum_of_diag.__dict__.keys())
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
We can use the method of the `Diagnostic` class as usual, for example, `load_all`, and `unload`:
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
# we can load all the data at once
|
|
150
|
+
sum_of_diag.load_all()
|
|
151
|
+
print(sum_of_diag.data.shape) # (n_steps, nx)
|
|
152
|
+
sum_of_diag.unload()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
And accessing a specific time step of the new `Diagnostic` is done through indexing, as usual.
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
plt.figure(figsize=(12, 4))
|
|
160
|
+
plt.subplot(121)
|
|
161
|
+
plt.plot(sum_of_diag.x, sum_of_diag[100], label="T11 + vfl1", c="tab:orange")
|
|
162
|
+
plt.title("Diagnostic from sum of two diagnostics")
|
|
163
|
+
plt.xlabel(sum_of_diag.axis[0]["plot_label"])
|
|
164
|
+
plt.legend()
|
|
165
|
+
plt.show()
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
This is really useful when we want a quantity that OSIRIS doesn't provide. For example, when the pressure is adiabatic, we can calculate the pressure using the formula `P = n * T`, where `P` is the pressure, `n` is the density, and `T` is the temperature. We can calculate the pressure using the formula `P = n * T` using the `Diagnostic` class, and then use the pressure to calculate the adiabatic index `gamma = 5/3` using the formula `gamma = P / (n * T)`.
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
nT = -1 * sim["electrons"]["T11"] * sim["electrons"]["charge"] # -1 because we are dealing with electrons
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
plt.figure(figsize=(6, 4))
|
|
178
|
+
plt.plot(nT.x, nT[100], label=r"$n_eT_{11}$", c="tab:green")
|
|
179
|
+
plt.title(r"$n_eT_{11}$")
|
|
180
|
+
plt.xlabel(nT.axis[0]["plot_label"])
|
|
181
|
+
plt.legend()
|
|
182
|
+
plt.show()
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
If the `load_all` method is called before the operations, the whole data will be stored in the new quantity.
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
sim["electrons"]["vfl1"].load_all()
|
|
190
|
+
sim["electrons"]["charge"].load_all()
|
|
191
|
+
|
|
192
|
+
v_times_charge = sim["electrons"]["vfl1"] * sim["electrons"]["charge"]
|
|
193
|
+
|
|
194
|
+
print(v_times_charge)
|
|
195
|
+
print(v_times_charge.__dict__.keys())
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The whole data is computed if stored in the diagnostics before the operations
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
print(v_times_charge.data.shape)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
And it can be unloaded from memory using the `unload` method.
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
v_times_charge.unload()
|
|
210
|
+
|
|
211
|
+
# print something that checks that data is none
|
|
212
|
+
print("Is `v_times_charge.data` None?", v_times_charge._data is None)
|
|
213
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Quick Start Guide
|
|
2
|
+
|
|
3
|
+
```python
|
|
4
|
+
%load_ext autoreload
|
|
5
|
+
%autoreload 2
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
"""
|
|
11
|
+
Quick demonstration of osiris_utils:
|
|
12
|
+
• opens an OSIRIS simulation directory
|
|
13
|
+
• plots Ez field at t = 2000
|
|
14
|
+
Run with: python examples/quick_start.py <PATH_TO_RUN>
|
|
15
|
+
"""
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
import matplotlib.pyplot as plt
|
|
24
|
+
|
|
25
|
+
import osiris_utils as ou
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
sim_path = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("example_data/thermal.1d")
|
|
32
|
+
sim = ou.Simulation(sim_path)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
# grab Ez diagnostic
|
|
38
|
+
ez = sim["e3"]
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
# plot Ez field at iteration 220
|
|
44
|
+
plt.plot(ez.x, ez[220], label=f"${ez.label}$")
|
|
45
|
+
plt.title(rf"${ez.label}$ at t = {ez.time(220)[0]} $[{ez.time(220)[1]}]$")
|
|
46
|
+
plt.xlabel(ez.axis[0]["plot_label"])
|
|
47
|
+
plt.ylabel(f"${ez.units}$")
|
|
48
|
+
plt.legend()
|
|
49
|
+
plt.tight_layout()
|
|
50
|
+
plt.show()
|
|
51
|
+
```
|
docs/source/examples.rst
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Examples
|
|
2
|
+
========
|
|
3
|
+
|
|
4
|
+
This section contains examples and tutorials on how to use ``osiris_utils``.
|
|
5
|
+
|
|
6
|
+
.. toctree::
|
|
7
|
+
:maxdepth: 1
|
|
8
|
+
:caption: Tutorials:
|
|
9
|
+
|
|
10
|
+
examples/quick_start
|
|
11
|
+
examples/example_Simulation_Diagnostic
|
|
12
|
+
examples/example_InputDeck
|
|
13
|
+
examples/example_Derivatives
|
|
14
|
+
examples/example_FFT
|
docs/source/index.rst
CHANGED
|
@@ -5,6 +5,13 @@ OSIRIS Utils Documentation
|
|
|
5
5
|
|
|
6
6
|
.. include:: ../../README.rst
|
|
7
7
|
|
|
8
|
+
.. toctree::
|
|
9
|
+
:maxdepth: 2
|
|
10
|
+
:caption: Examples:
|
|
11
|
+
:hidden:
|
|
12
|
+
|
|
13
|
+
examples
|
|
14
|
+
|
|
8
15
|
.. toctree::
|
|
9
16
|
:maxdepth: 2
|
|
10
17
|
:caption: Simulation and Diagnostic API:
|
|
@@ -24,6 +31,7 @@ OSIRIS Utils Documentation
|
|
|
24
31
|
:caption: Utilities API:
|
|
25
32
|
:hidden:
|
|
26
33
|
|
|
34
|
+
api/decks
|
|
27
35
|
api/utilities
|
|
28
36
|
|
|
29
37
|
.. toctree::
|