Skip to content

Commit f6d7201

Browse files
authored
Implement iMultiFab (#410)
Generalize the `MultiFab` logic and reuse as much as possible for the `iMultiFab` bindings.
1 parent ed9ed53 commit f6d7201

10 files changed

+1624
-892
lines changed

src/Base/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@ foreach(D IN LISTS AMReX_SPACEDIM)
2020
CoordSys.cpp
2121
Dim3.cpp
2222
DistributionMapping.cpp
23+
FabArray.cpp
2324
FArrayBox.cpp
2425
Geometry.cpp
26+
iMultiFab.cpp
2527
IndexType.cpp
2628
IntVect.cpp
2729
RealVect.cpp
2830
SmallMatrix.cpp
31+
MFInfo.cpp
2932
MultiFab.cpp
3033
ParallelDescriptor.cpp
3134
ParmParse.cpp

src/Base/FabArray.cpp

+301
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
/* Copyright 2021-2022 The AMReX Community
2+
*
3+
* Authors: Axel Huebl
4+
* License: BSD-3-Clause-LBNL
5+
*/
6+
#include "pyAMReX.H"
7+
8+
#include <AMReX_BoxArray.H>
9+
#include <AMReX_DistributionMapping.H>
10+
#include <AMReX_FabArray.H>
11+
#include <AMReX_FArrayBox.H>
12+
#include <AMReX_IArrayBox.H>
13+
#include <AMReX_iMultiFab.H>
14+
15+
#include <memory>
16+
#include <string>
17+
18+
19+
namespace
20+
{
21+
template<typename T>
22+
void make_FabArray_T(py::module &m, std::string const &name)
23+
{
24+
using namespace amrex;
25+
26+
using FAT = FabArray<T>;
27+
using value_type = typename FAT::value_type;
28+
std::string const full_name = "FabArray_" + name;
29+
py::class_<FAT, FabArrayBase > py_FAT(m, full_name.c_str());
30+
py_FAT
31+
// define
32+
.def("clear", &FAT::clear)
33+
.def("ok", &FAT::ok)
34+
35+
.def_property_readonly("arena", &FAT::arena,
36+
"Provides access to the Arena this FabArray was build with.")
37+
.def_property_readonly("has_EB_fab_factory", &FAT::hasEBFabFactory)
38+
.def_property_readonly("factory", &FAT::Factory)
39+
40+
//.def("array", py::overload_cast< const MFIter& >(&FAT::array))
41+
//.def("const_array", &FAT::const_array)
42+
.def("array", [](FAT & fa, MFIter const & mfi)
43+
{ return fa.array(mfi); },
44+
// as long as the return value (argument 0) exists, keep the fa (argument 1) alive
45+
py::keep_alive<0, 1>()
46+
)
47+
.def("const_array", [](FAT & fa, MFIter const & mfi)
48+
{ return fa.const_array(mfi); },
49+
// as long as the return value (argument 0) exists, keep the fa (argument 1) alive
50+
py::keep_alive<0, 1>()
51+
)
52+
53+
/* setters */
54+
.def("set_val",
55+
py::overload_cast< value_type >(&FAT::template setVal<T>),
56+
py::arg("val"),
57+
"Set all components in the entire region of each FAB to val."
58+
)
59+
.def("set_val",
60+
py::overload_cast< value_type, int, int, int >(&FAT::template setVal<T>),
61+
py::arg("val"), py::arg("comp"), py::arg("num_comp"), py::arg("nghost")=0,
62+
"Set the value of num_comp components in the valid region of\n"
63+
"each FAB in the FabArray, starting at component comp to val.\n"
64+
"Also set the value of nghost boundary cells."
65+
)
66+
.def("set_val",
67+
py::overload_cast< value_type, int, int, IntVect const & >(&FAT::template setVal<T>),
68+
py::arg("val"), py::arg("comp"), py::arg("num_comp"), py::arg("nghost"),
69+
"Set the value of num_comp components in the valid region of\n"
70+
"each FAB in the FabArray, starting at component comp to val.\n"
71+
"Also set the value of nghost boundary cells."
72+
)
73+
.def("set_val",
74+
py::overload_cast< value_type, Box const &, int, int, int >(&FAT::template setVal<T>),
75+
py::arg("val"), py::arg("region"), py::arg("comp"), py::arg("num_comp"), py::arg("nghost")=0,
76+
"Set the value of num_comp components in the valid region of\n"
77+
"each FAB in the FabArray, starting at component comp, as well\n"
78+
"as nghost boundary cells, to val, provided they also intersect\n"
79+
"with the Box region."
80+
)
81+
.def("set_val",
82+
py::overload_cast< value_type, Box const &, int, int, IntVect const & >(&FAT::template setVal<T>),
83+
py::arg("val"), py::arg("region"), py::arg("comp"), py::arg("num_comp"), py::arg("nghost"),
84+
"Set the value of num_comp components in the valid region of\n"
85+
"each FAB in the FabArray, starting at component comp, as well\n"
86+
"as nghost boundary cells, to val, provided they also intersect\n"
87+
"with the Box region."
88+
)
89+
90+
.def("abs", py::overload_cast< int, int, int >(&FAT::template abs<T>),
91+
py::arg("comp"), py::arg("ncomp"), py::arg("nghost")=0
92+
)
93+
.def("abs", py::overload_cast< int, int, IntVect const & >(&FAT::template abs<T>),
94+
py::arg("comp"), py::arg("ncomp"), py::arg("nghost")
95+
)
96+
97+
.def("saxpy",
98+
[](FAT & dst, value_type a, FAT const & x, int x_comp, int comp, int ncomp, IntVect const & nghost)
99+
{
100+
FAT::Saxpy(dst, a, x, x_comp, comp, ncomp, nghost);
101+
},
102+
py::arg("a"), py::arg("x"), py::arg("x_comp"), py::arg("comp"), py::arg("ncomp"), py::arg("nghost"),
103+
"self += a * x\n\n"
104+
"Parameters\n"
105+
"----------\n"
106+
"a : scalar a\n"
107+
"x : FabArray x\n"
108+
"x_comp : starting component of x\n"
109+
"comp : starting component of self\n"
110+
"ncomp : number of components\n"
111+
"nghost : number of ghost cells"
112+
)
113+
.def("xpay",
114+
[](FAT & self, value_type a, FAT const & x, int x_comp, int comp, int ncomp, IntVect const & nghost)
115+
{
116+
FAT::Xpay(self, a, x, x_comp, comp, ncomp, nghost);
117+
},
118+
py::arg("a"), py::arg("x"), py::arg("xcomp"), py::arg("comp"), py::arg("ncomp"), py::arg("nghost"),
119+
"self = x + a * self\n\n"
120+
"Parameters\n"
121+
"----------\n"
122+
"a : scalar a\n"
123+
"x : FabArray x\n"
124+
"x_comp : starting component of x\n"
125+
"comp : starting component of self\n"
126+
"ncomp : number of components\n"
127+
"nghost : number of ghost cells"
128+
)
129+
.def("lin_comb",
130+
[](
131+
FAT & dst,
132+
value_type a, FAT const & x, int x_comp,
133+
value_type b, FAT const & y, int y_comp,
134+
int comp, int ncomp, IntVect const & nghost)
135+
{
136+
FAT::LinComb(dst, a, x, x_comp, b, y, y_comp, comp, ncomp, nghost);
137+
},
138+
py::arg("a"), py::arg("x"), py::arg("xcomp"),
139+
py::arg("b"), py::arg("y"), py::arg("ycomp"),
140+
py::arg("comp"), py::arg("numcomp"), py::arg("nghost"),
141+
"self = a * x + b * y\n\n"
142+
"Parameters\n"
143+
"----------\n"
144+
"a : float\n"
145+
" scalar a\n"
146+
"x : FabArray\n"
147+
"xcomp : int\n"
148+
" starting component of x\n"
149+
"b : float\n"
150+
" scalar b\n"
151+
"y : FabArray\n"
152+
"ycomp : int\n"
153+
" starting component of y\n"
154+
"comp : int\n"
155+
" starting component of self\n"
156+
"numcomp : int\n"
157+
" number of components\n"
158+
"nghost : int\n"
159+
" number of ghost cells"
160+
)
161+
162+
.def("sum",
163+
py::overload_cast< int, IntVect const&, bool >(&FAT::template sum<T>, py::const_),
164+
py::arg("comp"), py::arg("nghost"), py::arg("local"),
165+
"Returns the sum of component \"comp\""
166+
)
167+
.def("sum_boundary",
168+
py::overload_cast< Periodicity const & >(&FAT::SumBoundary),
169+
py::arg("period"),
170+
"Sum values in overlapped cells. The destination is limited to valid cells."
171+
)
172+
.def("sum_boundary", py::overload_cast< int, int, Periodicity const & >(&FAT::SumBoundary),
173+
py::arg("scomp"), py::arg("ncomp"), py::arg("period"),
174+
"Sum values in overlapped cells. The destination is limited to valid cells."
175+
)
176+
.def("sum_boundary", py::overload_cast< int, int, IntVect const&, Periodicity const & >(&FAT::SumBoundary),
177+
py::arg("scomp"), py::arg("ncomp"), py::arg("nghost"), py::arg("period"),
178+
"Sum values in overlapped cells. The destination is limited to valid cells."
179+
)
180+
.def("sum_boundary", py::overload_cast< int, int, IntVect const&, IntVect const&, Periodicity const & >(&FAT::SumBoundary),
181+
py::arg("scomp"), py::arg("ncomp"), py::arg("nghost"), py::arg("dst_nghost"), py::arg("period"),
182+
"Sum values in overlapped cells. The destination is limited to valid cells."
183+
)
184+
;
185+
186+
constexpr auto doc_fabarray_osync = R"(Synchronize nodal data.
187+
188+
The synchronization will override valid regions by the intersecting valid regions with a higher precedence.
189+
The smaller the global box index is, the higher precedence the box has.
190+
With periodic boundaries, for cells in the same box, those near the lower corner have higher precedence than those near the upper corner.
191+
192+
Parameters
193+
----------
194+
scomp :
195+
starting component
196+
ncomp :
197+
number of components
198+
period :
199+
periodic length if it's non-zero)";
200+
201+
py_FAT
202+
.def("override_sync",
203+
py::overload_cast< Periodicity const & >(&FAT::OverrideSync),
204+
py::arg("period"),
205+
doc_fabarray_osync
206+
)
207+
.def("override_sync",
208+
py::overload_cast< int, int, Periodicity const & >(&FAT::OverrideSync),
209+
py::arg("scomp"), py::arg("ncomp"), py::arg("period"),
210+
doc_fabarray_osync
211+
)
212+
;
213+
214+
constexpr auto doc_fabarray_fillb = R"(Copy on intersection within a FabArray.
215+
216+
Data is copied from valid regions to intersecting regions of definition.
217+
The purpose is to fill in the boundary regions of each FAB in the FabArray.
218+
If cross=true, corner cells are not filled. If the length of periodic is provided,
219+
periodic boundaries are also filled.
220+
221+
If scomp is provided, this only copies ncomp components starting at scomp.
222+
223+
Note that FabArray itself does not contains any periodicity information.
224+
FillBoundary expects that its cell-centered version of its BoxArray is non-overlapping.)";
225+
226+
py_FAT
227+
.def("fill_boundary",
228+
py::overload_cast< bool >(&FAT::template FillBoundary<value_type>),
229+
py::arg("cross")=false,
230+
doc_fabarray_fillb
231+
)
232+
.def("fill_boundary",
233+
py::overload_cast< Periodicity const &, bool >(&FAT::template FillBoundary<value_type>),
234+
py::arg("period"),
235+
py::arg("cross")=false,
236+
doc_fabarray_fillb
237+
)
238+
.def("fill_boundary",
239+
py::overload_cast< IntVect const &, Periodicity const &, bool >(&FAT::template FillBoundary<value_type>),
240+
py::arg("nghost"),
241+
py::arg("period"),
242+
py::arg("cross")=false,
243+
doc_fabarray_fillb
244+
)
245+
.def("fill_boundary",
246+
py::overload_cast< int, int, bool >(&FAT::template FillBoundary<value_type>),
247+
py::arg("scomp"),
248+
py::arg("ncomp"),
249+
py::arg("cross")=false,
250+
doc_fabarray_fillb
251+
)
252+
.def("fill_boundary",
253+
py::overload_cast< int, int, Periodicity const &, bool >(&FAT::template FillBoundary<value_type>),
254+
py::arg("scomp"),
255+
py::arg("ncomp"),
256+
py::arg("period"),
257+
py::arg("cross")=false,
258+
doc_fabarray_fillb
259+
)
260+
.def("fill_boundary",
261+
py::overload_cast< int, int, IntVect const &, Periodicity const &, bool >(&FAT::template FillBoundary<value_type>),
262+
py::arg("scomp"),
263+
py::arg("ncomp"),
264+
py::arg("nghost"),
265+
py::arg("period"),
266+
py::arg("cross")=false,
267+
doc_fabarray_fillb
268+
)
269+
;
270+
}
271+
}
272+
273+
void
274+
init_FabArray(py::module &m)
275+
{
276+
using namespace amrex;
277+
278+
py::class_< FabArrayBase >(m, "FabArrayBase")
279+
.def_property_readonly("is_all_cell_centered", &FabArrayBase::is_cell_centered)
280+
.def_property_readonly("is_all_nodal",
281+
py::overload_cast< >(&FabArrayBase::is_nodal, py::const_))
282+
.def("is_nodal",
283+
py::overload_cast< int >(&FabArrayBase::is_nodal, py::const_))
284+
285+
.def_property_readonly("nComp", &FabArrayBase::nComp,
286+
"Return number of variables (aka components) associated with each point.")
287+
.def_property_readonly("num_comp", &FabArrayBase::nComp,
288+
"Return number of variables (aka components) associated with each point.")
289+
.def_property_readonly("size", &FabArrayBase::size,
290+
"Return the number of FABs in the FabArray.")
291+
292+
.def_property_readonly("n_grow_vect", &FabArrayBase::nGrowVect,
293+
"Return the grow factor (per direction) that defines the region of definition.")
294+
;
295+
296+
py::class_< FabFactory<IArrayBox> >(m, "FabFactory_IArrayBox");
297+
py::class_< FabFactory<FArrayBox> >(m, "FabFactory_FArrayBox");
298+
299+
make_FabArray_T<IArrayBox>(m, "IArrayBox");
300+
make_FabArray_T<FArrayBox>(m, "FArrayBox");
301+
}

