Skip to content

Commit 6b45d10

Browse files
committed
3d
1 parent 4fb69ed commit 6b45d10

File tree

96 files changed

+3828
-807
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+3828
-807
lines changed

.github/workflows/cmake_macos.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ jobs:
7878
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
7979
-DENABLE_SAMRAI_TESTS=OFF -DCMAKE_C_COMPILER_LAUNCHER=ccache \
8080
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DlowResourceTests=ON \
81-
-DCMAKE_CXX_FLAGS="-DPHARE_DIAG_DOUBLES=1 "
81+
-DCMAKE_CXX_FLAGS="-DPHARE_DIAG_DOUBLES=1 -DPHARE_SIMULATORS=2 "
8282
8383
- name: Build
8484
working-directory: ${{github.workspace}}/build

pyphare/pyphare/core/box.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ def __eq__(self, other):
6262
)
6363

6464
def __sub__(self, other):
65+
if isinstance(other, (list, tuple)):
66+
assert all([isinstance(item, Box) for item in other])
67+
return remove_all(self, other)
6568
assert isinstance(other, Box)
6669
return remove(self, other)
6770

@@ -179,5 +182,42 @@ def copy(arr, replace):
179182
return list(boxes.values())
180183

181184

185+
def remove_all(box, to_remove):
186+
if len(to_remove) > 0:
187+
remaining = box - to_remove[0]
188+
for to_rm in to_remove[1:]:
189+
tmp, remove = [], []
190+
for i, rem in enumerate(remaining):
191+
if rem * to_rm is not None:
192+
remove.append(i)
193+
tmp += rem - to_rm
194+
for rm in reversed(remove):
195+
del remaining[rm]
196+
remaining += tmp
197+
return remaining
198+
return box
199+
200+
201+
182202
def amr_to_local(box, ref_box):
183203
return Box(box.lower - ref_box.lower, box.upper - ref_box.lower)
204+
205+
206+
def select(data, box):
207+
return data[tuple([slice(l, u + 1) for l,u in zip(box.lower, box.upper)])]
208+
209+
class DataSelector:
210+
"""
211+
can't assign return to function unless []
212+
usage
213+
DataSelector(data)[box] = val
214+
"""
215+
def __init__(self, data):
216+
self.data = data
217+
def __getitem__(self, box_or_slice):
218+
if isinstance(box_or_slice, Box):
219+
return select(self.data, box_or_slice)
220+
return self.data[box_or_slice]
221+
222+
def __setitem__(self, box_or_slice, val):
223+
self.__getitem__(box_or_slice)[:] = val

pyphare/pyphare/core/gridlayout.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,24 @@ def yeeCoords(self, knode, iStart, centering, direction, ds, origin, derivOrder)
359359

360360
return x
361361

362+
def meshCoords(self, qty):
363+
ndim = self.ndim
364+
assert ndim > 0 and ndim < 4
365+
x = self.yeeCoordsFor(qty, "x")
366+
if ndim == 1:
367+
return x
368+
y = self.yeeCoordsFor(qty, "y")
369+
if ndim == 2:
370+
X, Y = np.meshgrid(x, y, indexing="ij")
371+
return np.array([X.flatten(), Y.flatten()]).T.reshape(
372+
(len(x), len(y), ndim)
373+
)
374+
z = self.yeeCoordsFor(qty, "z")
375+
X, Y, Z = np.meshgrid(x, y, z, indexing="ij")
376+
return np.array([X.flatten(), Y.flatten(), Z.flatten()]).T.reshape(
377+
(len(x), len(y), len(z), ndim)
378+
)
379+
362380
def yeeCoordsFor(self, qty, direction, withGhosts=True, **kwargs):
363381
"""
364382
from a qty and a direction, returns a 1d array containing

pyphare/pyphare/cpp/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44

55

6-
def cpp_lib(override=None):
6+
def cpp_lib():
77
import importlib
88

99
return importlib.import_module("pybindlibs.cpp")

pyphare/pyphare/pharein/__init__.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,6 @@ def NO_GUI():
6464
mpl.use("Agg")
6565

6666

67-
def getSimulation():
68-
from .global_vars import sim
69-
70-
return sim
71-
72-
7367
def _patch_data_ids(restart_file_dir):
7468
"""
7569
for restarts we save samrai patch data ids to the restart files, which we access from here
@@ -125,10 +119,15 @@ def clearDict():
125119
pp.stop()
126120

127121

