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.
Files changed (54) hide show
  1. benchmarks/benchmark_hdf5_io.py +46 -0
  2. benchmarks/benchmark_load_all.py +54 -0
  3. docs/source/_static/Imagem1.png +0 -0
  4. docs/source/_static/custom.css +24 -8
  5. docs/source/api/decks.rst +48 -0
  6. docs/source/api/postprocess.rst +72 -8
  7. docs/source/api/sim_diag.rst +9 -7
  8. docs/source/api/utilities.rst +6 -6
  9. docs/source/conf.py +28 -8
  10. docs/source/examples/example_Derivatives.md +78 -0
  11. docs/source/examples/example_FFT.md +152 -0
  12. docs/source/examples/example_InputDeck.md +149 -0
  13. docs/source/examples/example_Simulation_Diagnostic.md +213 -0
  14. docs/source/examples/quick_start.md +51 -0
  15. docs/source/examples.rst +14 -0
  16. docs/source/index.rst +8 -0
  17. examples/edited-deck.1d +1 -1
  18. examples/example_Derivatives.ipynb +24 -36
  19. examples/example_FFT.ipynb +44 -23
  20. examples/example_InputDeck.ipynb +24 -277
  21. examples/example_Simulation_Diagnostic.ipynb +27 -17
  22. examples/quick_start.ipynb +17 -1
  23. osiris_utils/__init__.py +10 -6
  24. osiris_utils/cli/__init__.py +6 -0
  25. osiris_utils/cli/__main__.py +85 -0
  26. osiris_utils/cli/export.py +199 -0
  27. osiris_utils/cli/info.py +156 -0
  28. osiris_utils/cli/plot.py +189 -0
  29. osiris_utils/cli/validate.py +247 -0
  30. osiris_utils/data/__init__.py +15 -0
  31. osiris_utils/data/data.py +41 -171
  32. osiris_utils/data/diagnostic.py +285 -274
  33. osiris_utils/data/simulation.py +20 -13
  34. osiris_utils/decks/__init__.py +4 -0
  35. osiris_utils/decks/decks.py +83 -8
  36. osiris_utils/decks/species.py +12 -9
  37. osiris_utils/postprocessing/__init__.py +28 -0
  38. osiris_utils/postprocessing/derivative.py +317 -106
  39. osiris_utils/postprocessing/fft.py +135 -24
  40. osiris_utils/postprocessing/field_centering.py +28 -14
  41. osiris_utils/postprocessing/heatflux_correction.py +39 -18
  42. osiris_utils/postprocessing/mft.py +10 -2
  43. osiris_utils/postprocessing/postprocess.py +8 -5
  44. osiris_utils/postprocessing/pressure_correction.py +29 -17
  45. osiris_utils/utils.py +26 -17
  46. osiris_utils/vis/__init__.py +3 -0
  47. osiris_utils/vis/plot3d.py +148 -0
  48. {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.1.dist-info}/METADATA +61 -7
  49. {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.1.dist-info}/RECORD +53 -35
  50. {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.1.dist-info}/WHEEL +1 -1
  51. osiris_utils-1.2.1.dist-info/entry_points.txt +2 -0
  52. {osiris_utils-1.1.10a0.dist-info → osiris_utils-1.2.1.dist-info}/top_level.txt +1 -0
  53. osiris_utils/postprocessing/mft_for_gridfile.py +0 -55
  54. {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
@@ -1,6 +1,7 @@
1
1
  /* Sidebar background */
2
2
  .wy-nav-side {
3
- background: #88cbf8; /* Change to your preferred color */
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 > a {
22
+ .wy-menu-vertical li.current>a {
22
23
  background: #aeecff;
23
24
  }
24
25
 
25
26
  /* Header (H1, H2, etc.) colors */
26
- h1, h2, h3, h4, h5, h6 {
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
- white-space: normal !important;
48
- }
52
+ .wy-table-responsive table td {
53
+ white-space: normal !important;
54
+ }
49
55
 
50
- .wy-table-responsive {
51
- overflow: visible !important;
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
@@ -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', Species, "path/to/input/deck")
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
@@ -36,8 +36,8 @@ Simulation Class
36
36
 
37
37
  from osiris_utils.data import Simulation
38
38
 
39
- # Create a simulation interface for electron data
40
- sim = Simulation('path/to/simulation', "name_of_input_deck")
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 (Specie object)
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
- diag = Diagnostic("/path/to/simulation", species)
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", species)
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", "file_input_deck")
226
+ sim = Simulation("/path/to/simulation/osiris.inp")
225
227
  e1 = sim["e1"]
226
228
  e2 = sim["e2"]
227
229
  e3 = sim["e3"]
@@ -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.raw = ou.OsirisRawFile("path/to/raw/file.h5")
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.utils.convert_tracks('path/to/input_trackfile.h5')
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.utils.create_file_tags('output.tag', tags)
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.1.10a"
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 = "head"
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
- # source_suffix = {
85
- # '.rst': 'restructuredtext',
86
- # '.md': 'markdown',
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
- # html_logo = '_static/images/logo_small_clear.png'
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
+ ```