Skip to content

Commit 4de43d2

Browse files
committed
3d
1 parent 5db724c commit 4de43d2

File tree

91 files changed

+4272
-614
lines changed

Some content is hidden

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

91 files changed

+4272
-614
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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,20 @@ 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((len(x), len(y), ndim))
372+
z = self.yeeCoordsFor(qty, "z")
373+
X ,Y, Z = np.meshgrid(x,y,z,indexing="ij")
374+
return np.array([X.flatten(), Y.flatten(), Z.flatten()]).T.reshape((len(x), len(y), len(z), ndim))
375+
362376
def yeeCoordsFor(self, qty, direction, withGhosts=True, **kwargs):
363377
"""
364378
from a qty and a direction, returns a 1d array containing

pyphare/pyphare/pharesee/geometry.py

Lines changed: 82 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,24 @@ def domain_border_ghost_boxes(domain_box, patches):
5454
elif domain_box.ndim == 2:
5555
upper_x, upper_y = domain_box.upper
5656
return {
57-
"bottom": Box(
58-
(
59-
0,
60-
0,
61-
),
62-
(upper_x, ghost_box_width),
63-
),
64-
"top": Box((0, upper_y - ghost_box_width), (upper_x, upper_y)),
6557
"left": Box((0, 0), (ghost_box_width, upper_y)),
6658
"right": Box((upper_x - ghost_box_width, 0), (upper_x, upper_y)),
59+
"bottom": Box((0, 0), (upper_x, ghost_box_width)),
60+
"top": Box((0, upper_y - ghost_box_width), (upper_x, upper_y)),
6761
}
6862

69-
raise ValueError("Unhandeled dimension")
63+
else:
64+
upper_x, upper_y, upper_z = domain_box.upper
65+
return {
66+
"left": Box((0, 0, 0), (ghost_box_width, upper_y, upper_z)),
67+
"right": Box(
68+
(upper_x - ghost_box_width, 0, 0), (upper_x, upper_y, upper_z)
69+
),
70+
"bottom": Box((0, 0, 0), (upper_x, ghost_box_width, upper_z)),
71+
"top": Box((0, upper_y - ghost_box_width, 0), (upper_x, upper_y, upper_z)),
72+
"front": Box((0, 0, 0), (upper_x, upper_y, ghost_box_width)),
73+
"back": Box((0, 0, upper_z - ghost_box_width), (upper_x, upper_y, upper_z)),
74+
}
7075

7176

7277
def touch_domain_border(box, domain_box, border):
@@ -79,21 +84,29 @@ def touch_domain_border(box, domain_box, border):
7984

8085

8186
def periodicity_shifts(domain_box):
87+
shifts = {}
88+
8289
if domain_box.ndim == 1:
8390
shape_x = domain_box.shape
84-
return {
91+
shifts = {
8592
"left": shape_x,
8693
"right": -shape_x,
8794
}
95+
shifts.update({"leftright": [shifts["left"], shifts["right"]]})
8896

8997
if domain_box.ndim == 2:
9098
shape_x, shape_y = domain_box.shape
99+
if domain_box.ndim == 3:
100+
shape_x, shape_y, shape_z = domain_box.shape
101+
102+
if domain_box.ndim > 1:
91103
shifts = {
92104
"left": [(shape_x, 0)],
93105
"right": [(-shape_x, 0)],
94106
"bottom": [(0, shape_y)],
95107
"top": [(0, -shape_y)],
96108
}
109+
97110
shifts.update(
98111
{
99112
"bottomleft": [*shifts["left"], *shifts["bottom"], (shape_x, shape_y)],
@@ -134,7 +147,7 @@ def periodicity_shifts(domain_box):
134147
shifts["topleft"][-1],
135148
shifts["topright"][-1],
136149
],
137-
"bottomtopleftright": [ # one patch covers domain
150+
"leftrightbottomtop": [ # one patch covers domain
138151
*shifts["bottomleft"],
139152
*shifts["topright"],
140153
shifts["bottomright"][-1],
@@ -144,7 +157,35 @@ def periodicity_shifts(domain_box):
144157
)
145158

146159
if domain_box.ndim == 3:
147-
raise ValueError("Unhandeled dimension")
160+
front = {
161+
f"{k}front": [(v[0], v[1], shape_z) for v in l] for k, l in shifts.items()
162+
}
163+
back = {
164+
f"{k}back": [([v[0], v[1], -shape_z]) for v in l] for k, l in shifts.items()
165+
}
166+
167+
shifts = {k: [([v[0], v[1], 0]) for v in l] for k, l in shifts.items()}
168+
169+
shifts.update(front)
170+
shifts.update(back)
171+
shifts.update(
172+
{
173+
"back": [(0, 0, -shape_z)],
174+
"front": [(0, 0, shape_z)],
175+
"leftrightbottomtopfrontback": [
176+
*shifts["bottomleftfront"],
177+
*shifts["bottomrightback"],
178+
*shifts["topleftfront"],
179+
*shifts["toprightback"],
180+
],
181+
}
182+
)
183+
184+
assert len(list(shifts.keys())) == len(
185+
set(["".join(sorted(k)) for k in list(shifts.keys())])
186+
)
187+
188+
shifts = {"".join(sorted(k)): l for k, l in shifts.items()}
148189

149190
return shifts
150191

@@ -246,7 +287,7 @@ def borders_per(patch):
246287
]
247288

248289
for patch_i, ref_patch in enumerate(border_patches):
249-
in_sides = borders_per_patch[ref_patch]
290+
in_sides = "".join(sorted(borders_per_patch[ref_patch]))
250291
assert in_sides in shifts
251292

252293
for ref_pdname, ref_pd in ref_patch.patch_datas.items():
@@ -336,36 +377,41 @@ def get_periodic_list(patches, domain_box, n_ghosts):
336377
shift_patch(first_patch, domain_box.shape)
337378
sorted_patches.append(first_patch)
338379

380+
return sorted_patches
381+
382+
dbu = domain_box.upper
383+
339384
if dim == 2:
340385
sides = {
341-
"bottom": Box([0, 0], [domain_box.upper[0], 0]),
342-
"top": Box(
343-
[0, domain_box.upper[1]], [domain_box.upper[0], domain_box.upper[1]]
344-
),
345-
"left": Box([0, 0], [0, domain_box.upper[1]]),
346-
"right": Box(
347-
[domain_box.upper[0], 0], [domain_box.upper[0], domain_box.upper[1]]
348-
),
386+
"left": Box([0, 0], [0, dbu[1]]),
387+
"right": Box([dbu[0], 0], [dbu[0], dbu[1]]),
388+
"bottom": Box([0, 0], [dbu[0], 0]),
389+
"top": Box([0, dbu[1]], [dbu[0], dbu[1]]),
349390
}
350391

351-
shifts = periodicity_shifts(domain_box)
392+
else:
393+
sides = {
394+
"left": Box([0, 0, 0], [0, dbu[1], dbu[2]]),
395+
"right": Box([dbu[0], 0, 0], [dbu[0], dbu[1], dbu[2]]),
396+
"bottom": Box([0, 0, 0], [dbu[0], 0, dbu[2]]),
397+
"top": Box([0, dbu[1], 0], [dbu[0], dbu[1], dbu[2]]),
398+
"front": Box([0, 0, 0], [dbu[0], dbu[1], 0]),
399+
"back": Box([0, 0, dbu[2]], [dbu[0], dbu[1], dbu[2]]),
400+
}
352401

353-
def borders_per(box):
354-
return "".join(
355-
[key for key, side in sides.items() if box * side is not None]
356-
)
402+
shifts = periodicity_shifts(domain_box)
357403

358-
for patch in patches:
359-
in_sides = borders_per(boxm.grow(patch.box, n_ghosts))
404+
def borders_per(box):
405+
return "".join([key for key, side in sides.items() if box * side is not None])
360406

361-
if in_sides in shifts: # in_sides might be empty, so no borders
362-
for shift in shifts[in_sides]:
363-
patch_copy = copy(patch)
364-
shift_patch(patch_copy, shift)
365-
sorted_patches.append(patch_copy)
407+
for patch in patches:
408+
in_sides = "".join(sorted(borders_per(boxm.grow(patch.box, n_ghosts))))
366409

367-
if dim == 3:
368-
raise ValueError("not yet implemented")
410+
if in_sides in shifts: # in_sides might be empty, so no borders
411+
for shift in shifts[in_sides]:
412+
patch_copy = copy(patch)
413+
shift_patch(patch_copy, shift)
414+
sorted_patches.append(patch_copy)
369415

370416
return sorted_patches
371417

@@ -470,18 +516,7 @@ def level_ghost_boxes(hierarchy, quantities, levelNbrs=[], time=None):
470516
check_patches = patches
471517

472518
for gabox in ghostAreaBoxes:
473-
remaining = gabox - check_patches[0].box
474-
475-
for patch in check_patches[1:]:
476-
tmp = []
477-
remove = []
478-
for i, rem in enumerate(remaining):
479-
if rem * patch.box is not None:
480-
remove.append(i)
481-
tmp += rem - patch.box
482-
for rm in reversed(remove):
483-
del remaining[rm]
484-
remaining += tmp
519+
remaining = gabox - [p.box for p in check_patches]
485520

486521
if ilvl not in lvl_gaboxes:
487522
lvl_gaboxes[ilvl] = {}

pyphare/pyphare/pharesee/hierarchy/hierarchy.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,11 +556,44 @@ def plot2d(self, **kwargs):
556556

557557
return fig, ax
558558

559+
def plot3d(self, **kwargs):
560+
"""!HAX!"""
561+
time = kwargs.get("time", self._default_time())
562+
usr_lvls = kwargs.get("levels", self.levelNbrs(time))
563+
default_qty = None
564+
if len(self.quantities()) == 1:
565+
default_qty = self.quantities()[0]
566+
qty = kwargs.get("qty", default_qty)
567+
for lvl_nbr, lvl in self.levels(time).items():
568+
if lvl_nbr not in usr_lvls:
569+
continue
570+
for patch in self.level(lvl_nbr, time).patches:
571+
pdat = patch.patch_datas[qty]
572+
primals = pdat.primal_directions()
573+
if primals[0]:
574+
pdat._x = pdat.x[:-1]
575+
if primals[1]:
576+
pdat._y = pdat.y[:-1]
577+
pdat.dataset = pdat.dataset[:, :, int(pdat.ghost_box.shape[2] / 2)]
578+
patch.box.lower = patch.box.lower[:-1]
579+
patch.box.upper = patch.box.upper[:-1]
580+
patch.box.ndim = 2
581+
582+
pdat.ghost_box.lower = pdat.ghost_box.lower[:-1]
583+
pdat.ghost_box.upper = pdat.ghost_box.upper[:-1]
584+
pdat.ghost_box.ndim = 2
585+
pdat.size = np.copy(pdat.ghost_box.shape)
586+
pdat.layout.dl = pdat.layout.dl[:-1]
587+
588+
return self.plot2d(**kwargs) # ¯\_(ツ)_/¯
589+
559590
def plot(self, **kwargs):
560591
if self.ndim == 1:
561592
return self.plot1d(**kwargs)
562593
elif self.ndim == 2:
563594
return self.plot2d(**kwargs)
595+
elif self.ndim == 3:
596+
return self.plot3d(**kwargs)
564597

565598
def dist_plot(self, **kwargs):
566599
"""

