9template <
typename Tb,
typename Tf>
13 Kokkos::View<Tb*>& buffer = fd.
buffer;
15 size_t size = intersect.
size();
17 if (buffer.size() < size) {
18 const int overalloc =
ippl::Comm->getDefaultOverallocation();
19 Kokkos::realloc(buffer, size * overalloc);
22 const int first0 = intersect[0].
first() + nghost - ldom[0].
first();
23 const int first1 = intersect[1].
first() + nghost - ldom[1].
first();
24 const int first2 = intersect[2].
first() + nghost - ldom[2].
first();
26 const int last0 = intersect[0].
last() + nghost - ldom[0].
first() + 1;
27 const int last1 = intersect[1].
last() + nghost - ldom[1].
first() + 1;
28 const int last2 = intersect[2].
last() + nghost - ldom[2].
first() + 1;
30 using mdrange_type = Kokkos::MDRangePolicy<Kokkos::Rank<3>>;
35 mdrange_type({first0, first1, first2}, {(
long int)last0, (
long int)last1, (
long int)last2}),
36 KOKKOS_LAMBDA(
const size_t i,
const size_t j,
const size_t k) {
37 const int ig = i - first0;
38 const int jg = j - first1;
39 const int kg = k - first2;
41 int l = ig + jg * intersect[0].
length()
44 Kokkos::complex<Tb> val = view(i, j, k);
46 buffer(l) = Kokkos::real(val);
51template <
int tensorRank,
typename Tb,
typename Tf>
54 size_t dim1 = 0,
size_t dim2 = 0,
bool x =
false,
bool y =
false,
bool z =
false) {
55 Kokkos::View<Tb*>& buffer = fd.
buffer;
57 const int first0 = intersect[0].
first() + nghost - ldom[0].
first();
58 const int first1 = intersect[1].
first() + nghost - ldom[1].
first();
59 const int first2 = intersect[2].
first() + nghost - ldom[2].
first();
61 const int last0 = intersect[0].
last() + nghost - ldom[0].
first() + 1;
62 const int last1 = intersect[1].
last() + nghost - ldom[1].
first() + 1;
63 const int last2 = intersect[2].
last() + nghost - ldom[2].
first() + 1;
65 using mdrange_type = Kokkos::MDRangePolicy<Kokkos::Rank<3>>;
67 "pack()", mdrange_type({first0, first1, first2}, {last0, last1, last2}),
68 KOKKOS_LAMBDA(
const size_t i,
const size_t j,
const size_t k) {
73 ig = x * (intersect[0].
length() - 2 * ig - 1) + ig;
74 jg = y * (intersect[1].
length() - 2 * jg - 1) + jg;
75 kg = z * (intersect[2].
length() - 2 * kg - 1) + kg;
77 int l = ig + jg * intersect[0].
length()
86template <
typename Tb,
typename Tf>
89 bool x =
false,
bool y =
false,
bool z =
false) {
90 unpack_impl<0, Tb, Tf>(intersect, view, fd, nghost, ldom, 0, 0, x, y, z);
93template <
typename Tb,
typename Tf>
97 unpack_impl<1, Tb, ippl::Vector<Tf, 3>>(intersect, view, fd, nghost, ldom, dim1);
100template <
typename Tb,
typename Tf>
104 size_t dim1,
size_t dim2) {
105 unpack_impl<2, Tb, ippl::Vector<ippl::Vector<Tf, 3>, 3>>(intersect, view, fd, nghost, ldom,
109template <
typename Tb,
typename Tf,
unsigned Dim>
113 using memory_space =
typename Kokkos::View<Tf***>::memory_space;
115 requests.resize(requests.size() + 1);
118 pack(intersection, view, fd, nghost, ldom, nsends);
122 ippl::Comm->getBuffer<memory_space, Tf>(nsends);
126 ippl::Comm->isend(i, tag, fd, *buf, requests.back(), nsends);
127 buf->resetWritePos();
130template <
typename Tb,
typename Tf,
unsigned Dim>
135 using memory_space =
typename Kokkos::View<Tf***>::memory_space;
138 nrecvs = intersection.
size();
142 ippl::Comm->getBuffer<memory_space, Tf>(nrecvs);
146 ippl::Comm->recv(i, tag, fd, *buf, nrecvs *
sizeof(Tf), nrecvs);
149 unpack(intersection, view, fd, nghost, ldom, x, y, z);
156 template <
typename FieldLHS,
typename FieldRHS>
163 , meshComplex_m(nullptr)
164 , layoutComplex_m(nullptr)
168 , layout2n1_m(nullptr)
169 , isGradFD_m(false) {
173 template <
typename FieldLHS,
typename FieldRHS>
180 , meshComplex_m(nullptr)
181 , layoutComplex_m(nullptr)
185 , layout2n1_m(nullptr)
186 , isGradFD_m(false) {
187 using T =
typename FieldLHS::value_type::value_type;
188 static_assert(std::is_floating_point<T>::value,
"Not a floating point type");
197 template <
typename FieldLHS,
typename FieldRHS>
204 , meshComplex_m(nullptr)
205 , layoutComplex_m(nullptr)
209 , layout2n1_m(nullptr)
210 , isGradFD_m(false) {
211 using T =
typename FieldLHS::value_type::value_type;
212 static_assert(std::is_floating_point<T>::value,
"Not a floating point type");
223 template <
typename FieldLHS,
typename FieldRHS>
240 template <
typename FieldLHS,
typename FieldRHS>
243 const int out = this->params_m.template get<int>(
"output_type");
245 if (out != Base::SOL_AND_GRAD) {
247 "FFTOpenPoissonSolver::setGradFD()",
248 "Cannot use gradient for Efield computation unless output type is SOL_AND_GRAD");
257 template <
typename FieldLHS,
typename FieldRHS>
260 const int alg = this->params_m.template get<int>(
"algorithm");
261 const bool hessian = this->params_m.template get<bool>(
"hessian");
264 if ((alg != Algorithm::VICO) && (alg != Algorithm::HOCKNEY)
265 && (alg != Algorithm::BIHARMONIC) && (alg != Algorithm::DCT_VICO)) {
266 throw IpplException(
"FFTOpenPoissonSolver::initializeFields()",
267 "Currently only HOCKNEY, VICO, DCT_VICO, and BIHARMONIC are "
268 "supported for open BCs");
272 layout_mp = &(this->rhs_mp->getLayout());
273 mesh_mp = &(this->rhs_mp->get_mesh());
277 hr_m = mesh_mp->getMeshSpacing();
281 domain_m = layout_mp->getDomain();
284 for (
unsigned int i = 0; i <
Dim; ++i) {
285 nr_m[i] = domain_m[i].length();
288 domain2_m[i] =
Index(2 * nr_m[i]);
292 std::array<bool, Dim> isParallel = layout_mp->isParallel();
296 mesh2_m = std::unique_ptr<mesh_type>(
new mesh_type(domain2_m, hr_m, origin));
297 layout2_m = std::unique_ptr<FieldLayout_t>(
new FieldLayout_t(comm, domain2_m, isParallel));
303 unsigned int RCDirection = this->params_m.template get<int>(
"r2c_direction");
304 for (
unsigned int i = 0; i <
Dim; ++i) {
305 if (i == RCDirection) {
306 domainComplex_m[RCDirection] =
Index(nr_m[RCDirection] + 1);
308 domainComplex_m[i] =
Index(2 * nr_m[i]);
313 meshComplex_m = std::unique_ptr<mesh_type>(
new mesh_type(domainComplex_m, hr_m, origin));
315 std::unique_ptr<FieldLayout_t>(
new FieldLayout_t(comm, domainComplex_m, isParallel));
318 storage_field.initialize(*mesh2_m, *layout2_m);
319 rho2tr_m.initialize(*meshComplex_m, *layoutComplex_m);
320 grntr_m.initialize(*meshComplex_m, *layoutComplex_m);
322 int out = this->params_m.template get<int>(
"output_type");
323 if (((out == Base::GRAD || out == Base::SOL_AND_GRAD) && !isGradFD_m) || hessian) {
324 temp_m.initialize(*meshComplex_m, *layoutComplex_m);
328 hess_m.initialize(*mesh_mp, *layout_mp);
332 fft_m = std::make_unique<FFT_t>(*layout2_m, *layoutComplex_m, this->params_m);
337 if (alg == Algorithm::VICO || alg == Algorithm::BIHARMONIC) {
343 for (
unsigned int i = 0; i <
Dim; ++i) {
344 domain4_m[i] =
Index(4 * nr_m[i]);
349 mesh4_m = std::unique_ptr<mesh_type>(
new mesh_type(domain4_m, hr_m, origin));
351 std::unique_ptr<FieldLayout_t>(
new FieldLayout_t(comm, domain4_m, isParallel));
354 grnL_m.initialize(*mesh4_m, *layout4_m);
357 fft4n_m = std::make_unique<FFT<CCTransform, CxField_gt>>(*layout4_m, this->params_m);
364 if (alg == Algorithm::DCT_VICO) {
371 for (
unsigned int i = 0; i <
Dim; ++i) {
372 domain2n1_m[i] =
Index(2 * nr_m[i] + 1);
376 mesh2n1_m = std::unique_ptr<mesh_type>(
new mesh_type(domain2n1_m, hr_m, origin));
378 std::unique_ptr<FieldLayout_t>(
new FieldLayout_t(comm, domain2n1_m, isParallel));
381 grn2n1_m.initialize(*mesh2n1_m, *layout2n1_m);
384 fft2n1_m = std::make_unique<FFT<Cos1Transform, Field_t>>(*layout2n1_m, this->params_m);
390 if (alg == Algorithm::HOCKNEY) {
396 for (
unsigned int d = 0; d <
Dim; ++d) {
397 grnIField_m[d].initialize(*mesh2_m, *layout2_m);
400 auto view = grnIField_m[d].getView();
401 const int nghost = grnIField_m[d].getNghost();
402 const auto& ldom = layout2_m->getLocalNDIndex();
405 const int size = nr_m[d];
411 "Helper index Green field initialization",
412 grnIField_m[d].getFieldRangePolicy(),
413 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
415 const int ig = i + ldom[0].first() - nghost;
416 const int jg = j + ldom[1].first() - nghost;
417 const int kg = k + ldom[2].first() - nghost;
420 const bool outsideN = (ig >= size);
422 (2 * size * outsideN - ig) * (2 * size * outsideN - ig);
425 const bool isOrig = ((ig == 0) && (jg == 0) && (kg == 0));
426 view(i, j, k) += isOrig * 1.0;
431 "Helper index Green field initialization",
432 grnIField_m[d].getFieldRangePolicy(),
433 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
435 const int jg = j + ldom[1].first() - nghost;
438 const bool outsideN = (jg >= size);
440 (2 * size * outsideN - jg) * (2 * size * outsideN - jg);
445 "Helper index Green field initialization",
446 grnIField_m[d].getFieldRangePolicy(),
447 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
449 const int kg = k + ldom[2].first() - nghost;
452 const bool outsideN = (kg >= size);
454 (2 * size * outsideN - kg) * (2 * size * outsideN - kg);
466 fft_m->warmup(rho2_mr, rho2tr_m);
467 if (alg == Algorithm::VICO || alg == Algorithm::BIHARMONIC) {
468 fft4n_m->warmup(grnL_m);
470 if (alg == Algorithm::DCT_VICO) {
471 fft2n1_m->warmup(grn2n1_m);
492 template <
typename FieldLHS,
typename FieldRHS>
499 const int out = this->params_m.template get<int>(
"output_type");
502 const int alg = this->params_m.template get<int>(
"algorithm");
505 const bool hessian = this->params_m.template get<bool>(
"hessian");
508 mesh_mp = &(this->rhs_mp->get_mesh());
513 for (
unsigned int i = 0; i <
Dim; ++i) {
514 if (hr_m[i] != mesh_mp->getMeshSpacing(i)) {
515 hr_m[i] = mesh_mp->getMeshSpacing(i);
521 mesh2_m->setMeshSpacing(hr_m);
522 meshComplex_m->setMeshSpacing(hr_m);
534 const int ranks =
Comm->size();
536 auto view2 = rho2_mr.getView();
537 auto view1 = this->rhs_mp->getView();
539 const int nghost2 = rho2_mr.getNghost();
540 const int nghost1 = this->rhs_mp->getNghost();
542 const auto& ldom2 = layout2_m->getLocalNDIndex();
543 const auto& ldom1 = layout_mp->getLocalNDIndex();
547 const auto& lDomains2 = layout2_m->getHostLocalDomains();
550 std::vector<MPI_Request> requests(0);
552 for (
int i = 0; i < ranks; ++i) {
553 if (lDomains2[i].touches(ldom1)) {
554 auto intersection = lDomains2[i].intersect(ldom1);
562 const auto& lDomains1 = layout_mp->getHostLocalDomains();
564 for (
int i = 0; i < ranks; ++i) {
565 if (lDomains1[i].touches(ldom2)) {
566 auto intersection = lDomains1[i].intersect(ldom2);
569 nrecvs = intersection.size();
576 unpack(intersection, view2, fd_m, nghost2, ldom2);
581 if (requests.size() > 0) {
582 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
588 "Write rho on the doubled grid", this->rhs_mp->getFieldRangePolicy(),
589 KOKKOS_LAMBDA(
const size_t i,
const size_t j,
const size_t k) {
590 const size_t ig2 = i + ldom2[0].first() - nghost2;
591 const size_t jg2 = j + ldom2[1].first() - nghost2;
592 const size_t kg2 = k + ldom2[2].first() - nghost2;
594 const size_t ig1 = i + ldom1[0].first() - nghost1;
595 const size_t jg1 = j + ldom1[1].first() - nghost1;
596 const size_t kg1 = k + ldom1[2].first() - nghost1;
599 const bool isQuadrant1 = ((ig1 == ig2) && (jg1 == jg2) && (kg1 == kg2));
600 view2(i, j, k) = view1(i, j, k) * isQuadrant1;
611 fft_m->transform(
FORWARD, rho2_mr, rho2tr_m);
623 rho2tr_m = -rho2tr_m * grntr_m;
626 if ((out == Base::SOL) || (out == Base::SOL_AND_GRAD)) {
632 fft_m->transform(
BACKWARD, rho2_mr, rho2tr_m);
642 for (
unsigned int i = 0; i <
Dim; ++i) {
644 case Algorithm::HOCKNEY:
645 rho2_mr = rho2_mr * 2.0 * nr_m[i] * hr_m[i];
647 case Algorithm::VICO:
648 case Algorithm::BIHARMONIC:
649 rho2_mr = rho2_mr * 2.0 * (1.0 / 4.0);
651 case Algorithm::DCT_VICO:
652 rho2_mr = rho2_mr * (1.0 / 4.0);
656 "FFTOpenPoissonSolver::initializeFields()",
657 "Currently only HOCKNEY, VICO, DCT_VICO, and BIHARMONIC are "
658 "supported for open BCs");
673 const auto& lDomains1 = layout_mp->getHostLocalDomains();
675 std::vector<MPI_Request> requests(0);
677 for (
int i = 0; i < ranks; ++i) {
678 if (lDomains1[i].touches(ldom2)) {
679 auto intersection = lDomains1[i].intersect(ldom2);
682 view2, fd_m, requests);
687 const auto& lDomains2 = layout2_m->getHostLocalDomains();
689 for (
int i = 0; i < ranks; ++i) {
690 if (ldom1.touches(lDomains2[i])) {
691 auto intersection = ldom1.intersect(lDomains2[i]);
694 nrecvs = intersection.size();
702 unpack(intersection, view1, fd_m, nghost1, ldom1);
707 if (requests.size() > 0) {
708 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
714 "Write the solution into the LHS on physical grid",
715 this->rhs_mp->getFieldRangePolicy(),
716 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
717 const int ig2 = i + ldom2[0].first() - nghost2;
718 const int jg2 = j + ldom2[1].first() - nghost2;
719 const int kg2 = k + ldom2[2].first() - nghost2;
721 const int ig = i + ldom1[0].first() - nghost1;
722 const int jg = j + ldom1[1].first() - nghost1;
723 const int kg = k + ldom1[2].first() - nghost1;
726 const bool isQuadrant1 = ((ig == ig2) && (jg == jg2) && (kg == kg2));
727 view1(i, j, k) = view2(i, j, k) * isQuadrant1;
736 if (isGradFD_m && (out == Base::SOL_AND_GRAD)) {
737 *(this->lhs_mp) = -
grad(*this->rhs_mp);
741 if (((out == Base::GRAD) || (out == Base::SOL_AND_GRAD)) && (!isGradFD_m)) {
747 auto viewL = this->lhs_mp->getView();
748 const int nghostL = this->lhs_mp->getNghost();
751 auto viewR = rho2tr_m.getView();
752 const int nghostR = rho2tr_m.getNghost();
753 const auto& ldomR = layoutComplex_m->getLocalNDIndex();
756 auto view_g = temp_m.getView();
760 const Kokkos::complex<Trhs> I = {0.0, 1.0};
767 for (
size_t gd = 0; gd <
Dim; ++gd) {
770 "Gradient - E field", rho2tr_m.getFieldRangePolicy(),
771 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
773 const int ig = i + ldomR[0].first() - nghostR;
774 const int jg = j + ldomR[1].first() - nghostR;
775 const int kg = k + ldomR[2].first() - nghostR;
781 const bool shift = (iVec[gd] > N[gd]);
782 const bool notMid = (iVec[gd] != N[gd]);
784 k_gd = notMid * (
pi / Len) * (iVec[gd] - shift * 2 * N[gd]);
786 view_g(i, j, k) = -(I * k_gd) * viewR(i, j, k);
794 fft_m->transform(
BACKWARD, rho2_mr, temp_m);
799 for (
unsigned int i = 0; i <
Dim; ++i) {
801 case Algorithm::HOCKNEY:
802 rho2_mr = rho2_mr * 2.0 * nr_m[i] * hr_m[i];
804 case Algorithm::VICO:
805 case Algorithm::BIHARMONIC:
806 rho2_mr = rho2_mr * 2.0 * (1.0 / 4.0);
808 case Algorithm::DCT_VICO:
809 rho2_mr = rho2_mr * (1.0 / 4.0);
813 "FFTOpenPoissonSolver::initializeFields()",
814 "Currently only HOCKNEY, VICO, DCT_VICO, and BIHARMONIC are "
815 "supported for open BCs");
830 const auto& lDomains1 = layout_mp->getHostLocalDomains();
831 std::vector<MPI_Request> requests(0);
833 for (
int i = 0; i < ranks; ++i) {
834 if (lDomains1[i].touches(ldom2)) {
835 auto intersection = lDomains1[i].intersect(ldom2);
838 view2, fd_m, requests);
843 const auto& lDomains2 = layout2_m->getHostLocalDomains();
845 for (
int i = 0; i < ranks; ++i) {
846 if (ldom1.touches(lDomains2[i])) {
847 auto intersection = ldom1.intersect(lDomains2[i]);
850 nrecvs = intersection.size();
858 unpack(intersection, viewL, gd, fd_m, nghostL, ldom1);
863 if (requests.size() > 0) {
864 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
870 "Write the E-field on physical grid", this->lhs_mp->getFieldRangePolicy(),
871 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
872 const int ig2 = i + ldom2[0].first() - nghost2;
873 const int jg2 = j + ldom2[1].first() - nghost2;
874 const int kg2 = k + ldom2[2].first() - nghost2;
876 const int ig = i + ldom1[0].first() - nghostL;
877 const int jg = j + ldom1[1].first() - nghostL;
878 const int kg = k + ldom1[2].first() - nghostL;
881 const bool isQuadrant1 = ((ig == ig2) && (jg == jg2) && (kg == kg2));
882 viewL(i, j, k)[gd] = view2(i, j, k) * isQuadrant1;
897 auto viewH = hess_m.getView();
898 const int nghostH = hess_m.getNghost();
901 auto viewR = rho2tr_m.getView();
902 const int nghostR = rho2tr_m.getNghost();
903 const auto& ldomR = layoutComplex_m->getLocalNDIndex();
906 auto view_g = temp_m.getView();
916 for (
size_t row = 0; row <
Dim; ++row) {
917 for (
size_t col = 0; col <
Dim; ++col) {
923 "Hessian", rho2tr_m.getFieldRangePolicy(),
924 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
926 const int ig = i + ldomR[0].first() - nghostR;
927 const int jg = j + ldomR[1].first() - nghostR;
928 const int kg = k + ldomR[2].first() - nghostR;
933 for (
size_t d = 0; d <
Dim; ++d) {
935 const bool shift = (iVec[d] > N[d]);
936 const bool isMid = (iVec[d] == N[d]);
937 const bool notDiag = (row != col);
939 kVec[d] = (1 - (notDiag * isMid)) * (
pi / Len)
940 * (iVec[d] - shift * 2 * N[d]);
943 view_g(i, j, k) = -(kVec[col] * kVec[row]) * viewR(i, j, k);
951 fft_m->transform(
BACKWARD, rho2_mr, temp_m);
956 for (
unsigned int i = 0; i <
Dim; ++i) {
958 case Algorithm::HOCKNEY:
959 rho2_mr = rho2_mr * 2.0 * nr_m[i] * hr_m[i];
961 case Algorithm::VICO:
962 case Algorithm::BIHARMONIC:
963 rho2_mr = rho2_mr * 2.0 * (1.0 / 4.0);
965 case Algorithm::DCT_VICO:
966 rho2_mr = rho2_mr * (1.0 / 4.0);
970 "FFTOpenPoissonSolver::initializeFields()",
971 "Currently only HOCKNEY, VICO, DCT_VICO, and BIHARMONIC are "
972 "supported for open BCs");
987 const auto& lDomains1 = layout_mp->getHostLocalDomains();
988 std::vector<MPI_Request> requests(0);
990 for (
int i = 0; i < ranks; ++i) {
991 if (lDomains1[i].touches(ldom2)) {
992 auto intersection = lDomains1[i].intersect(ldom2);
995 nghost2, view2, fd_m, requests);
1000 const auto& lDomains2 = layout2_m->getHostLocalDomains();
1002 for (
int i = 0; i < ranks; ++i) {
1003 if (ldom1.touches(lDomains2[i])) {
1004 auto intersection = ldom1.intersect(lDomains2[i]);
1007 nrecvs = intersection.size();
1012 nrecvs *
sizeof(
Trhs), nrecvs);
1013 buf->resetReadPos();
1015 unpack(intersection, viewH, fd_m, nghostH, ldom1, row, col);
1020 if (requests.size() > 0) {
1021 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
1027 "Write Hessian on physical grid", hess_m.getFieldRangePolicy(),
1028 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
1029 const int ig2 = i + ldom2[0].first() - nghost2;
1030 const int jg2 = j + ldom2[1].first() - nghost2;
1031 const int kg2 = k + ldom2[2].first() - nghost2;
1033 const int ig = i + ldom1[0].first() - nghostH;
1034 const int jg = j + ldom1[1].first() - nghostH;
1035 const int kg = k + ldom1[2].first() - nghostH;
1038 const bool isQuadrant1 =
1039 ((ig == ig2) && (jg == jg2) && (kg == kg2));
1040 viewH(i, j, k)[row][col] = view2(i, j, k) * isQuadrant1;
1054 template <
typename FieldLHS,
typename FieldRHS>
1059 const int alg = this->params_m.template get<int>(
"algorithm");
1061 if (alg == Algorithm::VICO || alg == Algorithm::BIHARMONIC) {
1068 for (
unsigned int i = 0; i <
Dim; ++i) {
1069 hs_m[i] =
pi * 0.5 / l[i];
1070 L_sum = L_sum + l[i] * l[i];
1076 for (
unsigned int i = 0; i <
Dim; ++i) {
1077 origin[i] = -2 * nr_m[i] *
pi / l[i];
1081 mesh4_m->setMeshSpacing(hs_m);
1084 L_sum = std::sqrt(L_sum);
1086 L_sum = 1.1 * L_sum;
1090 const int nghost_g = grnL_m.getNghost();
1091 const auto& ldom_g = layout4_m->getLocalNDIndex();
1096 if (alg == Algorithm::VICO) {
1098 "Initialize Green's function ", grnL_m.getFieldRangePolicy(),
1099 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
1101 const int ig = i + ldom_g[0].first() - nghost_g;
1102 const int jg = j + ldom_g[1].first() - nghost_g;
1103 const int kg = k + ldom_g[2].first() - nghost_g;
1105 bool isOutside = (ig > 2 * size[0] - 1);
1106 const Tg t = ig * hs_m[0] + isOutside * origin[0];
1108 isOutside = (jg > 2 * size[1] - 1);
1109 const Tg u = jg * hs_m[1] + isOutside * origin[1];
1111 isOutside = (kg > 2 * size[2] - 1);
1112 const Tg v = kg * hs_m[2] + isOutside * origin[2];
1114 Tg s = (t * t) + (u * u) + (v * v);
1115 s = Kokkos::sqrt(s);
1120 const bool isOrig = ((ig == 0 && jg == 0 && kg == 0));
1121 const Tg analyticLim = -L_sum * L_sum * 0.5;
1122 const Tg value = -2.0 * (Kokkos::sin(0.5 * L_sum * s) / (s + isOrig * 1.0))
1123 * (Kokkos::sin(0.5 * L_sum * s) / (s + isOrig * 1.0));
1125 view_g(i, j, k) = (!isOrig) * value + isOrig * analyticLim;
1127 }
else if (alg == Algorithm::BIHARMONIC) {
1129 "Initialize Green's function ", grnL_m.getFieldRangePolicy(),
1130 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
1132 const int ig = i + ldom_g[0].first() - nghost_g;
1133 const int jg = j + ldom_g[1].first() - nghost_g;
1134 const int kg = k + ldom_g[2].first() - nghost_g;
1136 bool isOutside = (ig > 2 * size[0] - 1);
1137 const Tg t = ig * hs_m[0] + isOutside * origin[0];
1139 isOutside = (jg > 2 * size[1] - 1);
1140 const Tg u = jg * hs_m[1] + isOutside * origin[1];
1142 isOutside = (kg > 2 * size[2] - 1);
1143 const Tg v = kg * hs_m[2] + isOutside * origin[2];
1145 Tg s = (t * t) + (u * u) + (v * v);
1146 s = Kokkos::sqrt(s);
1149 const bool isOrig = ((ig == 0 && jg == 0 && kg == 0));
1150 const Tg analyticLim = -L_sum * L_sum * L_sum * L_sum / 8.0;
1151 const Tg value = -((2 - (L_sum * L_sum * s * s)) * Kokkos::cos(L_sum * s)
1152 + 2 * L_sum * s * Kokkos::sin(L_sum * s) - 2)
1153 / (2 * s * s * s * s + isOrig * 1.0);
1155 view_g(i, j, k) = (!isOrig) * value + isOrig * analyticLim;
1164 fft4n_m->transform(
BACKWARD, grnL_m);
1172 const int nghost = grn_mr.getNghost();
1173 const auto& ldom = layout2_m->getLocalNDIndex();
1180 const int ranks =
Comm->size();
1183 communicateVico(size, view_g, ldom_g, nghost_g, view, ldom, nghost);
1186 using mdrange_type = Kokkos::MDRangePolicy<Kokkos::Rank<3>>;
1188 "Restrict domain of Green's function from 4N to 2N",
1189 mdrange_type({nghost, nghost, nghost}, {view.extent(0) - nghost - size[0],
1190 view.extent(1) - nghost - size[1],
1191 view.extent(2) - nghost - size[2]}),
1192 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
1194 const int ig = i + ldom[0].first() - nghost;
1195 const int jg = j + ldom[1].first() - nghost;
1196 const int kg = k + ldom[2].first() - nghost;
1198 const int ig2 = i + ldom_g[0].first() - nghost_g;
1199 const int jg2 = j + ldom_g[1].first() - nghost_g;
1200 const int kg2 = k + ldom_g[2].first() - nghost_g;
1202 const bool isOrig = (ig == ig2) && (jg == jg2) && (kg == kg2);
1203 view(i, j, k) = isOrig * real(view_g(i, j, k));
1206 const int s = 2 * size[0] - ig - 1 - ldom_g[0].first() + nghost_g;
1207 const int p = 2 * size[1] - jg - 1 - ldom_g[1].first() + nghost_g;
1208 const int q = 2 * size[2] - kg - 1 - ldom_g[2].first() + nghost_g;
1210 view(s, j, k) = real(view_g(i + 1, j, k));
1211 view(i, p, k) = real(view_g(i, j + 1, k));
1212 view(i, j, q) = real(view_g(i, j, k + 1));
1213 view(s, j, q) = real(view_g(i + 1, j, k + 1));
1214 view(s, p, k) = real(view_g(i + 1, j + 1, k));
1215 view(i, p, q) = real(view_g(i, j + 1, k + 1));
1216 view(s, p, q) = real(view_g(i + 1, j + 1, k + 1));
1221 }
else if (alg == Algorithm::DCT_VICO) {
1228 for (
unsigned int i = 0; i <
Dim; ++i) {
1229 hs_m[i] = Kokkos::numbers::pi_v<Trhs> * 0.5 / l[i];
1230 L_sum = L_sum + l[i] * l[i];
1237 mesh2n1_m->setMeshSpacing(hs_m);
1240 L_sum = Kokkos::sqrt(L_sum);
1241 L_sum = 1.1 * L_sum;
1248 const int nghost_g2n1 = grn2n1_m.getNghost();
1249 const auto& ldom_g2n1 = layout2n1_m->getLocalNDIndex();
1252 "Initialize 2N+1 Green's function ", grn2n1_m.getFieldRangePolicy(),
1253 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
1255 const int ig = i + ldom_g2n1[0].first() - nghost_g2n1;
1256 const int jg = j + ldom_g2n1[1].first() - nghost_g2n1;
1257 const int kg = k + ldom_g2n1[2].first() - nghost_g2n1;
1259 double t = ig * hs_m[0];
1260 double u = jg * hs_m[1];
1261 double v = kg * hs_m[2];
1263 double s = (t * t) + (u * u) + (v * v);
1264 s = Kokkos::sqrt(s);
1266 const bool isOrig = ((ig == 0 && jg == 0 && kg == 0));
1267 const double val = -2.0 * (Kokkos::sin(0.5 * L_sum * s) / (s + isOrig * 1.0))
1268 * (Kokkos::sin(0.5 * L_sum * s) / (s + isOrig * 1.0));
1269 const double analyticLim = -L_sum * L_sum * 0.5;
1271 view_g2n1(i, j, k) = ((!isOrig) * val) + (isOrig * analyticLim);
1279 fft2n1_m->transform(
BACKWARD, grn2n1_m);
1287 const int nghost = grn_mr.getNghost();
1288 const auto& ldom = layout2_m->getLocalNDIndex();
1298 using mdrange_type = Kokkos::MDRangePolicy<Kokkos::Rank<3>>;
1301 communicateVico(size, view_g2n1, ldom_g2n1, nghost_g2n1, view, ldom, nghost);
1305 "Restrict domain of Green's function from 2N+1 to 2N",
1306 mdrange_type({nghost, nghost, nghost}, {view.extent(0) - nghost - size[0],
1307 view.extent(1) - nghost - size[1],
1308 view.extent(2) - nghost - size[2]}),
1309 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
1311 const int ig = i + ldom[0].first() - nghost;
1312 const int jg = j + ldom[1].first() - nghost;
1313 const int kg = k + ldom[2].first() - nghost;
1315 const int ig2 = i + ldom_g2n1[0].first() - nghost_g2n1;
1316 const int jg2 = j + ldom_g2n1[1].first() - nghost_g2n1;
1317 const int kg2 = k + ldom_g2n1[2].first() - nghost_g2n1;
1319 const bool isOrig = ((ig == ig2) && (jg == jg2) && (kg == kg2));
1320 view(i, j, k) = isOrig * view_g2n1(i, j, k);
1323 const int s = 2 * size[0] - ig - 1 - ldom_g2n1[0].first() + nghost_g2n1;
1324 const int p = 2 * size[1] - jg - 1 - ldom_g2n1[1].first() + nghost_g2n1;
1325 const int q = 2 * size[2] - kg - 1 - ldom_g2n1[2].first() + nghost_g2n1;
1327 view(s, j, k) = view_g2n1(i + 1, j, k);
1328 view(i, p, k) = view_g2n1(i, j + 1, k);
1329 view(i, j, q) = view_g2n1(i, j, k + 1);
1330 view(s, j, q) = view_g2n1(i + 1, j, k + 1);
1331 view(s, p, k) = view_g2n1(i + 1, j + 1, k);
1332 view(i, p, q) = view_g2n1(i, j + 1, k + 1);
1333 view(s, p, q) = view_g2n1(i + 1, j + 1, k + 1);
1344 for (
unsigned int i = 0; i <
Dim; ++i) {
1345 grn_mr = grn_mr + grnIField_m[i] * hrsq[i];
1348 grn_mr = -1.0 / (4.0 *
pi * sqrt(grn_mr));
1351 const int nghost = grn_mr.getNghost();
1352 const auto& ldom = layout2_m->getLocalNDIndex();
1356 "Regularize Green's function ", grn_mr.getFieldRangePolicy(),
1357 KOKKOS_LAMBDA(
const int i,
const int j,
const int k) {
1359 const int ig = i + ldom[0].first() - nghost;
1360 const int jg = j + ldom[1].first() - nghost;
1361 const int kg = k + ldom[2].first() - nghost;
1364 const bool isOrig = (ig == 0 && jg == 0 && kg == 0);
1365 view(i, j, k) = isOrig * (-1.0 / (4.0 *
pi)) + (!isOrig) * view(i, j, k);
1374 fft_m->transform(
FORWARD, grn_mr, grntr_m);
1379 template <
typename FieldLHS,
typename FieldRHS>
1384 const auto& lDomains2 = layout2_m->getHostLocalDomains();
1385 const auto& lDomains4 = layout4_m->getHostLocalDomains();
1387 std::vector<MPI_Request> requests(0);
1388 const int ranks =
Comm->size();
1392 for (
unsigned i = 0; i <
Dim; i++) {
1427 for (
unsigned i = 0; i <
Dim; i++) {
1432 for (
int i = 0; i < ranks; ++i) {
1433 auto domain2 = lDomains2[i];
1435 if (domain2.touches(none)) {
1436 auto intersection = domain2.intersect(none);
1438 if (ldom_g.
touches(intersection)) {
1439 intersection = intersection.intersect(ldom_g);
1446 if (domain2.touches(x)) {
1447 auto intersection = domain2.intersect(x);
1449 (2 * size[0] - intersection[0].last()), -1);
1453 domain4[1] = intersection[1];
1454 domain4[2] = intersection[2];
1456 if (ldom_g.
touches(domain4)) {
1457 intersection = ldom_g.
intersect(domain4);
1464 if (domain2.touches(y)) {
1465 auto intersection = domain2.intersect(y);
1467 (2 * size[1] - intersection[1].last()), -1);
1470 domain4[0] = intersection[0];
1472 domain4[2] = intersection[2];
1474 if (ldom_g.
touches(domain4)) {
1475 intersection = ldom_g.
intersect(domain4);
1482 if (domain2.touches(z)) {
1483 auto intersection = domain2.intersect(z);
1485 (2 * size[2] - intersection[2].last()), -1);
1488 domain4[0] = intersection[0];
1489 domain4[1] = intersection[1];
1492 if (ldom_g.
touches(domain4)) {
1493 intersection = ldom_g.
intersect(domain4);
1500 if (domain2.touches(xy)) {
1501 auto intersection = domain2.intersect(xy);
1503 (2 * size[0] - intersection[0].last()), -1);
1505 (2 * size[1] - intersection[1].last()), -1);
1510 domain4[2] = intersection[2];
1512 if (ldom_g.
touches(domain4)) {
1513 intersection = ldom_g.
intersect(domain4);
1520 if (domain2.touches(yz)) {
1521 auto intersection = domain2.intersect(yz);
1523 (2 * size[1] - intersection[1].last()), -1);
1525 (2 * size[2] - intersection[2].last()), -1);
1528 domain4[0] = intersection[0];
1532 if (ldom_g.
touches(domain4)) {
1533 intersection = ldom_g.
intersect(domain4);
1539 if (domain2.touches(xz)) {
1540 auto intersection = domain2.intersect(xz);
1542 (2 * size[0] - intersection[0].last()), -1);
1544 (2 * size[2] - intersection[2].last()), -1);
1548 domain4[1] = intersection[1];
1551 if (ldom_g.
touches(domain4)) {
1552 intersection = ldom_g.
intersect(domain4);
1558 if (domain2.touches(xyz)) {
1559 auto intersection = domain2.intersect(xyz);
1561 (2 * size[0] - intersection[0].last()), -1);
1563 (2 * size[1] - intersection[1].last()), -1);
1565 (2 * size[2] - intersection[2].last()), -1);
1572 if (ldom_g.
touches(domain4)) {
1573 intersection = ldom_g.
intersect(domain4);
1581 for (
int i = 0; i < ranks; ++i) {
1583 auto intersection = ldom.
intersect(none);
1585 if (lDomains4[i].touches(intersection)) {
1586 intersection = intersection.intersect(lDomains4[i]);
1597 (2 * size[0] - intersection[0].last()), -1);
1601 domain4[1] = intersection[1];
1602 domain4[2] = intersection[2];
1604 if (lDomains4[i].touches(domain4)) {
1605 domain4 = lDomains4[i].
intersect(domain4);
1607 2 * size[0] - domain4[0].last(), -1);
1609 intersection = intersection.intersect(domain4);
1612 true,
false,
false);
1620 (2 * size[1] - intersection[1].last()), -1);
1623 domain4[0] = intersection[0];
1625 domain4[2] = intersection[2];
1627 if (lDomains4[i].touches(domain4)) {
1628 domain4 = lDomains4[i].
intersect(domain4);
1630 2 * size[1] - domain4[1].last(), -1);
1632 intersection = intersection.intersect(domain4);
1635 false,
true,
false);
1643 (2 * size[2] - intersection[2].last()), -1);
1646 domain4[0] = intersection[0];
1647 domain4[1] = intersection[1];
1650 if (lDomains4[i].touches(domain4)) {
1651 domain4 = lDomains4[i].
intersect(domain4);
1653 2 * size[2] - domain4[2].last(), -1);
1655 intersection = intersection.intersect(domain4);
1658 false,
false,
true);
1666 (2 * size[0] - intersection[0].last()), -1);
1668 (2 * size[1] - intersection[1].last()), -1);
1673 domain4[2] = intersection[2];
1675 if (lDomains4[i].touches(domain4)) {
1676 domain4 = lDomains4[i].
intersect(domain4);
1678 2 * size[0] - domain4[0].last(), -1);
1680 2 * size[1] - domain4[1].last(), -1);
1682 intersection = intersection.intersect(domain4);
1693 (2 * size[1] - intersection[1].last()), -1);
1695 (2 * size[2] - intersection[2].last()), -1);
1698 domain4[0] = intersection[0];
1702 if (lDomains4[i].touches(domain4)) {
1703 domain4 = lDomains4[i].
intersect(domain4);
1705 2 * size[1] - domain4[1].last(), -1);
1707 2 * size[2] - domain4[2].last(), -1);
1709 intersection = intersection.intersect(domain4);
1720 (2 * size[0] - intersection[0].last()), -1);
1722 (2 * size[2] - intersection[2].last()), -1);
1726 domain4[1] = intersection[1];
1729 if (lDomains4[i].touches(domain4)) {
1730 domain4 = lDomains4[i].
intersect(domain4);
1732 2 * size[0] - domain4[0].last(), -1);
1734 2 * size[2] - domain4[2].last(), -1);
1736 intersection = intersection.intersect(domain4);
1744 auto intersection = ldom.
intersect(xyz);
1747 (2 * size[0] - intersection[0].last()), -1);
1749 (2 * size[1] - intersection[1].last()), -1);
1751 (2 * size[2] - intersection[2].last()), -1);
1758 if (lDomains4[i].touches(domain4)) {
1759 domain4 = lDomains4[i].
intersect(domain4);
1761 2 * size[0] - domain4[0].last(), -1);
1763 2 * size[1] - domain4[1].last(), -1);
1765 2 * size[2] - domain4[2].last(), -1);
1767 intersection = intersection.intersect(domain4);
1775 if (requests.size() > 0) {
1776 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
1782 template <
typename FieldLHS,
typename FieldRHS>
1787 const auto& lDomains2 = layout2_m->getHostLocalDomains();
1788 const auto& lDomains2n1 = layout2n1_m->getHostLocalDomains();
1790 std::vector<MPI_Request> requests(0);
1795 for (
unsigned i = 0; i <
Dim; i++) {
1830 for (
unsigned i = 0; i <
Dim; i++) {
1835 for (
int i = 0; i < ranks; ++i) {
1836 auto domain2 = lDomains2[i];
1838 if (domain2.touches(none)) {
1839 auto intersection = domain2.intersect(none);
1841 if (ldom_g.
touches(intersection)) {
1842 intersection = intersection.intersect(ldom_g);
1849 if (domain2.touches(x)) {
1850 auto intersection = domain2.intersect(x);
1852 (2 * size[0] - intersection[0].last()), -1);
1855 domain2n1[0] = xdom;
1856 domain2n1[1] = intersection[1];
1857 domain2n1[2] = intersection[2];
1859 if (ldom_g.
touches(domain2n1)) {
1860 intersection = ldom_g.
intersect(domain2n1);
1867 if (domain2.touches(y)) {
1868 auto intersection = domain2.intersect(y);
1870 (2 * size[1] - intersection[1].last()), -1);
1873 domain2n1[0] = intersection[0];
1874 domain2n1[1] = ydom;
1875 domain2n1[2] = intersection[2];
1877 if (ldom_g.
touches(domain2n1)) {
1878 intersection = ldom_g.
intersect(domain2n1);
1885 if (domain2.touches(z)) {
1886 auto intersection = domain2.intersect(z);
1888 (2 * size[2] - intersection[2].last()), -1);
1891 domain2n1[0] = intersection[0];
1892 domain2n1[1] = intersection[1];
1893 domain2n1[2] = zdom;
1895 if (ldom_g.
touches(domain2n1)) {
1896 intersection = ldom_g.
intersect(domain2n1);
1903 if (domain2.touches(xy)) {
1904 auto intersection = domain2.intersect(xy);
1906 (2 * size[0] - intersection[0].last()), -1);
1908 (2 * size[1] - intersection[1].last()), -1);
1911 domain2n1[0] = xdom;
1912 domain2n1[1] = ydom;
1913 domain2n1[2] = intersection[2];
1915 if (ldom_g.
touches(domain2n1)) {
1916 intersection = ldom_g.
intersect(domain2n1);
1923 if (domain2.touches(yz)) {
1924 auto intersection = domain2.intersect(yz);
1926 (2 * size[1] - intersection[1].last()), -1);
1928 (2 * size[2] - intersection[2].last()), -1);
1931 domain2n1[0] = intersection[0];
1932 domain2n1[1] = ydom;
1933 domain2n1[2] = zdom;
1935 if (ldom_g.
touches(domain2n1)) {
1936 intersection = ldom_g.
intersect(domain2n1);
1943 if (domain2.touches(xz)) {
1944 auto intersection = domain2.intersect(xz);
1946 (2 * size[0] - intersection[0].last()), -1);
1948 (2 * size[2] - intersection[2].last()), -1);
1951 domain2n1[0] = xdom;
1952 domain2n1[1] = intersection[1];
1953 domain2n1[2] = zdom;
1955 if (ldom_g.
touches(domain2n1)) {
1956 intersection = ldom_g.
intersect(domain2n1);
1963 if (domain2.touches(xyz)) {
1964 auto intersection = domain2.intersect(xyz);
1966 (2 * size[0] - intersection[0].last()), -1);
1968 (2 * size[1] - intersection[1].last()), -1);
1970 (2 * size[2] - intersection[2].last()), -1);
1973 domain2n1[0] = xdom;
1974 domain2n1[1] = ydom;
1975 domain2n1[2] = zdom;
1977 if (ldom_g.
touches(domain2n1)) {
1978 intersection = ldom_g.
intersect(domain2n1);
1987 for (
int i = 0; i < ranks; ++i) {
1989 auto intersection = ldom.
intersect(none);
1991 if (lDomains2n1[i].touches(intersection)) {
1992 intersection = intersection.intersect(lDomains2n1[i]);
2003 (2 * size[0] - intersection[0].last()), -1);
2006 domain2n1[0] = xdom;
2007 domain2n1[1] = intersection[1];
2008 domain2n1[2] = intersection[2];
2010 if (lDomains2n1[i].touches(domain2n1)) {
2011 domain2n1 = lDomains2n1[i].
intersect(domain2n1);
2013 2 * size[0] - domain2n1[0].last(), -1);
2015 intersection = intersection.intersect(domain2n1);
2018 true,
false,
false);
2026 (2 * size[1] - intersection[1].last()), -1);
2029 domain2n1[0] = intersection[0];
2030 domain2n1[1] = ydom;
2031 domain2n1[2] = intersection[2];
2033 if (lDomains2n1[i].touches(domain2n1)) {
2034 domain2n1 = lDomains2n1[i].
intersect(domain2n1);
2036 2 * size[1] - domain2n1[1].last(), -1);
2038 intersection = intersection.intersect(domain2n1);
2041 false,
true,
false);
2049 (2 * size[2] - intersection[2].last()), -1);
2052 domain2n1[0] = intersection[0];
2053 domain2n1[1] = intersection[1];
2054 domain2n1[2] = zdom;
2056 if (lDomains2n1[i].touches(domain2n1)) {
2057 domain2n1 = lDomains2n1[i].
intersect(domain2n1);
2059 2 * size[2] - domain2n1[2].last(), -1);
2061 intersection = intersection.intersect(domain2n1);
2064 false,
false,
true);
2072 (2 * size[0] - intersection[0].last()), -1);
2074 (2 * size[1] - intersection[1].last()), -1);
2077 domain2n1[0] = xdom;
2078 domain2n1[1] = ydom;
2079 domain2n1[2] = intersection[2];
2081 if (lDomains2n1[i].touches(domain2n1)) {
2082 domain2n1 = lDomains2n1[i].
intersect(domain2n1);
2084 2 * size[0] - domain2n1[0].last(), -1);
2086 2 * size[1] - domain2n1[1].last(), -1);
2088 intersection = intersection.intersect(domain2n1);
2099 (2 * size[1] - intersection[1].last()), -1);
2101 (2 * size[2] - intersection[2].last()), -1);
2104 domain2n1[0] = intersection[0];
2105 domain2n1[1] = ydom;
2106 domain2n1[2] = zdom;
2108 if (lDomains2n1[i].touches(domain2n1)) {
2109 domain2n1 = lDomains2n1[i].
intersect(domain2n1);
2111 2 * size[1] - domain2n1[1].last(), -1);
2113 2 * size[2] - domain2n1[2].last(), -1);
2115 intersection = intersection.intersect(domain2n1);
2126 (2 * size[0] - intersection[0].last()), -1);
2128 (2 * size[2] - intersection[2].last()), -1);
2131 domain2n1[0] = xdom;
2132 domain2n1[1] = intersection[1];
2133 domain2n1[2] = zdom;
2135 if (lDomains2n1[i].touches(domain2n1)) {
2136 domain2n1 = lDomains2n1[i].
intersect(domain2n1);
2138 2 * size[0] - domain2n1[0].last(), -1);
2140 2 * size[2] - domain2n1[2].last(), -1);
2142 intersection = intersection.intersect(domain2n1);
2150 auto intersection = ldom.
intersect(xyz);
2153 (2 * size[0] - intersection[0].last()), -1);
2155 (2 * size[1] - intersection[1].last()), -1);
2157 (2 * size[2] - intersection[2].last()), -1);
2160 domain2n1[0] = xdom;
2161 domain2n1[1] = ydom;
2162 domain2n1[2] = zdom;
2164 if (lDomains2n1[i].touches(domain2n1)) {
2165 domain2n1 = lDomains2n1[i].
intersect(domain2n1);
2167 2 * size[0] - domain2n1[0].last(), -1);
2169 2 * size[1] - domain2n1[1].last(), -1);
2171 2 * size[2] - domain2n1[2].last(), -1);
2173 intersection = intersection.intersect(domain2n1);
2181 if (requests.size() > 0) {
2182 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
ippl::FieldLayout< Dim > FieldLayout_t
ippl::UniformCartesian< double, 3 > Mesh_t
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
void solver_recv(int TAG, int id, int i, const ippl::NDIndex< Dim > intersection, const ippl::NDIndex< Dim > ldom, int nghost, Kokkos::View< Tf *** > &view, ippl::detail::FieldBufferData< Tb > &fd, bool x=false, bool y=false, bool z=false)
void unpack_impl(const ippl::NDIndex< 3 > intersect, const Kokkos::View< Tf *** > &view, ippl::detail::FieldBufferData< Tb > &fd, int nghost, const ippl::NDIndex< 3 > ldom, size_t dim1=0, size_t dim2=0, bool x=false, bool y=false, bool z=false)
void solver_send(int TAG, int id, int i, const ippl::NDIndex< Dim > intersection, const ippl::NDIndex< Dim > ldom, int nghost, Kokkos::View< Tf *** > &view, ippl::detail::FieldBufferData< Tb > &fd, std::vector< MPI_Request > &requests)
void unpack(const ippl::NDIndex< 3 > intersect, const Kokkos::View< Tf *** > &view, ippl::detail::FieldBufferData< Tb > &fd, int nghost, const ippl::NDIndex< 3 > ldom, bool x=false, bool y=false, bool z=false)
void pack(const ippl::NDIndex< 3 > intersect, Kokkos::View< Tf *** > &view, ippl::detail::FieldBufferData< Tb > &fd, int nghost, const ippl::NDIndex< 3 > ldom, ippl::mpi::Communicator::size_type &nsends)
constexpr KOKKOS_INLINE_FUNCTION auto first()
void solve(double *Matrix, double *Solution, double *rightHandSide, const int &M, const int &N)
Implementations for FFT constructor/destructor and transforms.
void initialize(int &argc, char *argv[], MPI_Comm comm)
detail::meta_hess< Field > hess(Field &u)
detail::meta_grad< Field > grad(Field &u)
void parallel_for(const std::string &name, const ExecPolicy &policy, const FunctorType &functor)
std::unique_ptr< mpi::Communicator > Comm
KOKKOS_INLINE_FUNCTION auto & get(Tuple< Ts... > &t)
Accessor function to get an element mutable reference at a specific index from a Tuple.
std::shared_ptr< archive_type< MemorySpace > > buffer_type
detail::size_type size_type
typename BareField_t::view_type view_type
KOKKOS_INLINE_FUNCTION bool touches(const NDIndex< Dim > &) const
KOKKOS_INLINE_FUNCTION Vector< int, Dim > last() const
KOKKOS_INLINE_FUNCTION unsigned size() const noexcept
KOKKOS_INLINE_FUNCTION Vector< int, Dim > first() const
KOKKOS_INLINE_FUNCTION NDIndex< Dim > intersect(const NDIndex< Dim > &) const
KOKKOS_INLINE_FUNCTION Vector< size_t, Dim > length() const
typename FieldLHS::value_type::value_type Tg
typename mesh_type::vector_type vector_type
typename FieldLHS::memory_space memory_space
typename FieldRHS::value_type Trhs
virtual void setDefaultParameters() override
typename FieldLHS::Mesh_t mesh_type
void setRhs(rhs_type &rhs) override
mpi::Communicator::buffer_type< memory_space > buffer_type
typename mesh_type::value_type scalar_type
void communicateVico(Vector< int, Dim > size, typename CxField_gt::view_type view_g, const ippl::NDIndex< Dim > ldom_g, const int nghost_g, typename Field_t::view_type view, const ippl::NDIndex< Dim > ldom, const int nghost)
void setLhs(lhs_type &lhs)
Timing::TimerRef TimerRef
static TimerRef getTimer(const char *nm)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)
void merge(const ParameterList &p) noexcept
void update(const ParameterList &p) noexcept