15#include "Utility/IpplException.h"
22 template <
typename Field>
23 BCondBase<Field>::BCondBase(
unsigned int face)
25 , changePhysical_m(false) {}
27 template <
typename Field>
28 inline std::ostream& operator<<(std::ostream& os,
const BCondBase<Field>& bc) {
35 template <
typename Field>
36 void ExtrapolateFace<Field>::apply(
Field& field) {
40 unsigned int face = this->face_m;
41 unsigned d = face / 2;
42 if (field.getCommunicator().size() > 1) {
43 const Layout_t& layout = field.getLayout();
44 const auto& lDomains = layout.getHostLocalDomains();
45 const auto& domain = layout.getDomain();
46 int myRank = field.getCommunicator().rank();
52 const bool isLowerFace = !(face & 1);
54 const bool isBoundary = isLowerFace ? (lDomains[myRank][d].min() == domain[d].min())
55 : (lDomains[myRank][d].max() == domain[d].max());
66 typename Field::view_type& view = field.getView();
67 const int nghost = field.getNghost();
73 throw IpplException(
"ExtrapolateFace::apply",
"nghost > 1 not supported");
77 throw IpplException(
"ExtrapolateFace::apply",
"face number wrong");
82 src = view.extent(d) - 2;
89 using exec_space =
typename Field::execution_space;
90 using index_type =
typename RangePolicy<Dim, exec_space>::index_type;
91 Kokkos::Array<index_type, Dim> begin, end;
92 for (
unsigned i = 0; i < Dim; i++) {
94 end[i] = view.extent(i) - nghost;
98 using index_array_type =
typename RangePolicy<Dim, exec_space>::index_array_type;
100 "Assign extrapolate BC", createRangePolicy<Dim, exec_space>(begin, end),
101 KOKKOS_CLASS_LAMBDA(index_array_type & args) {
105 T value =
apply(view, args);
109 apply(view, args) = slope_m * value + offset_m;
113 template <
typename Field>
114 void ExtrapolateFace<Field>::write(std::ostream& out)
const {
115 out <<
"Constant Extrapolation Face"
116 <<
", Face = " << this->face_m;
119 template <
typename Field>
120 void NoBcFace<Field>::write(std::ostream& out)
const {
122 <<
", Face = " << this->face_m;
125 template <
typename Field>
126 void ConstantFace<Field>::write(std::ostream& out)
const {
127 out <<
"ConstantFace"
128 <<
", Face = " << this->face_m <<
", Constant = " << this->offset_m;
131 template <
typename Field>
132 void ZeroFace<Field>::write(std::ostream& out)
const {
134 <<
", Face = " << this->face_m;
137 template <
typename Field>
138 void PeriodicFace<Field>::write(std::ostream& out)
const {
139 out <<
"PeriodicFace"
140 <<
", Face = " << this->face_m;
143 template <
typename Field>
144 void PeriodicFace<Field>::findBCNeighbors(
Field& field) {
145 auto& comm = field.getCommunicator();
147 unsigned int face = this->face_m;
148 unsigned int d = face / 2;
149 const int nghost = field.getNghost();
150 int myRank = comm.rank();
151 const Layout_t& layout = field.getLayout();
152 const auto& lDomains = layout.getHostLocalDomains();
153 const auto& domain = layout.getDomain();
155 for (
auto& neighbors : faceNeighbors_m) {
159 if (lDomains[myRank][d].length() < domain[d].length()) {
162 bool isBoundary = (lDomains[myRank][d].max() == domain[d].max())
163 || (lDomains[myRank][d].min() == domain[d].min());
168 auto& nd = lDomains[myRank];
171 auto gnd = nd.grow(nghost, d);
176 offset = -domain[d].length();
179 offset = domain[d].length();
182 gnd[d] = gnd[d] + offset;
185 for (
int rank = 0; rank < comm.size(); ++rank) {
186 if (rank == myRank) {
190 if (gnd.touches(lDomains[rank])) {
191 faceNeighbors_m[face].push_back(rank);
198 template <
typename Field>
199 void PeriodicFace<Field>::apply(
Field& field) {
200 auto& comm = field.getCommunicator();
201 unsigned int face = this->face_m;
202 unsigned int d = face / 2;
203 typename Field::view_type& view = field.getView();
204 const Layout_t& layout = field.getLayout();
205 const int nghost = field.getNghost();
206 int myRank = comm.rank();
207 const auto& lDomains = layout.getHostLocalDomains();
208 const auto& domain = layout.getDomain();
212 int tag = comm.next_tag(mpi::tag::BC_PARALLEL_PERIODIC, mpi::tag::BC_CYCLE);
214 if (lDomains[myRank][d].length() < domain[d].length()) {
217 bool isBoundary = (lDomains[myRank][d].max() == domain[d].max())
218 || (lDomains[myRank][d].min() == domain[d].min());
223 auto& nd = lDomains[myRank];
225 int offset, offsetRecv, matchtag;
228 offset = -domain[d].length();
230 matchtag = comm.preceding_tag(mpi::tag::BC_PARALLEL_PERIODIC);
233 offset = domain[d].length();
234 offsetRecv = -nghost;
235 matchtag = comm.following_tag(mpi::tag::BC_PARALLEL_PERIODIC);
238 auto& neighbors = faceNeighbors_m[face];
240 using memory_space =
typename Field::memory_space;
241 using buffer_type = mpi::Communicator::buffer_type<memory_space>;
242 std::vector<MPI_Request> requests(neighbors.size());
245 using range_t =
typename HaloCells_t::bound_type;
246 HaloCells_t& halo = field.getHalo();
247 std::vector<range_t> rangeNeighbors;
249 for (
size_t i = 0; i < neighbors.size(); ++i) {
250 int rank = neighbors[i];
252 auto ndNeighbor = lDomains[rank];
253 ndNeighbor[d] = ndNeighbor[d] - offset;
255 NDIndex<Dim> gndNeighbor = ndNeighbor.grow(nghost, d);
257 NDIndex<Dim> overlap = gndNeighbor.intersect(nd);
261 for (
size_t j = 0; j < Dim; ++j) {
262 range.lo[j] = overlap[j].first() - nd[j].first() + nghost;
263 range.hi[j] = overlap[j].last() - nd[j].first() + nghost + 1;
266 rangeNeighbors.push_back(range);
268 detail::size_type nSends;
269 halo.
pack(range, view, haloData_m, nSends);
271 buffer_type buf = comm.template getBuffer<memory_space, T>(nSends);
273 comm.isend(rank, tag, haloData_m, *buf, requests[i], nSends);
274 buf->resetWritePos();
277 for (
size_t i = 0; i < neighbors.size(); ++i) {
278 int rank = neighbors[i];
280 range_t range = rangeNeighbors[i];
282 range.lo[d] = range.lo[d] + offsetRecv;
283 range.hi[d] = range.hi[d] + offsetRecv;
285 detail::size_type nRecvs = range.size();
287 buffer_type buf = comm.template getBuffer<memory_space, T>(nRecvs);
288 comm.recv(rank, matchtag, haloData_m, *buf, nRecvs *
sizeof(T), nRecvs);
291 using assign_t =
typename HaloCells_t::assign;
292 halo.template unpack<assign_t>(range, view, haloData_m);
294 if (!requests.empty()) {
295 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
297 comm.freeAllBuffers();
302 throw IpplException(
"PeriodicFace::apply",
"face number wrong");
305 auto N = view.extent(d) - 1;
307 using exec_space =
typename Field::execution_space;
308 using index_type =
typename RangePolicy<Dim, exec_space>::index_type;
309 Kokkos::Array<index_type, Dim> begin, end;
314 for (
size_t i = 0; i < Dim; ++i) {
315 end[i] = view.extent(i) - nghost;
321 using index_array_type =
typename RangePolicy<Dim, exec_space>::index_array_type;
323 "Assign periodic field BC", createRangePolicy<Dim, exec_space>(begin, end),
324 KOKKOS_CLASS_LAMBDA(index_array_type & coords) {
334 auto&& left =
apply(view, coords);
337 coords[d] = N - coords[d];
338 auto&& right =
apply(view, coords);
341 coords[d] += 2 * nghost - 1 - N;
342 apply(view, coords) = right;
346 coords[d] = N - coords[d];
347 apply(view, coords) = left;
352 template <
typename Field>
353 void PeriodicFace<Field>::assignGhostToPhysical(
Field& field) {
354 unsigned int face = this->face_m;
355 unsigned int d = face / 2;
356 typename Field::view_type& view = field.getView();
357 const Layout_t& layout = field.getLayout();
358 const int nghost = field.getNghost();
359 const auto& ldom = layout.getLocalNDIndex();
360 const auto& domain = layout.getDomain();
363 throw IpplException(
"PeriodicFace::apply",
"face number wrong");
366 bool upperFace = (face & 1);
367 bool isBoundary = ((ldom[d].max() == domain[d].max()) && upperFace)
368 || ((ldom[d].min() == domain[d].min()) && !(upperFace));
371 auto N = view.extent(d) - 1;
373 using exec_space =
typename Field::execution_space;
374 using index_type =
typename RangePolicy<Dim, exec_space>::index_type;
375 Kokkos::Array<index_type, Dim> begin, end;
380 bool isCorner = (d != 0);
381 for (
size_t i = 0; i < Dim; ++i) {
382 bool upperFace_i = (ldom[i].max() == domain[i].max());
383 bool lowerFace_i = (ldom[i].min() == domain[i].min());
384 end[i] = view.extent(i) - nghost - (upperFace_i) * (isCorner);
385 begin[i] = nghost + (lowerFace_i) * (isCorner);
387 begin[d] = ((0 + nghost - 1) * (1 - upperFace)) + (N * upperFace);
388 end[d] = begin[d] + 1;
390 using index_array_type =
typename RangePolicy<Dim, exec_space>::index_array_type;
392 "Assign periodic field BC", createRangePolicy<Dim, exec_space>(begin, end),
393 KOKKOS_CLASS_LAMBDA(index_array_type & coords) {
401 auto&& right =
apply(view, coords);
404 int shift = 1 - (2 * upperFace);
407 apply(view, coords) += right;
412 template <
typename Field>
413 void ExtrapolateFace<Field>::assignGhostToPhysical(
Field& field) {
414 unsigned int face = this->face_m;
415 unsigned int d = face / 2;
416 typename Field::view_type& view = field.getView();
417 const Layout_t& layout = field.getLayout();
418 const int nghost = field.getNghost();
419 const auto& ldom = layout.getLocalNDIndex();
420 const auto& domain = layout.getDomain();
423 throw IpplException(
"ExtrapolateFace::apply",
"face number wrong");
426 bool upperFace = (face & 1);
427 bool isBoundary = ((ldom[d].max() == domain[d].max()) && upperFace)
428 || ((ldom[d].min() == domain[d].min()) && !(upperFace));
431 auto N = view.extent(d) - 1;
433 using exec_space =
typename Field::execution_space;
434 using index_type =
typename RangePolicy<Dim, exec_space>::index_type;
435 Kokkos::Array<index_type, Dim> begin, end;
440 for (
size_t i = 0; i < Dim; ++i) {
441 end[i] = view.extent(i) - nghost;
444 begin[d] = ((0 + nghost - 1) * (1 - upperFace)) + (N * upperFace);
445 end[d] = begin[d] + 1;
447 using index_array_type =
typename RangePolicy<Dim, exec_space>::index_array_type;
449 "Assign field BC", createRangePolicy<Dim, exec_space>(begin, end),
450 KOKKOS_CLASS_LAMBDA(index_array_type & coords) {
458 auto&& right =
apply(view, coords);
461 int shift = 1 - (2 * upperFace);
465 apply(view, coords) = right;
Definition IpplException.h:6
void pack(const bound_type &range, const view_type &view, databuffer_type &fd, size_type &nsends)
Definition HaloCells.hpp:158
KOKKOS_INLINE_FUNCTION constexpr decltype(auto) apply(const View &view, const Coords &coords)
Definition IpplOperations.h:64