pyphare/pyphare/pharesee/run/utils.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,11 @@ def _pdd_to_ppp_domain_slicing(**kwargs):
150150
ndim = kwargs["ndim"]
151151

152152
inner, inner_shift_left, inner_shift_right = _inner_slices(nb_ghosts)
153+
inner_all = tuple([inner] * ndim)
153154

154155
if ndim == 1:
155-
inner_all = tuple([inner] * ndim)
156156
return inner_all, (inner_all,)
157157
elif ndim == 2:
158-
inner_all = tuple([inner] * ndim)
159158
return inner_all, ((inner, inner_shift_left), (inner, inner_shift_right))
160159
else:
161160
raise RuntimeError("dimension not yet implemented")
@@ -359,16 +358,16 @@ def _get_rank(patchdatas, patch_id, **kwargs):
359358
layout = reference_pd.layout
360359
centering = "dual"
361360
nbrGhosts = layout.nbrGhosts(layout.interp_order, centering)
362-
shape = grow(reference_pd.box, [nbrGhosts] * 2).shape
361+
shape = grow(reference_pd.box, [nbrGhosts] * ndim).shape
363362

364363
if ndim == 1:
365-
pass
364+
raise RuntimeError("Not used in 1D")
366365

367366
elif ndim == 2:
368367
data = np.zeros(shape) + int(patch_id.strip("p").split("#")[0])
369-
return ({"name": "rank", "data": data, "centering": [centering] * 2},)
368+
return ({"name": "rank", "data": data, "centering": [centering] * ndim},)
370369
else:
371-
raise RuntimeError("Not Implemented yet")
370+
raise RuntimeError("Not Implemented - not sure it is useful")
372371

373372

374373
def _compute_pressure(patch_datas, **kwargs):

0 commit comments

Comments
 (0)