py-pluto 1.1.4__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.
- pyPLUTO/__init__.py +22 -0
- pyPLUTO/amr.py +745 -0
- pyPLUTO/baseloadmixin.py +258 -0
- pyPLUTO/baseloadstate.py +45 -0
- pyPLUTO/codes/echo_load.py +161 -0
- pyPLUTO/configure.py +261 -0
- pyPLUTO/gui/config.py +174 -0
- pyPLUTO/gui/custom_var.py +435 -0
- pyPLUTO/gui/globals.py +108 -0
- pyPLUTO/gui/main.py +17 -0
- pyPLUTO/gui/main_window.py +177 -0
- pyPLUTO/gui/panels.py +66 -0
- pyPLUTO/gui/utils.py +273 -0
- pyPLUTO/h_pypluto.py +84 -0
- pyPLUTO/image.py +302 -0
- pyPLUTO/imagefuncs/colorbar.py +240 -0
- pyPLUTO/imagefuncs/contour.py +254 -0
- pyPLUTO/imagefuncs/create_axes.py +464 -0
- pyPLUTO/imagefuncs/display.py +306 -0
- pyPLUTO/imagefuncs/figure.py +395 -0
- pyPLUTO/imagefuncs/imagetools.py +487 -0
- pyPLUTO/imagefuncs/interactive.py +403 -0
- pyPLUTO/imagefuncs/legend.py +250 -0
- pyPLUTO/imagefuncs/plot.py +311 -0
- pyPLUTO/imagefuncs/range.py +242 -0
- pyPLUTO/imagefuncs/scatter.py +270 -0
- pyPLUTO/imagefuncs/set_axis.py +497 -0
- pyPLUTO/imagefuncs/streamplot.py +297 -0
- pyPLUTO/imagefuncs/zoom.py +428 -0
- pyPLUTO/imagemixin.py +259 -0
- pyPLUTO/imagestate.py +45 -0
- pyPLUTO/load.py +447 -0
- pyPLUTO/loadfuncs/baseloadtools.py +71 -0
- pyPLUTO/loadfuncs/codeselection.py +48 -0
- pyPLUTO/loadfuncs/defpluto.py +123 -0
- pyPLUTO/loadfuncs/descriptor.py +102 -0
- pyPLUTO/loadfuncs/findfiles.py +182 -0
- pyPLUTO/loadfuncs/findformat.py +245 -0
- pyPLUTO/loadfuncs/initload.py +203 -0
- pyPLUTO/loadfuncs/loadvars.py +227 -0
- pyPLUTO/loadfuncs/offsetdata.py +87 -0
- pyPLUTO/loadfuncs/offsetfluid.py +408 -0
- pyPLUTO/loadfuncs/read_files.py +213 -0
- pyPLUTO/loadfuncs/readdata.py +619 -0
- pyPLUTO/loadfuncs/readdata_old.py +567 -0
- pyPLUTO/loadfuncs/readdefplini.py +101 -0
- pyPLUTO/loadfuncs/readfluid.py +479 -0
- pyPLUTO/loadfuncs/readformat.py +277 -0
- pyPLUTO/loadfuncs/readgridalone.py +224 -0
- pyPLUTO/loadfuncs/readgridfile.py +255 -0
- pyPLUTO/loadfuncs/readgridout.py +451 -0
- pyPLUTO/loadfuncs/readpart.py +419 -0
- pyPLUTO/loadfuncs/readtab.py +105 -0
- pyPLUTO/loadfuncs/write_files.py +283 -0
- pyPLUTO/loadmixin.py +419 -0
- pyPLUTO/loadpart.py +233 -0
- pyPLUTO/loadstate.py +68 -0
- pyPLUTO/newload.py +81 -0
- pyPLUTO/pytools.py +145 -0
- pyPLUTO/toolfuncs/findlines.py +551 -0
- pyPLUTO/toolfuncs/fourier.py +149 -0
- pyPLUTO/toolfuncs/nabla.py +676 -0
- pyPLUTO/toolfuncs/parttools.py +152 -0
- pyPLUTO/toolfuncs/transform.py +638 -0
- pyPLUTO/utils/annotator.py +27 -0
- pyPLUTO/utils/inspector.py +145 -0
- pyPLUTO/utils/make_docstrings.py +3 -0
- py_pluto-1.1.4.dist-info/METADATA +218 -0
- py_pluto-1.1.4.dist-info/RECORD +73 -0
- py_pluto-1.1.4.dist-info/WHEEL +5 -0
- py_pluto-1.1.4.dist-info/entry_points.txt +2 -0
- py_pluto-1.1.4.dist-info/licenses/LICENSE +27 -0
- py_pluto-1.1.4.dist-info/top_level.txt +1 -0
pyPLUTO/amr.py
ADDED
|
@@ -0,0 +1,745 @@
|
|
|
1
|
+
import h5py
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _inspect_hdf5(self, i: int, exout: int) -> None:
|
|
6
|
+
"""Routine to inspect the hdf5 file from chombo.
|
|
7
|
+
|
|
8
|
+
Returns
|
|
9
|
+
-------
|
|
10
|
+
- None
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
- exout (not optional): int
|
|
15
|
+
The index of the output to be loaded.
|
|
16
|
+
- i (not optional): int
|
|
17
|
+
The index of the file to be loaded.
|
|
18
|
+
|
|
19
|
+
Notes
|
|
20
|
+
-----
|
|
21
|
+
- This routines will be optimize in the future, alongside a novel
|
|
22
|
+
implementation of the AMR in the PLUTO code.
|
|
23
|
+
|
|
24
|
+
----
|
|
25
|
+
|
|
26
|
+
Examples
|
|
27
|
+
--------
|
|
28
|
+
- Example #1: Inspect the hdf5 file
|
|
29
|
+
|
|
30
|
+
>>> _inspect_hdf5(0, 0)
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
try:
|
|
34
|
+
self._read_gridfile()
|
|
35
|
+
except FileNotFoundError:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
self.x1range = None
|
|
39
|
+
self.x2range = None
|
|
40
|
+
self.x3range = None
|
|
41
|
+
|
|
42
|
+
h5file = h5py.File(self._filepath, "r")
|
|
43
|
+
self.multiple = False
|
|
44
|
+
self.d_info["varslist"] = []
|
|
45
|
+
self.ntime = h5file.attrs.get("time")
|
|
46
|
+
for i in range(h5file.attrs.get("num_components")):
|
|
47
|
+
self.d_info["varslist"].append(h5file.attrs.get("component_" + str(i)))
|
|
48
|
+
|
|
49
|
+
NewData = self._DataScanHDF5(h5file, self.d_info["varslist"], self.level)
|
|
50
|
+
|
|
51
|
+
for key in NewData.keys():
|
|
52
|
+
if key == "grid":
|
|
53
|
+
for key2 in NewData[key].keys():
|
|
54
|
+
setattr(self, key2, NewData[key][key2])
|
|
55
|
+
continue
|
|
56
|
+
setattr(self, key, NewData[key])
|
|
57
|
+
|
|
58
|
+
h5file.close()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _DataScanHDF5(self, fp, myvars, ilev) -> dict:
|
|
62
|
+
"""Scans the Chombo HDF5 data files for AMR in PLUTO.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
- OutDict: dictionary
|
|
67
|
+
The dictionary consisting of variable names as keys and its values.
|
|
68
|
+
|
|
69
|
+
Parameters
|
|
70
|
+
----------
|
|
71
|
+
- fp: pointer
|
|
72
|
+
The data file pointer.
|
|
73
|
+
- ilev: float
|
|
74
|
+
The AMR level.
|
|
75
|
+
- myvars: str
|
|
76
|
+
The names of the variables to be read.
|
|
77
|
+
|
|
78
|
+
Notes
|
|
79
|
+
-----
|
|
80
|
+
- Due to the particularity of AMR, the grid arrays loaded in ReadGridFile
|
|
81
|
+
are overwritten here.
|
|
82
|
+
- This routines will be optimize in the future, alongside a novel
|
|
83
|
+
implementation of the AMR in the PLUTO code.
|
|
84
|
+
|
|
85
|
+
----
|
|
86
|
+
|
|
87
|
+
Examples
|
|
88
|
+
--------
|
|
89
|
+
- Example #1:
|
|
90
|
+
|
|
91
|
+
>>> _DataScanHDF5(fp, myvars, ilev)
|
|
92
|
+
|
|
93
|
+
"""
|
|
94
|
+
# Read the grid information
|
|
95
|
+
dim = fp["Chombo_global"].attrs.get("SpaceDim")
|
|
96
|
+
nlev = fp.attrs.get("num_levels")
|
|
97
|
+
il = min(nlev - 1, ilev)
|
|
98
|
+
lev = []
|
|
99
|
+
for i in range(nlev):
|
|
100
|
+
lev.append("level_" + str(i))
|
|
101
|
+
freb = np.zeros(nlev, dtype="int")
|
|
102
|
+
for i in range(il + 1)[::-1]:
|
|
103
|
+
fl = fp[lev[i]]
|
|
104
|
+
if i == il:
|
|
105
|
+
pdom = fl.attrs.get("prob_domain")
|
|
106
|
+
dx = fl.attrs.get("dx")
|
|
107
|
+
dt = fl.attrs.get("dt")
|
|
108
|
+
ystr = 1.0
|
|
109
|
+
zstr = 1.0
|
|
110
|
+
logr = 0
|
|
111
|
+
try:
|
|
112
|
+
# self.geom = fl.attrs.get("geometry")
|
|
113
|
+
logr = fl.attrs.get("logr")
|
|
114
|
+
if dim >= 2:
|
|
115
|
+
ystr = fl.attrs.get("g_x2stretch")
|
|
116
|
+
if dim == 3:
|
|
117
|
+
zstr = fl.attrs.get("g_x3stretch")
|
|
118
|
+
except DeprecationWarning:
|
|
119
|
+
print("Old HDF5 file, not reading stretch and logr factors")
|
|
120
|
+
freb[i] = 1
|
|
121
|
+
x1b = fl.attrs.get("domBeg1")
|
|
122
|
+
if dim == 1:
|
|
123
|
+
x2b = 0
|
|
124
|
+
else:
|
|
125
|
+
x2b = fl.attrs.get("domBeg2")
|
|
126
|
+
if dim == 1 or dim == 2:
|
|
127
|
+
x3b = 0
|
|
128
|
+
else:
|
|
129
|
+
x3b = fl.attrs.get("domBeg3")
|
|
130
|
+
jbeg = 0
|
|
131
|
+
jend = 0
|
|
132
|
+
ny = 1
|
|
133
|
+
kbeg = 0
|
|
134
|
+
kend = 0
|
|
135
|
+
nz = 1
|
|
136
|
+
if dim == 1:
|
|
137
|
+
ibeg = pdom[0]
|
|
138
|
+
iend = pdom[1]
|
|
139
|
+
nx = iend - ibeg + 1
|
|
140
|
+
elif dim == 2:
|
|
141
|
+
ibeg = pdom[0]
|
|
142
|
+
iend = pdom[2]
|
|
143
|
+
nx = iend - ibeg + 1
|
|
144
|
+
jbeg = pdom[1]
|
|
145
|
+
jend = pdom[3]
|
|
146
|
+
ny = jend - jbeg + 1
|
|
147
|
+
elif dim == 3:
|
|
148
|
+
ibeg = pdom[0]
|
|
149
|
+
iend = pdom[3]
|
|
150
|
+
nx = iend - ibeg + 1
|
|
151
|
+
jbeg = pdom[1]
|
|
152
|
+
jend = pdom[4]
|
|
153
|
+
ny = jend - jbeg + 1
|
|
154
|
+
kbeg = pdom[2]
|
|
155
|
+
kend = pdom[5]
|
|
156
|
+
nz = kend - kbeg + 1
|
|
157
|
+
else:
|
|
158
|
+
rat = fl.attrs.get("ref_ratio")
|
|
159
|
+
freb[i] = rat * freb[i + 1]
|
|
160
|
+
|
|
161
|
+
dx0 = dx * freb[0]
|
|
162
|
+
|
|
163
|
+
## Allow to load only a portion of the domain
|
|
164
|
+
if self.x1range is not None:
|
|
165
|
+
if logr == 0:
|
|
166
|
+
self.x1range = self.x1range - x1b
|
|
167
|
+
else:
|
|
168
|
+
self.x1range = [
|
|
169
|
+
np.log(self.x1range[0] / x1b),
|
|
170
|
+
np.log(self.x1range[1] / x1b),
|
|
171
|
+
]
|
|
172
|
+
ibeg0 = min(self.x1range) / dx0
|
|
173
|
+
iend0 = max(self.x1range) / dx0
|
|
174
|
+
ibeg = max([ibeg, int(ibeg0 * freb[0])])
|
|
175
|
+
iend = min([iend, int(iend0 * freb[0] - 1)])
|
|
176
|
+
nx = iend - ibeg + 1
|
|
177
|
+
if self.x2range is not None:
|
|
178
|
+
self.x2range = (self.x2range - x2b) / ystr
|
|
179
|
+
jbeg0 = min(self.x2range) / dx0
|
|
180
|
+
jend0 = max(self.x2range) / dx0
|
|
181
|
+
jbeg = max([jbeg, int(jbeg0 * freb[0])])
|
|
182
|
+
jend = min([jend, int(jend0 * freb[0] - 1)])
|
|
183
|
+
ny = jend - jbeg + 1
|
|
184
|
+
if self.x3range is not None:
|
|
185
|
+
self.x3range = (self.x3range - x3b) / zstr
|
|
186
|
+
kbeg0 = min(self.x3range) / dx0
|
|
187
|
+
kend0 = max(self.x3range) / dx0
|
|
188
|
+
kbeg = max([kbeg, int(kbeg0 * freb[0])])
|
|
189
|
+
kend = min([kend, int(kend0 * freb[0] - 1)])
|
|
190
|
+
nz = kend - kbeg + 1
|
|
191
|
+
|
|
192
|
+
## Create uniform grids at the required level
|
|
193
|
+
if logr == 0:
|
|
194
|
+
x1 = x1b + (ibeg + np.array(range(nx)) + 0.5) * dx
|
|
195
|
+
else:
|
|
196
|
+
x1 = (
|
|
197
|
+
x1b
|
|
198
|
+
* (
|
|
199
|
+
np.exp((ibeg + np.array(range(nx)) + 1) * dx)
|
|
200
|
+
+ np.exp((ibeg + np.array(range(nx))) * dx)
|
|
201
|
+
)
|
|
202
|
+
* 0.5
|
|
203
|
+
)
|
|
204
|
+
x2 = x2b + (jbeg + np.array(range(ny)) + 0.5) * dx * ystr
|
|
205
|
+
x3 = x3b + (kbeg + np.array(range(nz)) + 0.5) * dx * zstr
|
|
206
|
+
if logr == 0:
|
|
207
|
+
dx1 = np.ones(nx) * dx
|
|
208
|
+
else:
|
|
209
|
+
dx1 = x1b * (
|
|
210
|
+
np.exp((ibeg + np.array(range(nx)) + 1) * dx)
|
|
211
|
+
- np.exp((ibeg + np.array(range(nx))) * dx)
|
|
212
|
+
)
|
|
213
|
+
dx2 = np.ones(ny) * dx * ystr
|
|
214
|
+
dx3 = np.ones(nz) * dx * zstr
|
|
215
|
+
|
|
216
|
+
# Create the xr arrays containing the edges positions
|
|
217
|
+
# Useful for pcolormesh which should use those
|
|
218
|
+
x1r = np.zeros(len(x1) + 1)
|
|
219
|
+
x1r[1:] = x1 + dx1 / 2.0
|
|
220
|
+
x1r[0] = x1r[1] - dx1[0]
|
|
221
|
+
x2r = np.zeros(len(x2) + 1)
|
|
222
|
+
x2r[1:] = x2 + dx2 / 2.0
|
|
223
|
+
x2r[0] = x2r[1] - dx2[0]
|
|
224
|
+
x3r = np.zeros(len(x3) + 1)
|
|
225
|
+
x3r[1:] = x3 + dx3 / 2.0
|
|
226
|
+
x3r[0] = x3r[1] - dx3[0]
|
|
227
|
+
NewGridDict = dict(
|
|
228
|
+
[
|
|
229
|
+
("n1", nx),
|
|
230
|
+
("n2", ny),
|
|
231
|
+
("n3", nz),
|
|
232
|
+
("x1", x1),
|
|
233
|
+
("x2", x2),
|
|
234
|
+
("x3", x3),
|
|
235
|
+
("x1r", x1r),
|
|
236
|
+
("x2r", x2r),
|
|
237
|
+
("x3r", x3r),
|
|
238
|
+
("dx1", dx1),
|
|
239
|
+
("dx2", dx2),
|
|
240
|
+
("dx3", dx3),
|
|
241
|
+
("Dt", dt),
|
|
242
|
+
]
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Variables table
|
|
246
|
+
nvar = len(myvars)
|
|
247
|
+
vars = np.zeros((nx, ny, nz, nvar))
|
|
248
|
+
LevelDic = {
|
|
249
|
+
"nbox": 0,
|
|
250
|
+
"ibeg": ibeg,
|
|
251
|
+
"iend": iend,
|
|
252
|
+
"jbeg": jbeg,
|
|
253
|
+
"jend": jend,
|
|
254
|
+
"kbeg": kbeg,
|
|
255
|
+
"kend": kend,
|
|
256
|
+
}
|
|
257
|
+
AMRLevel = []
|
|
258
|
+
AMRBoxes = np.zeros((nx, ny, nz))
|
|
259
|
+
for i in range(il + 1):
|
|
260
|
+
AMRLevel.append(LevelDic.copy())
|
|
261
|
+
fl = fp[lev[i]]
|
|
262
|
+
data = fl["data:datatype=0"]
|
|
263
|
+
boxes = fl["boxes"]
|
|
264
|
+
nbox = len(boxes["lo_i"])
|
|
265
|
+
AMRLevel[i]["nbox"] = nbox
|
|
266
|
+
ncount = 0
|
|
267
|
+
AMRLevel[i]["box"] = []
|
|
268
|
+
for j in range(nbox): # loop on all boxes of a given level
|
|
269
|
+
AMRLevel[i]["box"].append(
|
|
270
|
+
{
|
|
271
|
+
"x0": 0.0,
|
|
272
|
+
"x1": 0.0,
|
|
273
|
+
"ib": 0,
|
|
274
|
+
"ie": 0,
|
|
275
|
+
"y0": 0.0,
|
|
276
|
+
"y1": 0.0,
|
|
277
|
+
"jb": 0,
|
|
278
|
+
"je": 0,
|
|
279
|
+
"z0": 0.0,
|
|
280
|
+
"z1": 0.0,
|
|
281
|
+
"kb": 0,
|
|
282
|
+
"ke": 0,
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
# Box indexes
|
|
286
|
+
ib = boxes[j]["lo_i"]
|
|
287
|
+
ie = boxes[j]["hi_i"]
|
|
288
|
+
nbx = ie - ib + 1
|
|
289
|
+
jb = 0
|
|
290
|
+
je = 0
|
|
291
|
+
nby = 1
|
|
292
|
+
kb = 0
|
|
293
|
+
ke = 0
|
|
294
|
+
nbz = 1
|
|
295
|
+
if dim > 1:
|
|
296
|
+
jb = boxes[j]["lo_j"]
|
|
297
|
+
je = boxes[j]["hi_j"]
|
|
298
|
+
nby = je - jb + 1
|
|
299
|
+
if dim > 2:
|
|
300
|
+
kb = boxes[j]["lo_k"]
|
|
301
|
+
ke = boxes[j]["hi_k"]
|
|
302
|
+
nbz = ke - kb + 1
|
|
303
|
+
szb = nbx * nby * nbz * nvar
|
|
304
|
+
# Rescale to current level
|
|
305
|
+
kb = kb * freb[i]
|
|
306
|
+
ke = (ke + 1) * freb[i] - 1
|
|
307
|
+
jb = jb * freb[i]
|
|
308
|
+
je = (je + 1) * freb[i] - 1
|
|
309
|
+
ib = ib * freb[i]
|
|
310
|
+
ie = (ie + 1) * freb[i] - 1
|
|
311
|
+
|
|
312
|
+
# Skip boxes lying outside ranges
|
|
313
|
+
if (
|
|
314
|
+
(ib > iend)
|
|
315
|
+
or (ie < ibeg)
|
|
316
|
+
or (jb > jend)
|
|
317
|
+
or (je < jbeg)
|
|
318
|
+
or (kb > kend)
|
|
319
|
+
or (ke < kbeg)
|
|
320
|
+
):
|
|
321
|
+
ncount = ncount + szb
|
|
322
|
+
else:
|
|
323
|
+
### Read data
|
|
324
|
+
q = data[ncount : ncount + szb].reshape((nvar, nbz, nby, nbx)).T
|
|
325
|
+
|
|
326
|
+
### Find boxes intersections with current domain ranges
|
|
327
|
+
ib0 = max([ibeg, ib])
|
|
328
|
+
ie0 = min([iend, ie])
|
|
329
|
+
jb0 = max([jbeg, jb])
|
|
330
|
+
je0 = min([jend, je])
|
|
331
|
+
kb0 = max([kbeg, kb])
|
|
332
|
+
ke0 = min([kend, ke])
|
|
333
|
+
|
|
334
|
+
### Store box corners in the AMRLevel structure
|
|
335
|
+
if logr == 0:
|
|
336
|
+
AMRLevel[i]["box"][j]["x0"] = x1b + dx * (ib0)
|
|
337
|
+
AMRLevel[i]["box"][j]["x1"] = x1b + dx * (ie0 + 1)
|
|
338
|
+
else:
|
|
339
|
+
AMRLevel[i]["box"][j]["x0"] = x1b * np.exp(dx * (ib0))
|
|
340
|
+
AMRLevel[i]["box"][j]["x1"] = x1b * np.exp(dx * (ie0 + 1))
|
|
341
|
+
AMRLevel[i]["box"][j]["y0"] = x2b + dx * (jb0) * ystr
|
|
342
|
+
AMRLevel[i]["box"][j]["y1"] = x2b + dx * (je0 + 1) * ystr
|
|
343
|
+
AMRLevel[i]["box"][j]["z0"] = x3b + dx * (kb0) * zstr
|
|
344
|
+
AMRLevel[i]["box"][j]["z1"] = x3b + dx * (ke0 + 1) * zstr
|
|
345
|
+
AMRLevel[i]["box"][j]["ib"] = ib0
|
|
346
|
+
AMRLevel[i]["box"][j]["ie"] = ie0
|
|
347
|
+
AMRLevel[i]["box"][j]["jb"] = jb0
|
|
348
|
+
AMRLevel[i]["box"][j]["je"] = je0
|
|
349
|
+
AMRLevel[i]["box"][j]["kb"] = kb0
|
|
350
|
+
AMRLevel[i]["box"][j]["ke"] = ke0
|
|
351
|
+
AMRBoxes[
|
|
352
|
+
ib0 - ibeg : ie0 - ibeg + 1,
|
|
353
|
+
jb0 - jbeg : je0 - jbeg + 1,
|
|
354
|
+
kb0 - kbeg : ke0 - kbeg + 1,
|
|
355
|
+
] = il
|
|
356
|
+
|
|
357
|
+
### Extract the box intersection from data stored in q
|
|
358
|
+
cib0 = (ib0 - ib) // freb[i]
|
|
359
|
+
cie0 = (ie0 - ib) // freb[i]
|
|
360
|
+
cjb0 = (jb0 - jb) // freb[i]
|
|
361
|
+
cje0 = (je0 - jb) // freb[i]
|
|
362
|
+
ckb0 = (kb0 - kb) // freb[i]
|
|
363
|
+
cke0 = (ke0 - kb) // freb[i]
|
|
364
|
+
q1 = np.zeros(
|
|
365
|
+
(cie0 - cib0 + 1, cje0 - cjb0 + 1, cke0 - ckb0 + 1, nvar)
|
|
366
|
+
)
|
|
367
|
+
q1 = q[cib0 : cie0 + 1, cjb0 : cje0 + 1, ckb0 : cke0 + 1, :]
|
|
368
|
+
|
|
369
|
+
# Remap the extracted portion
|
|
370
|
+
if dim == 1:
|
|
371
|
+
new_shape = (ie0 - ib0 + 1, 1)
|
|
372
|
+
elif dim == 2:
|
|
373
|
+
new_shape = (ie0 - ib0 + 1, je0 - jb0 + 1)
|
|
374
|
+
else:
|
|
375
|
+
new_shape = (ie0 - ib0 + 1, je0 - jb0 + 1, ke0 - kb0 + 1)
|
|
376
|
+
|
|
377
|
+
stmp = list(new_shape)
|
|
378
|
+
while stmp.count(1) > 0:
|
|
379
|
+
stmp.remove(1)
|
|
380
|
+
new_shape = tuple(stmp)
|
|
381
|
+
|
|
382
|
+
for iv in range(nvar):
|
|
383
|
+
vars[
|
|
384
|
+
ib0 - ibeg : ie0 - ibeg + 1,
|
|
385
|
+
jb0 - jbeg : je0 - jbeg + 1,
|
|
386
|
+
kb0 - kbeg : ke0 - kbeg + 1,
|
|
387
|
+
iv,
|
|
388
|
+
] = self._congrid(
|
|
389
|
+
q1[:, :, :, iv].squeeze(),
|
|
390
|
+
new_shape,
|
|
391
|
+
method="linear",
|
|
392
|
+
minusone=True,
|
|
393
|
+
).reshape((ie0 - ib0 + 1, je0 - jb0 + 1, ke0 - kb0 + 1))
|
|
394
|
+
ncount = ncount + szb
|
|
395
|
+
|
|
396
|
+
h5vardict = {}
|
|
397
|
+
for iv in range(nvar):
|
|
398
|
+
myvars[iv] = myvars[iv].decode()
|
|
399
|
+
h5vardict[myvars[iv]] = vars[:, :, :, iv].squeeze().T
|
|
400
|
+
self.load_vars = myvars
|
|
401
|
+
AMRdict = dict([("AMRBoxes", AMRBoxes), ("AMRLevel", AMRLevel)])
|
|
402
|
+
OutDict = dict(NewGridDict)
|
|
403
|
+
OutDict.update(AMRdict)
|
|
404
|
+
OutDict.update(h5vardict)
|
|
405
|
+
|
|
406
|
+
return OutDict
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def oplotbox(
|
|
410
|
+
self,
|
|
411
|
+
AMRLevel,
|
|
412
|
+
lrange=[0, 0],
|
|
413
|
+
cval=None,
|
|
414
|
+
islice=-1,
|
|
415
|
+
jslice=-1,
|
|
416
|
+
kslice=-1,
|
|
417
|
+
geom="CARTESIAN",
|
|
418
|
+
ax=None,
|
|
419
|
+
**kwargs,
|
|
420
|
+
) -> None:
|
|
421
|
+
"""This method overplots the AMR boxes up to the specified level.
|
|
422
|
+
|
|
423
|
+
Returns
|
|
424
|
+
-------
|
|
425
|
+
- None
|
|
426
|
+
|
|
427
|
+
Parameters
|
|
428
|
+
----------
|
|
429
|
+
- AMRLevel: AMR object
|
|
430
|
+
AMR object loaded during the reading and stored in the pload object.
|
|
431
|
+
- ax: axis object
|
|
432
|
+
The axis object where to plot the AMR boxes.
|
|
433
|
+
- cval: str | None
|
|
434
|
+
List of colors for the levels to be overplotted.
|
|
435
|
+
- geom: str, default 'CARTESIAN'
|
|
436
|
+
The specified geometry. At the moment 'CARTESIAN' and 'POLAR' are the
|
|
437
|
+
handled geometries.
|
|
438
|
+
- islice: int
|
|
439
|
+
The index of the 2D slice along x-axis direction.
|
|
440
|
+
- jslice: int
|
|
441
|
+
The index of the 2D slice along y-axis direction.
|
|
442
|
+
- kslice: int, default min(x3)
|
|
443
|
+
The index of the 2D slice along z-axis direction.
|
|
444
|
+
- kwargs: Any
|
|
445
|
+
The kwargs of the plot method.
|
|
446
|
+
- lrange: [level_min, level_max]
|
|
447
|
+
The range to be overplotted.
|
|
448
|
+
|
|
449
|
+
----
|
|
450
|
+
|
|
451
|
+
Examples
|
|
452
|
+
--------
|
|
453
|
+
- Example #1: Overplot the AMR boxes up to the specified level
|
|
454
|
+
|
|
455
|
+
>>> oplotbox(AMRLevel, lrange=[0, 2])
|
|
456
|
+
|
|
457
|
+
"""
|
|
458
|
+
nlev = len(AMRLevel)
|
|
459
|
+
lrange[1] = min(lrange[1], nlev - 1)
|
|
460
|
+
npl = lrange[1] - lrange[0] + 1
|
|
461
|
+
lpls = [lrange[0] + v for v in range(npl)]
|
|
462
|
+
cols = cval[0:nlev] if cval is not None else self.color[0:nlev]
|
|
463
|
+
# Get the offset and the type of slice
|
|
464
|
+
Slice = 0
|
|
465
|
+
inds = "k"
|
|
466
|
+
xx = "x"
|
|
467
|
+
yy = "y"
|
|
468
|
+
if islice >= 0:
|
|
469
|
+
Slice = islice + AMRLevel[0]["ibeg"]
|
|
470
|
+
inds = "i"
|
|
471
|
+
xx = "y"
|
|
472
|
+
yy = "z"
|
|
473
|
+
if jslice >= 0:
|
|
474
|
+
Slice = jslice + AMRLevel[0]["jbeg"]
|
|
475
|
+
inds = "j"
|
|
476
|
+
xx = "x"
|
|
477
|
+
yy = "z"
|
|
478
|
+
if kslice >= 0:
|
|
479
|
+
Slice = kslice + AMRLevel[0]["kbeg"]
|
|
480
|
+
inds = "k"
|
|
481
|
+
xx = "x"
|
|
482
|
+
yy = "y"
|
|
483
|
+
|
|
484
|
+
# Overplot the boxes
|
|
485
|
+
for il in lpls:
|
|
486
|
+
level = AMRLevel[il]
|
|
487
|
+
for ib in range(level["nbox"]):
|
|
488
|
+
box = level["box"][ib]
|
|
489
|
+
if (Slice - box[inds + "b"]) * (box[inds + "e"] - Slice) >= 0:
|
|
490
|
+
if geom == "CARTESIAN":
|
|
491
|
+
x0 = box[xx + "0"]
|
|
492
|
+
x1 = box[xx + "1"]
|
|
493
|
+
y0 = box[yy + "0"]
|
|
494
|
+
y1 = box[yy + "1"]
|
|
495
|
+
self.plot(
|
|
496
|
+
[x0, x1, x1, x0, x0],
|
|
497
|
+
[y0, y0, y1, y1, y0],
|
|
498
|
+
color=cols[il],
|
|
499
|
+
ax=ax,
|
|
500
|
+
**kwargs,
|
|
501
|
+
)
|
|
502
|
+
elif (geom == "POLAR") or (geom == "SPHERICAL"):
|
|
503
|
+
dn = np.pi / 50.0
|
|
504
|
+
x0 = box[xx + "0"]
|
|
505
|
+
x1 = box[xx + "1"]
|
|
506
|
+
y0 = box[yy + "0"]
|
|
507
|
+
y1 = box[yy + "1"]
|
|
508
|
+
if y0 == y1:
|
|
509
|
+
y1 = 2 * np.pi + y0 - 1.0e-3
|
|
510
|
+
if kslice >= 0 and geom == "SPHERICAL":
|
|
511
|
+
y0 = np.pi / 2 - y0
|
|
512
|
+
y1 = np.pi / 2 - y1
|
|
513
|
+
xb = np.concatenate(
|
|
514
|
+
[
|
|
515
|
+
[x0 * np.cos(y0), x1 * np.cos(y0)],
|
|
516
|
+
x1
|
|
517
|
+
* np.cos(
|
|
518
|
+
np.linspace(y0, y1, num=int(abs(y0 - y1) / dn))
|
|
519
|
+
),
|
|
520
|
+
[x1 * np.cos(y1), x0 * np.cos(y1)],
|
|
521
|
+
x0
|
|
522
|
+
* np.cos(
|
|
523
|
+
np.linspace(y1, y0, num=int(abs(y0 - y1) / dn))
|
|
524
|
+
),
|
|
525
|
+
]
|
|
526
|
+
)
|
|
527
|
+
yb = np.concatenate(
|
|
528
|
+
[
|
|
529
|
+
[x0 * np.sin(y0), x1 * np.sin(y0)],
|
|
530
|
+
x1
|
|
531
|
+
* np.sin(
|
|
532
|
+
np.linspace(y0, y1, num=int(abs(y0 - y1) / dn))
|
|
533
|
+
),
|
|
534
|
+
[x1 * np.sin(y1), x0 * np.sin(y1)],
|
|
535
|
+
x0
|
|
536
|
+
* np.sin(
|
|
537
|
+
np.linspace(y1, y0, num=int(abs(y0 - y1) / dn))
|
|
538
|
+
),
|
|
539
|
+
]
|
|
540
|
+
)
|
|
541
|
+
self.plot(xb, yb, c=cols[il], ax=ax, **kwargs)
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
def _read_gridfile(self) -> None:
|
|
545
|
+
"""The file grid.out is read and all the grid information are stored
|
|
546
|
+
in the Load class. Such information are the dimensions, the
|
|
547
|
+
geometry, the center and edges of each cell, the grid shape and size
|
|
548
|
+
and, in case of non cartesian coordinates, the transformed cartesian
|
|
549
|
+
coordinates (only 2D for now).bThe full non-cartesian 3D
|
|
550
|
+
transformations have not been implemented yet.
|
|
551
|
+
|
|
552
|
+
Returns
|
|
553
|
+
-------
|
|
554
|
+
- None
|
|
555
|
+
|
|
556
|
+
Parameters
|
|
557
|
+
----------
|
|
558
|
+
- None
|
|
559
|
+
|
|
560
|
+
----
|
|
561
|
+
|
|
562
|
+
Examples
|
|
563
|
+
--------
|
|
564
|
+
- Example #1: read the grid file
|
|
565
|
+
|
|
566
|
+
>>> _read_gridfile()
|
|
567
|
+
|
|
568
|
+
"""
|
|
569
|
+
# Initialize relevant lists
|
|
570
|
+
nmax, xL, xR = [], [], []
|
|
571
|
+
|
|
572
|
+
# Open and read the gridfile
|
|
573
|
+
with open(self._pathgrid) as gfp:
|
|
574
|
+
for i in gfp.readlines():
|
|
575
|
+
self._split_gridfile(i, xL, xR, nmax)
|
|
576
|
+
|
|
577
|
+
# Compute nx1, nx2, nx3
|
|
578
|
+
self.nx1, self.nx2, self.nx3 = nmax
|
|
579
|
+
nx1p2 = self.nx1 + self.nx2
|
|
580
|
+
nx1p3 = self.nx1 + self.nx2 + self.nx3
|
|
581
|
+
|
|
582
|
+
# Define grid shapes based on dimensions
|
|
583
|
+
nx1s, nx2s, nx3s = self.nx1 + 1, self.nx2 + 1, self.nx3 + 1
|
|
584
|
+
GRID_SHAPES = {
|
|
585
|
+
1: lambda nx1, _, __: (nx1, nx1s, None, None),
|
|
586
|
+
2: lambda nx1, nx2, _: ((nx2, nx1), (nx2, nx1s), (nx2s, nx1), None),
|
|
587
|
+
3: lambda nx1, nx2, nx3: (
|
|
588
|
+
(nx3, nx2, nx1),
|
|
589
|
+
(nx3, nx2, nx1s),
|
|
590
|
+
(nx3, nx2s, nx1),
|
|
591
|
+
(nx3s, nx2, nx1),
|
|
592
|
+
),
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
# Determine grid shape based on dimension
|
|
596
|
+
(self.nshp, self._nshp_st1, self._nshp_st2, self._nshp_st3) = GRID_SHAPES[
|
|
597
|
+
self.dim
|
|
598
|
+
](self.nx1, self.nx2, self.nx3)
|
|
599
|
+
|
|
600
|
+
# Compute the centered and staggered grid values
|
|
601
|
+
self.x1r = np.array(xL[0 : self.nx1] + [xR[self.nx1 - 1]])
|
|
602
|
+
self.x1 = 0.5 * (self.x1r[:-1] + self.x1r[1:])
|
|
603
|
+
self.dx1 = self.x1r[1:] - self.x1r[:-1]
|
|
604
|
+
|
|
605
|
+
self.x2r = np.array(xL[self.nx1 : nx1p2] + [xR[nx1p2 - 1]])
|
|
606
|
+
self.x2 = 0.5 * (self.x2r[:-1] + self.x2r[1:])
|
|
607
|
+
self.dx2 = self.x2r[1:] - self.x2r[:-1]
|
|
608
|
+
|
|
609
|
+
self.x3r = np.array(xL[nx1p2:nx1p3] + [xR[nx1p3 - 1]])
|
|
610
|
+
self.x3 = 0.5 * (self.x3r[:-1] + self.x3r[1:])
|
|
611
|
+
self.dx3 = self.x3r[1:] - self.x3r[:-1]
|
|
612
|
+
|
|
613
|
+
# Compute the cartesian grid coordinates (non-cartesian geometry)
|
|
614
|
+
|
|
615
|
+
if self.geom == "POLAR" or self.geom == "CYLINDRICAL":
|
|
616
|
+
x1_2D, x2_2D = np.meshgrid(self.x1, self.x2, indexing="ij")
|
|
617
|
+
x1r_2D, x2r_2D = np.meshgrid(self.x1r, self.x2r, indexing="ij")
|
|
618
|
+
|
|
619
|
+
self.x1c = (np.cos(x2_2D) * x1_2D).T
|
|
620
|
+
self.x2c = (np.sin(x2_2D) * x1_2D).T
|
|
621
|
+
self.x1rc = (np.cos(x2r_2D) * x1r_2D).T
|
|
622
|
+
self.x2rc = (np.sin(x2r_2D) * x1r_2D).T
|
|
623
|
+
|
|
624
|
+
self.gridlist3 = ["x1c", "x2c", "x1rc", "x2rc"]
|
|
625
|
+
del x1_2D, x2_2D, x1r_2D, x2r_2D
|
|
626
|
+
elif self.geom == "SPHERICAL":
|
|
627
|
+
x1_2D, x2_2D = np.meshgrid(self.x1, self.x2, indexing="ij")
|
|
628
|
+
x1r_2D, x2r_2D = np.meshgrid(self.x1r, self.x2r, indexing="ij")
|
|
629
|
+
|
|
630
|
+
self.x1p = (np.sin(x2_2D) * x1_2D).T
|
|
631
|
+
self.x2p = (np.cos(x2_2D) * x1_2D).T
|
|
632
|
+
self.x1rp = (np.sin(x2r_2D) * x1r_2D).T
|
|
633
|
+
self.x2rp = (np.cos(x2r_2D) * x1r_2D).T
|
|
634
|
+
|
|
635
|
+
x1_2D, x3_2D = np.meshgrid(self.x1, self.x3, indexing="ij")
|
|
636
|
+
x1r_2D, x3r_2D = np.meshgrid(self.x1r, self.x3r, indexing="ij")
|
|
637
|
+
|
|
638
|
+
self.x1t = (np.cos(x3_2D) * x1_2D).T
|
|
639
|
+
self.x3t = (np.sin(x3_2D) * x1_2D).T
|
|
640
|
+
self.x1rt = (np.cos(x3r_2D) * x1r_2D).T
|
|
641
|
+
self.x3rt = (np.sin(x3r_2D) * x1r_2D).T
|
|
642
|
+
|
|
643
|
+
self.gridlist3 = [
|
|
644
|
+
"x1p",
|
|
645
|
+
"x2p",
|
|
646
|
+
"x1rp",
|
|
647
|
+
"x2rp",
|
|
648
|
+
"x1t",
|
|
649
|
+
"x3t",
|
|
650
|
+
"x1rt",
|
|
651
|
+
"x3rt",
|
|
652
|
+
]
|
|
653
|
+
|
|
654
|
+
del x1_2D, x2_2D, x1r_2D, x2r_2D, x3_2D, x3r_2D
|
|
655
|
+
|
|
656
|
+
if self.dim == 3 and self._full3d is True:
|
|
657
|
+
x1_3D, x2_3D, x3_3D = np.meshgrid(
|
|
658
|
+
self.x1, self.x2, self.x3, indexing="ij"
|
|
659
|
+
)
|
|
660
|
+
x1r_3D, x2r_3D, x3r_3D = np.meshgrid(
|
|
661
|
+
self.x1r, self.x2r, self.x3r, indexing="ij"
|
|
662
|
+
)
|
|
663
|
+
|
|
664
|
+
self.x1c = (np.sin(x2_3D) * np.cos(x3_3D) * x1_3D).T
|
|
665
|
+
self.x2c = (np.sin(x2_3D) * np.sin(x3_3D) * x1_3D).T
|
|
666
|
+
self.x3c = (np.cos(x2_3D) * x1_3D).T
|
|
667
|
+
self.x1rc = (np.sin(x2r_3D) * np.cos(x3r_3D) * x1r_3D).T
|
|
668
|
+
self.x2rc = (np.sin(x2r_3D) * np.sin(x3r_3D) * x1r_3D).T
|
|
669
|
+
self.x3rc = (np.cos(x2r_3D) * x1r_3D).T
|
|
670
|
+
|
|
671
|
+
self.gridlist3.extend(["x1c", "x2c", "x3c", "x1rc", "x2rc", "x3rc"])
|
|
672
|
+
|
|
673
|
+
del x1_3D, x2_3D, x3_3D, x1r_3D, x2r_3D, x3r_3D
|
|
674
|
+
else:
|
|
675
|
+
pass
|
|
676
|
+
# self.x1c = np.zeros((self.nx1,self.nx2,self.nx3))
|
|
677
|
+
# print(np.shape(self.x1c))
|
|
678
|
+
# self.pippo = np.meshgrid(self.x2, self.x3, indexing='xy')
|
|
679
|
+
# print(np.shape(self.pippo))
|
|
680
|
+
|
|
681
|
+
# Compute the gridsize both centered and staggered
|
|
682
|
+
self.gridsize = self.nx1 * self.nx2 * self.nx3
|
|
683
|
+
self.gridsize_st1 = nx1s * self.nx2 * self.nx3
|
|
684
|
+
self.gridsize_st2 = self.nx1 * nx2s * self.nx3
|
|
685
|
+
self.gridsize_st3 = self.nx1 * self.nx2 * nx3s
|
|
686
|
+
|
|
687
|
+
self.info = False
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
def _split_gridfile(
|
|
691
|
+
self, i: str, xL: list[float], xR: list[float], nmax: list[int]
|
|
692
|
+
) -> None:
|
|
693
|
+
"""Splits the gridfile, storing the information in the variables
|
|
694
|
+
passed by the function. Dimensions and geometry are stored in the
|
|
695
|
+
class.
|
|
696
|
+
|
|
697
|
+
Return
|
|
698
|
+
------
|
|
699
|
+
|
|
700
|
+
- None
|
|
701
|
+
|
|
702
|
+
Parameters
|
|
703
|
+
----------
|
|
704
|
+
- i (not optional): str
|
|
705
|
+
The line of the gridfile.
|
|
706
|
+
- nmax (not optional): list[int]
|
|
707
|
+
The number of the cells in the grid.
|
|
708
|
+
- xL (not optional): list[float]
|
|
709
|
+
The list of the left cell boundaries values.
|
|
710
|
+
- xR (not optional): list[float]
|
|
711
|
+
The list of the right cell boundaries values.
|
|
712
|
+
|
|
713
|
+
----
|
|
714
|
+
|
|
715
|
+
Examples
|
|
716
|
+
--------
|
|
717
|
+
- Example #1: Split the gridfile
|
|
718
|
+
|
|
719
|
+
>>> _split_gridfile(i, xL, xR, nmax)
|
|
720
|
+
|
|
721
|
+
"""
|
|
722
|
+
# If the splitted line has only one string, try to convert it
|
|
723
|
+
# to an integer (number of cells in a dimension).
|
|
724
|
+
if len(i.split()) == 1:
|
|
725
|
+
try:
|
|
726
|
+
nmax.append(int(i.split(maxsplit=1)[0]))
|
|
727
|
+
except ValueError:
|
|
728
|
+
pass
|
|
729
|
+
|
|
730
|
+
# Check if the splitted line has three strings
|
|
731
|
+
if len(i.split()) == 3:
|
|
732
|
+
# Try to convert the first string to an int (cell number in a dimension)
|
|
733
|
+
# and the other two to floats (left and right cell boundaries)
|
|
734
|
+
try:
|
|
735
|
+
int(i.split(maxsplit=1)[0])
|
|
736
|
+
xL.append(float(i.split()[1]))
|
|
737
|
+
xR.append(float(i.split()[2]))
|
|
738
|
+
|
|
739
|
+
# Check if the keyword is geometry or dimensions and
|
|
740
|
+
# store the information in the class
|
|
741
|
+
except ValueError:
|
|
742
|
+
if i.split()[1] == "GEOMETRY:":
|
|
743
|
+
self.geom = i.split()[2]
|
|
744
|
+
if i.split()[1] == "DIMENSIONS:":
|
|
745
|
+
self.dim = int(i.split()[2])
|