osiris-utils 1.1.10a0__py3-none-any.whl → 1.2.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.
- benchmarks/benchmark_hdf5_io.py +46 -0
- benchmarks/benchmark_load_all.py +54 -0
- docs/source/_static/Imagem1.png +0 -0
- docs/source/_static/custom.css +24 -8
- docs/source/api/decks.rst +48 -0
- docs/source/api/postprocess.rst +72 -8
- docs/source/api/sim_diag.rst +9 -7
- docs/source/api/utilities.rst +6 -6
- docs/source/conf.py +28 -8
- docs/source/examples/example_Derivatives.md +78 -0
- docs/source/examples/example_FFT.md +152 -0
- docs/source/examples/example_InputDeck.md +149 -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.1.dist-info}/METADATA +61 -7
- {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.1.dist-info}/RECORD +53 -35
- {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.1.dist-info}/WHEEL +1 -1
- osiris_utils-1.2.1.dist-info/entry_points.txt +2 -0
- {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.1.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.1.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
import osiris_utils as ou
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def benchmark_hdf5_io():
|
|
7
|
+
"""Benchmark HDF5 file opening and reading."""
|
|
8
|
+
print("=" * 60)
|
|
9
|
+
print("Benchmarking HDF5 I/O Performance")
|
|
10
|
+
print("=" * 60)
|
|
11
|
+
|
|
12
|
+
filepath = "examples/example_data/MS/FLD/e3/e3-000100.h5"
|
|
13
|
+
|
|
14
|
+
# Warm-up (file may be cached by OS)
|
|
15
|
+
_ = ou.OsirisGridFile(filepath)
|
|
16
|
+
|
|
17
|
+
# Benchmark multiple loads
|
|
18
|
+
n_iterations = 100
|
|
19
|
+
times = []
|
|
20
|
+
|
|
21
|
+
print(f"\nLoading file {n_iterations} times...")
|
|
22
|
+
for _ in range(n_iterations):
|
|
23
|
+
start = time.time()
|
|
24
|
+
data = ou.OsirisGridFile(filepath)
|
|
25
|
+
times.append(time.time() - start)
|
|
26
|
+
|
|
27
|
+
avg_time = sum(times) / len(times)
|
|
28
|
+
min_time = min(times)
|
|
29
|
+
max_time = max(times)
|
|
30
|
+
|
|
31
|
+
print("\nResults:")
|
|
32
|
+
print(f" Average load time: {avg_time * 1000:.2f}ms")
|
|
33
|
+
print(f" Min load time: {min_time * 1000:.2f}ms")
|
|
34
|
+
print(f" Max load time: {max_time * 1000:.2f}ms")
|
|
35
|
+
print(f" Data shape: {data.data.shape}")
|
|
36
|
+
print(f" Data size: {data.data.nbytes / 1024:.1f} KB")
|
|
37
|
+
|
|
38
|
+
# Calculate throughput
|
|
39
|
+
throughput = (data.data.nbytes / 1024 / 1024) / avg_time
|
|
40
|
+
print(f" Throughput: {throughput:.1f} MB/s")
|
|
41
|
+
|
|
42
|
+
print("\n" + "=" * 60)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
benchmark_hdf5_io()
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
import osiris_utils as ou
|
|
5
|
+
|
|
6
|
+
# Use example data if available
|
|
7
|
+
data_path = "examples/example_data"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def benchmark_loading():
|
|
11
|
+
"""Benchmark parallel vs sequential loading."""
|
|
12
|
+
_ = f"{data_path}/MS/FLD/e3"
|
|
13
|
+
|
|
14
|
+
print("=" * 60)
|
|
15
|
+
print("Benchmarking Diagnostic.load_all() performance")
|
|
16
|
+
print("=" * 60)
|
|
17
|
+
|
|
18
|
+
# Test with sequential loading
|
|
19
|
+
print("\n1. Testing SEQUENTIAL loading...")
|
|
20
|
+
d = ou.Diagnostic(simulation_folder=data_path)
|
|
21
|
+
d.get_quantity("e3")
|
|
22
|
+
|
|
23
|
+
start = time.time()
|
|
24
|
+
data_seq = d.load_all(use_parallel=False)
|
|
25
|
+
seq_time = time.time() - start
|
|
26
|
+
print(f" Sequential time: {seq_time:.3f}s for {len(d)} timesteps")
|
|
27
|
+
print(f" Data shape: {data_seq.shape}")
|
|
28
|
+
|
|
29
|
+
# Unload to test parallel
|
|
30
|
+
d.unload()
|
|
31
|
+
|
|
32
|
+
# Test with parallel loading
|
|
33
|
+
print("\n2. Testing PARALLEL loading...")
|
|
34
|
+
start = time.time()
|
|
35
|
+
data_par = d.load_all(use_parallel=True)
|
|
36
|
+
par_time = time.time() - start
|
|
37
|
+
print(f" Parallel time: {par_time:.3f}s for {len(d)} timesteps")
|
|
38
|
+
print(f" Data shape: {data_par.shape}")
|
|
39
|
+
|
|
40
|
+
# Calculate speedup
|
|
41
|
+
speedup = seq_time / par_time if par_time > 0 else 0
|
|
42
|
+
print(f"\n✓ Speedup: {speedup:.2f}x faster with parallel loading")
|
|
43
|
+
print(f" Time saved: {seq_time - par_time:.3f}s ({100 * (seq_time - par_time) / seq_time:.1f}%)")
|
|
44
|
+
|
|
45
|
+
print("\n" + "=" * 60)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
try:
|
|
50
|
+
benchmark_loading()
|
|
51
|
+
except Exception as e:
|
|
52
|
+
print(f"Error running benchmark: {e}")
|
|
53
|
+
print("Make sure example_data is available in the examples directory")
|
|
54
|
+
sys.exit(1)
|
|
Binary file
|
docs/source/_static/custom.css
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Sidebar background */
|
|
2
2
|
.wy-nav-side {
|
|
3
|
-
background: #88cbf8;
|
|
3
|
+
background: #88cbf8;
|
|
4
|
+
/* Change to your preferred color */
|
|
4
5
|
}
|
|
5
6
|
|
|
6
7
|
/* Sidebar link color */
|
|
@@ -18,12 +19,17 @@
|
|
|
18
19
|
background: #2f93f0;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
.wy-menu-vertical li.current
|
|
22
|
+
.wy-menu-vertical li.current>a {
|
|
22
23
|
background: #aeecff;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/* Header (H1, H2, etc.) colors */
|
|
26
|
-
h1,
|
|
27
|
+
h1,
|
|
28
|
+
h2,
|
|
29
|
+
h3,
|
|
30
|
+
h4,
|
|
31
|
+
h5,
|
|
32
|
+
h6 {
|
|
27
33
|
color: #57bafb;
|
|
28
34
|
}
|
|
29
35
|
|
|
@@ -43,11 +49,21 @@ a:hover {
|
|
|
43
49
|
|
|
44
50
|
/* Keep your existing table width overrides */
|
|
45
51
|
@media screen and (min-width: 767px) {
|
|
46
|
-
.wy-table-responsive table td {
|
|
47
|
-
|
|
48
|
-
}
|
|
52
|
+
.wy-table-responsive table td {
|
|
53
|
+
white-space: normal !important;
|
|
54
|
+
}
|
|
49
55
|
|
|
50
|
-
.wy-table-responsive {
|
|
51
|
-
|
|
56
|
+
.wy-table-responsive {
|
|
57
|
+
overflow: visible !important;
|
|
58
|
+
}
|
|
52
59
|
}
|
|
60
|
+
|
|
61
|
+
/* Small easter-egg logo sizing */
|
|
62
|
+
.wy-side-nav-search .logo img,
|
|
63
|
+
.wy-side-nav .logo img,
|
|
64
|
+
.rst-sidebar .logo img,
|
|
65
|
+
.logo img {
|
|
66
|
+
max-width: 80px;
|
|
67
|
+
margin: 6px 8px;
|
|
68
|
+
height: auto;
|
|
53
69
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Deck Handling
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
This section documents the utilities for handling OSIRIS input decks.
|
|
5
|
+
|
|
6
|
+
InputDeckIO
|
|
7
|
+
-----------
|
|
8
|
+
|
|
9
|
+
.. autoclass:: osiris_utils.decks.decks.InputDeckIO
|
|
10
|
+
:members:
|
|
11
|
+
:special-members: __init__, __getitem__
|
|
12
|
+
:undoc-members:
|
|
13
|
+
:noindex:
|
|
14
|
+
|
|
15
|
+
Class to handle parsing and modifying OSIRIS input decks.
|
|
16
|
+
|
|
17
|
+
**Key Features:**
|
|
18
|
+
|
|
19
|
+
* Parse input decks into python objects
|
|
20
|
+
* Modify parameters programmatically
|
|
21
|
+
* Save modified decks to new files
|
|
22
|
+
* Automatic handling of OSIRIS syntax idiosyncrasies
|
|
23
|
+
|
|
24
|
+
**Usage Example:**
|
|
25
|
+
|
|
26
|
+
.. code-block:: python
|
|
27
|
+
|
|
28
|
+
from osiris_utils import InputDeckIO
|
|
29
|
+
|
|
30
|
+
# Load an input deck
|
|
31
|
+
deck = InputDeckIO("osiris.inp")
|
|
32
|
+
|
|
33
|
+
# Get simulation dimension
|
|
34
|
+
print(f"Simulation dimension: {deck.dim}")
|
|
35
|
+
|
|
36
|
+
# Modify a parameter
|
|
37
|
+
# (Assuming there is a 'time_step' section with 'dt' parameter)
|
|
38
|
+
deck.set_param("time_step", "dt", "0.05")
|
|
39
|
+
|
|
40
|
+
# Save to a new file
|
|
41
|
+
deck.print_to_file("osiris_modified.inp")
|
|
42
|
+
|
|
43
|
+
Coordinate Conversion
|
|
44
|
+
---------------------
|
|
45
|
+
|
|
46
|
+
.. function:: osiris_utils.decks.decks.deval
|
|
47
|
+
|
|
48
|
+
.. autofunction:: osiris_utils.decks.decks.deval
|
docs/source/api/postprocess.rst
CHANGED
|
@@ -86,7 +86,7 @@ Derivative_Simulation Class
|
|
|
86
86
|
from osiris_utils.postprocessing import Derivative_Simulation
|
|
87
87
|
|
|
88
88
|
# Create a simulation interface
|
|
89
|
-
sim = Simulation('/path/to/input/deck')
|
|
89
|
+
sim = Simulation('/path/to/input/deck.inp')
|
|
90
90
|
|
|
91
91
|
# Create a derivative processor for x₁ derivatives
|
|
92
92
|
dx1 = Derivative_Simulation(sim, 'x1')
|
|
@@ -206,7 +206,7 @@ This example shows how to compute the z-component of curl(B):
|
|
|
206
206
|
from osiris_utils.postprocessing import Derivative
|
|
207
207
|
|
|
208
208
|
# Setup
|
|
209
|
-
sim = Simulation('/path/to/input/deck')
|
|
209
|
+
sim = Simulation('/path/to/input/deck.inp')
|
|
210
210
|
dx1 = Derivative_Simulation(sim, 'x1')
|
|
211
211
|
dx2 = Derivative_Simulation(sim, 'x2')
|
|
212
212
|
|
|
@@ -227,7 +227,7 @@ This example shows how to compute the divergence of E:
|
|
|
227
227
|
from osiris_utils.postprocessing import Derivative_Diagnostic
|
|
228
228
|
|
|
229
229
|
# Setup
|
|
230
|
-
e1 = Diagnostic('/path/to/folder',
|
|
230
|
+
e1 = Diagnostic('/path/to/folder', species=None, input_deck="/path/to/input/deck.inp")
|
|
231
231
|
|
|
232
232
|
# Create derivative processor for x₁ and x₂ derivatives
|
|
233
233
|
de1_dx1 = Derivative_Diagnostic(e1, 'x1')
|
|
@@ -281,7 +281,7 @@ FFT_Simulation Class
|
|
|
281
281
|
from osiris_utils.postprocessing import FFT_Simulation
|
|
282
282
|
|
|
283
283
|
# Create a simulation interface
|
|
284
|
-
sim = Simulation('/path/to/input/deck')
|
|
284
|
+
sim = Simulation('/path/to/input/deck.inp')
|
|
285
285
|
|
|
286
286
|
# Create an FFT processor for the first spatial dimension
|
|
287
287
|
fft = FFT_Simulation(sim, 1)
|
|
@@ -379,7 +379,7 @@ This example shows how to compute and visualize a dispersion relation:
|
|
|
379
379
|
import matplotlib.pyplot as plt
|
|
380
380
|
|
|
381
381
|
# Setup
|
|
382
|
-
sim = Simulation('/path/to/input/deck')
|
|
382
|
+
sim = Simulation('/path/to/input/deck.inp')
|
|
383
383
|
|
|
384
384
|
# Create FFT processor for both time and space
|
|
385
385
|
# We'll do a 2D FFT - time (axis 0) and x1 (axis 1)
|
|
@@ -467,7 +467,7 @@ MFT_Simulation Class
|
|
|
467
467
|
from osiris_utils.postprocessing import MFT_Simulation
|
|
468
468
|
|
|
469
469
|
# Create a simulation interface
|
|
470
|
-
sim = Simulation('/path/to/input/deck')
|
|
470
|
+
sim = Simulation('/path/to/input/deck.inp')
|
|
471
471
|
|
|
472
472
|
# Create MFT analyzer for x₁ direction (axis=1)
|
|
473
473
|
mft = MFT_Simulation(sim, 1)
|
|
@@ -602,8 +602,72 @@ For large datasets, consider these performance optimizations:
|
|
|
602
602
|
* Only call `load_all()` when analyzing the full time evolution
|
|
603
603
|
* Use `delete()` and `delete_all()` to free memory when finished with results
|
|
604
604
|
|
|
605
|
-
2. **Computation Efficiency**:
|
|
605
|
+
2. **Computation Efficiency**:
|
|
606
606
|
|
|
607
607
|
* Averaging is computationally inexpensive compared to other operations
|
|
608
608
|
* For 2D/3D data, consider which axis to average along based on your physics
|
|
609
|
-
* For iterative analysis, calculate fluctuations only when needed
|
|
609
|
+
* For iterative analysis, calculate fluctuations only when needed
|
|
610
|
+
|
|
611
|
+
Field Centering
|
|
612
|
+
===============
|
|
613
|
+
|
|
614
|
+
.. _field-centering-api:
|
|
615
|
+
|
|
616
|
+
The `FieldCentering` module provides tools to center fields on the grid cells, converting from the Yee mesh positions to cell centers.
|
|
617
|
+
|
|
618
|
+
FieldCentering_Simulation Class
|
|
619
|
+
-------------------------------
|
|
620
|
+
|
|
621
|
+
.. autoclass:: osiris_utils.postprocessing.field_centering.FieldCentering_Simulation
|
|
622
|
+
:members:
|
|
623
|
+
:special-members: __init__, __getitem__
|
|
624
|
+
:show-inheritance:
|
|
625
|
+
:noindex:
|
|
626
|
+
|
|
627
|
+
Post-processor for centering electromagnetic fields.
|
|
628
|
+
|
|
629
|
+
The FieldCentering_Simulation class provides a convenient interface for centering fields from the Yee mesh to cell centers.
|
|
630
|
+
|
|
631
|
+
**Key Features:**
|
|
632
|
+
|
|
633
|
+
* Centers fields from Yee mesh to cell centers
|
|
634
|
+
* Handles periodic boundaries
|
|
635
|
+
* Supports 1D, 2D, and 3D simulations
|
|
636
|
+
* Lazy evaluation
|
|
637
|
+
|
|
638
|
+
**Usage Examples:**
|
|
639
|
+
|
|
640
|
+
.. code-block:: python
|
|
641
|
+
|
|
642
|
+
from osiris_utils.data import Simulation
|
|
643
|
+
from osiris_utils.postprocessing import FieldCentering_Simulation
|
|
644
|
+
|
|
645
|
+
# Create a simulation interface
|
|
646
|
+
sim = Simulation('/path/to/input/deck.inp')
|
|
647
|
+
|
|
648
|
+
# Create a field centering processor
|
|
649
|
+
centered_sim = FieldCentering_Simulation(sim)
|
|
650
|
+
|
|
651
|
+
# Get centered E1 field
|
|
652
|
+
e1_centered = centered_sim['e1']
|
|
653
|
+
|
|
654
|
+
# Access specific timestep (interpolated on-demand)
|
|
655
|
+
timestep_10 = e1_centered[10]
|
|
656
|
+
|
|
657
|
+
FieldCentering_Diagnostic Class
|
|
658
|
+
-------------------------------
|
|
659
|
+
|
|
660
|
+
.. autoclass:: osiris_utils.postprocessing.field_centering.FieldCentering_Diagnostic
|
|
661
|
+
:members:
|
|
662
|
+
:special-members: __init__, __getitem__
|
|
663
|
+
:show-inheritance:
|
|
664
|
+
:noindex:
|
|
665
|
+
|
|
666
|
+
Specialized diagnostic that represents the centered field.
|
|
667
|
+
|
|
668
|
+
This class handles the actual interpolation while maintaining the Diagnostic interface.
|
|
669
|
+
|
|
670
|
+
**Key Methods:**
|
|
671
|
+
|
|
672
|
+
* ``load_all()`` - Compute and store the complete centered field
|
|
673
|
+
* ``__getitem__(index)`` - Compute centered field for a specific timestep on-demand
|
docs/source/api/sim_diag.rst
CHANGED
|
@@ -36,8 +36,8 @@ Simulation Class
|
|
|
36
36
|
|
|
37
37
|
from osiris_utils.data import Simulation
|
|
38
38
|
|
|
39
|
-
# Create a simulation interface
|
|
40
|
-
sim = Simulation('path/to/simulation'
|
|
39
|
+
# Create a simulation interface
|
|
40
|
+
sim = Simulation('path/to/simulation/osiris.inp')
|
|
41
41
|
|
|
42
42
|
# Access the E1 field diagnostic (doesn't load data yet) - this is a Diagnostic object
|
|
43
43
|
# Since it is a diagnostic not related with the species, the species argument is not needed
|
|
@@ -63,7 +63,7 @@ Simulation Class
|
|
|
63
63
|
b3 = sim['b3']
|
|
64
64
|
|
|
65
65
|
# Load specific timesteps
|
|
66
|
-
e1[10:20] # Load timesteps 10-19
|
|
66
|
+
e1[10:20, 0:10] # Load timesteps 10-19 and x1 0-10
|
|
67
67
|
|
|
68
68
|
# Clean up to free memory
|
|
69
69
|
sim.delete_diagnostic('e1')
|
|
@@ -110,7 +110,7 @@ Diagnostic Base Class
|
|
|
110
110
|
|
|
111
111
|
**Key Attributes:**
|
|
112
112
|
|
|
113
|
-
* ``species`` - The plasma species being analyzed (
|
|
113
|
+
* ``species`` - The plasma species being analyzed (Species object)
|
|
114
114
|
* ``dx`` - Grid spacing in each direction
|
|
115
115
|
* ``nx`` - Number of grid points in each direction
|
|
116
116
|
* ``x`` - Grid coordinates
|
|
@@ -134,7 +134,9 @@ Diagnostic Base Class
|
|
|
134
134
|
.. code-block:: python
|
|
135
135
|
|
|
136
136
|
# Create diagnostic for electron charge
|
|
137
|
-
|
|
137
|
+
# Note: Use Simulation class for easier access instead of Diagnostic directly
|
|
138
|
+
electrons = Species("electrons", rqm=-1, q=-1)
|
|
139
|
+
diag = Diagnostic("/path/to/simulation", species=electrons)
|
|
138
140
|
diag.get_quantity("charge")
|
|
139
141
|
|
|
140
142
|
# Access specific timestep (without loading all data)
|
|
@@ -151,7 +153,7 @@ Diagnostic Base Class
|
|
|
151
153
|
.. code-block:: python
|
|
152
154
|
|
|
153
155
|
# Operations between diagnostics
|
|
154
|
-
sim = Simulation("/path/to/simulation"
|
|
156
|
+
sim = Simulation("/path/to/simulation/osiris.inp")
|
|
155
157
|
e1 = sim["e1"]
|
|
156
158
|
vfl1 = sim["electron"]["vfl1"]
|
|
157
159
|
|
|
@@ -221,7 +223,7 @@ One of the most powerful features of the Diagnostic system is that new diagnosti
|
|
|
221
223
|
.. code-block:: python
|
|
222
224
|
|
|
223
225
|
# Create base diagnostics
|
|
224
|
-
sim = Simulation("/path/to/simulation"
|
|
226
|
+
sim = Simulation("/path/to/simulation/osiris.inp")
|
|
225
227
|
e1 = sim["e1"]
|
|
226
228
|
e2 = sim["e2"]
|
|
227
229
|
e3 = sim["e3"]
|
docs/source/api/utilities.rst
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Utilities API
|
|
2
2
|
=============
|
|
3
3
|
|
|
4
|
-
This document provides a reference to the osiris_utils utilities API.
|
|
4
|
+
This document provides a reference to the `osiris_utils` utilities API, which includes tools for reading various OSIRIS data formats (Grid, Raw Particles, Tracks, HIST) and helper functions for common physics calculations and data operations.
|
|
5
5
|
|
|
6
6
|
Data Readers Structures
|
|
7
7
|
-----------------------
|
|
@@ -79,7 +79,7 @@ Particle Data
|
|
|
79
79
|
.. code-block:: python
|
|
80
80
|
|
|
81
81
|
import osiris_utils as ou
|
|
82
|
-
raw = ou.
|
|
82
|
+
raw = ou.OsirisRawFile("path/to/raw/file.h5")
|
|
83
83
|
print(raw.data.keys())
|
|
84
84
|
print(raw.data["x1"][0:10]) # Access x1 position of first 10 particles
|
|
85
85
|
|
|
@@ -107,7 +107,7 @@ Particle Data
|
|
|
107
107
|
raw = ou.OsirisRawFile("path/to/raw/file/.../.h5")
|
|
108
108
|
# Selecting 5 random tags from particles with energy>5
|
|
109
109
|
mask = raw.data["ene"] > 5.
|
|
110
|
-
raw_to_file_tags("output.tag", type="random", n_tags=5, mask=mask)
|
|
110
|
+
raw.raw_to_file_tags("output.tag", type="random", n_tags=5, mask=mask)
|
|
111
111
|
|
|
112
112
|
|
|
113
113
|
|
|
@@ -149,7 +149,7 @@ TRACK Data
|
|
|
149
149
|
.. code-block:: python
|
|
150
150
|
|
|
151
151
|
import osiris_utils as ou
|
|
152
|
-
track = ou.OsirisTrackFile(path/to/track_file.h5)
|
|
152
|
+
track = ou.OsirisTrackFile("path/to/track_file.h5")
|
|
153
153
|
print(track.data[0:10, :]["x1"]) # Access x1 position of first 10 particles over all time steps
|
|
154
154
|
|
|
155
155
|
|
|
@@ -175,7 +175,7 @@ Convert track file to the older more readable format
|
|
|
175
175
|
.. code-block:: python
|
|
176
176
|
|
|
177
177
|
>>> import osiris_utils as ou
|
|
178
|
-
>>> ou.
|
|
178
|
+
>>> ou.convert_tracks('path/to/input_trackfile.h5')
|
|
179
179
|
>>> # The output will be saved as 'path/to/input_trackfile-v2.h5'
|
|
180
180
|
|
|
181
181
|
**Notes:**
|
|
@@ -209,7 +209,7 @@ To create a tag file directly from raw data, see :class:`osiris_utils.data.data.
|
|
|
209
209
|
import osiris_utils as ou
|
|
210
210
|
import numpy as np
|
|
211
211
|
tags = np.array([[1, 12345], [2, 67890], [3, 11111]]) # Example tags
|
|
212
|
-
ou.
|
|
212
|
+
ou.create_file_tags('output.tag', tags)
|
|
213
213
|
# This will generate a file 'output.tag' with the particle tags.
|
|
214
214
|
|
|
215
215
|
**Notes:**
|
docs/source/conf.py
CHANGED
|
@@ -26,7 +26,7 @@ sys.path.append(os.path.abspath("../.."))
|
|
|
26
26
|
project = "osiris_utils"
|
|
27
27
|
copyright = "2025, João Biu"
|
|
28
28
|
author = "João Biu"
|
|
29
|
-
version = "v1.
|
|
29
|
+
version = "v1.2.0"
|
|
30
30
|
release = version
|
|
31
31
|
|
|
32
32
|
|
|
@@ -46,16 +46,36 @@ extensions = [
|
|
|
46
46
|
"sphinx.ext.napoleon",
|
|
47
47
|
"sphinx_copybutton",
|
|
48
48
|
"sphinx_github_style",
|
|
49
|
+
"myst_parser",
|
|
49
50
|
]
|
|
50
51
|
|
|
51
52
|
nb_execution_mode = "off" # use stored output; avoids long CI builds
|
|
52
53
|
# options for sphinx_github_style
|
|
53
54
|
top_level = "OSIRIS Utils"
|
|
54
|
-
linkcode_blob = "
|
|
55
|
+
linkcode_blob = "main"
|
|
55
56
|
linkcode_url = r"https://github.com/joaopedrobiu6/osiris_utils/"
|
|
56
57
|
linkcode_link_text = "Source"
|
|
57
58
|
|
|
58
59
|
|
|
60
|
+
def linkcode_resolve(domain, info):
|
|
61
|
+
"""Return a URL to the source code for ``info``.
|
|
62
|
+
|
|
63
|
+
This implementation avoids invoking git or requiring a tag; it
|
|
64
|
+
constructs URLs pointing at the `linkcode_blob` branch on GitHub.
|
|
65
|
+
"""
|
|
66
|
+
if domain != "py":
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
module = info.get("module")
|
|
70
|
+
if not module:
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
# Convert module path to file path
|
|
74
|
+
filename = module.replace(".", "/") + ".py"
|
|
75
|
+
|
|
76
|
+
return f"{linkcode_url}blob/{linkcode_blob}/{filename}"
|
|
77
|
+
|
|
78
|
+
|
|
59
79
|
# numpydoc_class_members_toctree = False
|
|
60
80
|
# Napoleon settings
|
|
61
81
|
napoleon_google_docstring = False
|
|
@@ -80,11 +100,11 @@ templates_path = ["_templates"]
|
|
|
80
100
|
# The suffix(es) of source filenames.
|
|
81
101
|
# You can specify multiple suffix as a list of string:
|
|
82
102
|
#
|
|
83
|
-
source_suffix = [".rst", ".md"]
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
103
|
+
# source_suffix = [".rst", ".md"]
|
|
104
|
+
source_suffix = {
|
|
105
|
+
'.rst': 'restructuredtext',
|
|
106
|
+
'.md': 'markdown',
|
|
107
|
+
}
|
|
88
108
|
# The master toctree document.
|
|
89
109
|
master_doc = "index"
|
|
90
110
|
|
|
@@ -135,7 +155,7 @@ html_css_files = ["custom.css"]
|
|
|
135
155
|
|
|
136
156
|
# The name of an image file (relative to this directory) to place at the top
|
|
137
157
|
# of the sidebar.
|
|
138
|
-
|
|
158
|
+
html_logo = '_static/Imagem1.png'
|
|
139
159
|
|
|
140
160
|
# The name of an image file (within the static path) to use as favicon of the
|
|
141
161
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
# Derivatives using `Derivative_Simulation` object
|
|
15
|
+
|
|
16
|
+
In this notebook we will show how to use the `Derivative_Simulation` object to compute derivatives of a function with respect to the time and space coordinates.
|
|
17
|
+
|
|
18
|
+
As an example, we will compute the residual of the continuity equation of a thermal plasma, in the x-direction, this is, the LHS of:
|
|
19
|
+
|
|
20
|
+
$$
|
|
21
|
+
\frac{\partial n}{\partial t} + \frac{\partial}{\partial x}(n v_1) = 0
|
|
22
|
+
$$
|
|
23
|
+
|
|
24
|
+
For this, we need the derivatives of the density `n` and the velocity `v1` with respect to the time and space coordinates. The `Derivative_Simulation` object will compute these derivatives using finite differences.
|
|
25
|
+
|
|
26
|
+
Initialize the simulation object:
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
sim = ou.Simulation(input_deck_path="example_data/thermal.1d")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Initialize the `Derivative_Simulation` objects with respect to the time and $x_1$ coordinate, since these are the derivatives that we want to compute.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
d_dt = ou.Derivative_Simulation(sim, "t")
|
|
38
|
+
d_dx1 = ou.Derivative_Simulation(sim, "x1")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Note that the derivative with respect to $x_1$ is applied not to one diagnostic, but to the product of two diagnostics. We can take advantage of the operations between diagnostics to compute this "new" diagnostic, the product of the density and the fluid velocity.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
# Create a new diagnostic n * vfl1
|
|
46
|
+
nVfl1 = sim["electrons"]["n"] * sim["electrons"]["vfl1"]
|
|
47
|
+
# Add this to the simulation (electrons)
|
|
48
|
+
sim["electrons"].add_diagnostic(nVfl1, "nVfl1")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Now that we have the diagnostics needed in our `Simulation` object, we can directly reconstruct the equation desired:
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
continuity = d_dt["electrons"]["n"] + d_dx1["electrons"]["nVfl1"]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This is a new diagnostic, and we can now access to its iterations using indexing
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
plt.figure(figsize=(8, 6))
|
|
63
|
+
plt.title("Continuity equation residuals")
|
|
64
|
+
plt.xlabel(continuity.axis[0]["plot_label"])
|
|
65
|
+
|
|
66
|
+
plt.plot(continuity.x, continuity[10], label="Continuity equation")
|
|
67
|
+
plt.legend()
|
|
68
|
+
plt.xlim(continuity.x[0], continuity.x[-1])
|
|
69
|
+
plt.show()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
plt.plot(continuity.x, ou.integrate(continuity[10], continuity.dx), label=r"$\int \partial_t n + \partial_x( n v_{fl1}) dx$")
|
|
75
|
+
plt.legend()
|
|
76
|
+
plt.xlim(continuity.x[0], continuity.x[-1])
|
|
77
|
+
plt.show()
|
|
78
|
+
```
|