src/Base/MFInfo.cpp

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* Copyright 2021-2022 The AMReX Community
2+
*
3+
* Authors: Axel Huebl
4+
* License: BSD-3-Clause-LBNL
5+
*/
6+
#include "pyAMReX.H"
7+
8+
#include <AMReX_FabArray.H>
9+
10+
11+
void init_MFInfo(py::module &m)
12+
{
13+
using namespace amrex;
14+
15+
py::class_<MFInfo>(m, "MFInfo")
16+
.def_readwrite("alloc", &MFInfo::alloc)
17+
.def_readwrite("arena", &MFInfo::arena)
18+
.def_readwrite("tags", &MFInfo::tags)
19+
20+
.def(py::init<>())
21+
22+
.def("set_alloc", &MFInfo::SetAlloc)
23+
.def("set_arena", &MFInfo::SetArena)
24+
//.def("set_tag", py::overload_cast< std::string >(&MFInfo::SetTag))
25+
.def("set_tag", [](MFInfo &info, std::string tag) { info.SetTag(std::move(tag)); });
26+
27+
py::class_<MFItInfo>(m, "MFItInfo")
28+
.def_readwrite("do_tiling", &MFItInfo::do_tiling)
29+
.def_readwrite("dynamic", &MFItInfo::dynamic)
30+
.def_readwrite("device_sync", &MFItInfo::device_sync)
31+
.def_readwrite("num_streams", &MFItInfo::num_streams)
32+
.def_readwrite("tilesize", &MFItInfo::tilesize)
33+
34+
.def(py::init<>())
35+
36+
.def("enable_tiling", &MFItInfo::EnableTiling,
37+
py::arg("ts") /*=FabArrayBase::mfiter_tile_size*/ )
38+
.def("set_dynamic", &MFItInfo::SetDynamic,
39+
py::arg("f"))
40+
.def("disable_device_sync", &MFItInfo::DisableDeviceSync)
41+
.def("set_device_sync", &MFItInfo::SetDeviceSync,
42+
py::arg("f"))
43+
.def("set_num_streams", &MFItInfo::SetNumStreams,
44+
py::arg("n"))
45+
.def("use_default_stream", &MFItInfo::UseDefaultStream);
46+
}

0 commit comments

Comments
 (0)