128-
def populateDict():
129-
from .global_vars import sim as simulation
122+
def populateDict(simulation=None):
123+
# from .global_vars import sim as simulation
130124
import pybindlibs.dictator as pp
131125

126+
if simulation is None:
127+
from .global_vars import sim
128+
129+
simulation = sim
130+
132131
# pybind complains if receiving wrong type
133132
def add_int(path, val):
134133
pp.add_int(path, int(val))

pyphare/pyphare/pharein/maxwellian_fluid_model.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ def validate(self, sim, atol=1e-15):
193193
self.validate1d(sim, atol)
194194
elif sim.ndim == 2:
195195
self.validate2d(sim, atol)
196+
elif sim.ndim == 3:
197+
self.validate3d(sim, atol)
198+
else:
199+
raise ValueError("Unknown dimension")
196200

197201
def validate1d(self, sim, atol):
198202
domain_box = Box([0] * sim.ndim, sim.cells)
@@ -301,3 +305,79 @@ def getCoord(L, R, idir):
301305
)
302306
if sim.strict:
303307
raise RuntimeError("Simulation is not periodic")
308+
309+
def validate3d(self, sim, atol):
310+
domain_box = Box([0] * sim.ndim, sim.cells)
311+
layout = GridLayout(domain_box, domain_box.lower, sim.dl, sim.interp_order)
312+
nbrDualGhosts = layout.nbrGhostsPrimal(sim.interp_order)
313+
nbrPrimalGhosts = layout.nbrGhostsPrimal(sim.interp_order)
314+
directions = ["X", "Y", "Z"]
315+
domain = sim.simulation_domain()
316+
bx = self.model_dict["bx"]
317+
by = self.model_dict["by"]
318+
bz = self.model_dict["bz"]
319+
is_periodic = True
320+
not_periodic = []
321+
322+
def getCoord(L, R, idir):
323+
if idir == 0:
324+
return (L, np.zeros_like(L), np.zeros_like(L)), (
325+
R,
326+
np.zeros_like(R),
327+
np.zeros_like(R),
328+
)
329+
else:
330+
return (np.zeros_like(L), np.zeros_like(L), L), (
331+
np.zeros_like(R),
332+
np.zeros_like(R),
333+
R,
334+
)
335+
336+
phare_utilities.debug_print("3d periodic validation")
337+
for idir in np.arange(sim.ndim):
338+
phare_utilities.debug_print("validating direction ...", idir)
339+
if sim.boundary_types[idir] == "periodic":
340+
phare_utilities.debug_print(f"direction {idir} is periodic?")
341+
dual_left = (np.arange(-nbrDualGhosts, nbrDualGhosts) + 0.5) * sim.dl[0]
342+
dual_right = dual_left + domain[0]
343+
primal_left = np.arange(-nbrPrimalGhosts, nbrPrimalGhosts) * sim.dl[0]
344+
primal_right = primal_left + domain[0]
345+
346+
direction = directions[idir]
347+
348+
for b_i, b_name in zip((bx, by, bz), ("Bx", "By", "Bz")):
349+
if layout.qtyIsDual(b_name, direction):
350+
L, R = dual_left, dual_right
351+
else:
352+
L, R = primal_left, primal_right
353+
354+
coordsL, coordsR = getCoord(L, R, idir)
355+
check = np.allclose(b_i(*coordsL), b_i(*coordsR), atol=atol, rtol=0)
356+
if not check:
357+
not_periodic += [(b_name, idir)]
358+
is_periodic &= check
359+
360+
for pop in self.populations:
361+
functions = ("vx", "vy", "vz", "vthx", "vthy", "vthz")
362+
L, R = primal_left, primal_right
363+
coordsL, coordsR = getCoord(L, R, idir)
364+
365+
for fn in functions:
366+
f = self.model_dict[pop][fn]
367+
fL = f(*coordsL)
368+
fR = f(*coordsR)
369+
check = np.allclose(fL, fR, atol=atol, rtol=0)
370+
phare_utilities.debug_print(
371+
f"checked {fn} : fL = {fL} and fR = {fR} and check = {check}"
372+
)
373+
if not check:
374+
not_periodic += [(fn, idir)]
375+
is_periodic &= check
376+
377+
if not is_periodic:
378+
print(
379+
"Warning: Simulation is periodic but some functions are not : ",
380+
not_periodic,
381+
)
382+
if sim.strict:
383+
raise RuntimeError("Simulation is not periodic")

0 commit comments

Comments
 (0)