75 n_ =
static_cast<Index>(
A.invVol.size());
77 S_ = core::solver::HostCsrOp{};
81 S_.coef.assign(
A.coef.size(), 0.0);
82 S_.diag.assign(
static_cast<std::size_t
>(n_), 0.0);
83 identity_.assign(
static_cast<std::size_t
>(n_), 0);
87 for (
Index k =
A.start[
static_cast<std::size_t
>(
i)];
88 k <
A.start[
static_cast<std::size_t
>(
i) + 1]; ++k) {
89 S_.coef[
static_cast<std::size_t
>(k)] = -
A.coef[
static_cast<std::size_t
>(k)];
90 s +=
A.coef[
static_cast<std::size_t
>(k)];
92 S_.diag[
static_cast<std::size_t
>(
i)] =
s +
A.bcDiag[
static_cast<std::size_t
>(
i)];
93 if (S_.diag[
static_cast<std::size_t
>(
i)] <= 0.0) {
97 identity_[
static_cast<std::size_t
>(
i)] = 1;
98 S_.diag[
static_cast<std::size_t
>(
i)] = 1.0;
103 const core::solver::AmgParams
prm;
105 dIn_ =
View<double>(
"amgb_in",
static_cast<std::size_t
>(n_));
106 dOut_ =
View<double>(
"amgb_out",
static_cast<std::size_t
>(n_));
108 amgD_.build(S_,
prm);
113 r_.assign(
static_cast<std::size_t
>(n_), 0.0);
114 z_.assign(
static_cast<std::size_t
>(n_), 0.0);
115 p_.assign(
static_cast<std::size_t
>(n_), 0.0);
116 q_.assign(
static_cast<std::size_t
>(n_), 0.0);
117 rhs_.assign(
static_cast<std::size_t
>(n_), 0.0);
118 bHost_.assign(
static_cast<std::size_t
>(n_), 0.0);
119 xHost_.assign(
static_cast<std::size_t
>(n_), 0.0);
120 bMirror_ = Kokkos::View<double*, Kokkos::HostSpace>(
"amgb_b",
static_cast<std::size_t
>(n_));
121 xMirror_ = Kokkos::View<double*, Kokkos::HostSpace>(
"amgb_x",
static_cast<std::size_t
>(n_));
126 bool ready()
const {
return n_ > 0; }
159 void solveHost()
const {
160 Kokkos::deep_copy(bMirror_, dIn_);
162 bHost_[
static_cast<std::size_t
>(
i)] = bMirror_(
i);
163 std::fill(xHost_.begin(), xHost_.end(), 0.0);
165 rhs_[
static_cast<std::size_t
>(
i)] =
166 identity_[
static_cast<std::size_t
>(
i)]
173 bnorm = std::max(
bnorm, std::fabs(rhs_[
static_cast<std::size_t
>(
i)]));
177 const double rnorm0 = norm2(r_);
179 for (
int it = 0;
it < kMaxIters; ++
it) {
186 const double beta =
rz /
rzOld;
188 p_[
static_cast<std::size_t
>(
i)] =
189 z_[
static_cast<std::size_t
>(
i)] + beta * p_[
static_cast<std::size_t
>(
i)];
192 const double pq = dot(p_, q_);
193 if (!(std::fabs(
pq) > 0.0))
195 const double alpha =
rz /
pq;
197 xHost_[
static_cast<std::size_t
>(
i)] += alpha * p_[
static_cast<std::size_t
>(
i)];
198 r_[
static_cast<std::size_t
>(
i)] -= alpha * q_[
static_cast<std::size_t
>(
i)];
202 if (norm2(r_) <= kTol *
rnorm0)
207 if (identity_[
static_cast<std::size_t
>(
i)])
208 xHost_[
static_cast<std::size_t
>(
i)] = 0.0;
209 S_.apply(xHost_, q_);
213 e, std::fabs(rhs_[
static_cast<std::size_t
>(
i)] - q_[
static_cast<std::size_t
>(
i)]));
217 xMirror_(
i) = xHost_[
static_cast<std::size_t
>(
i)];
218 Kokkos::deep_copy(dOut_, xMirror_);
221 static double dot(
const std::vector<double>&
a,
const std::vector<double>& b) {
223 for (std::size_t
i = 0;
i <
a.size(); ++
i)
227 static double norm2(
const std::vector<double>&
a) {
return std::sqrt(dot(
a,
a)); }
231 void project(std::vector<double>&
v)
const {
232 if (!singular_ || nComp_ == 0)
234 std::vector<double> sum(
static_cast<std::size_t
>(nComp_), 0.0);
236 const Index c = comp_[
static_cast<std::size_t
>(
i)];
238 sum[
static_cast<std::size_t
>(
c)] +=
v[
static_cast<std::size_t
>(
i)];
240 for (
int c = 0;
c < nComp_; ++
c)
241 sum[
static_cast<std::size_t
>(
c)] /=
242 static_cast<double>(compSize_[
static_cast<std::size_t
>(
c)]);
244 const Index c = comp_[
static_cast<std::size_t
>(
i)];
246 v[
static_cast<std::size_t
>(
i)] -= sum[
static_cast<std::size_t
>(
c)];
251 void uploadDevice(
const typename Poisson::FvAssembled&
A) {
252 dDiag_ =
toDevice(S_.diag,
"amgb_diag");
253 dStart_ =
toDevice(S_.start,
"amgb_start");
254 dNbr_ =
toDevice(S_.nbr,
"amgb_nbr");
255 dCoef_ =
toDevice(S_.coef,
"amgb_coef");
256 dInvVol_ =
toDevice(
A.invVol,
"amgb_invvol");
257 dComp_ =
toDevice(comp_,
"amgb_comp");
258 std::vector<double>
ident(
static_cast<std::size_t
>(n_), 0.0);
260 ident[
static_cast<std::size_t
>(
i)] = identity_[
static_cast<std::size_t
>(
i)] ? 1.0 : 0.0;
262 const std::size_t
nn =
static_cast<std::size_t
>(n_);
273 if (!singular_ || nComp_ == 0)
276 for (
int c = 0;
c < nComp_; ++
c) {
278 Kokkos::parallel_reduce(
279 "amr::amgb_proj_sum", n_,
285 const double m =
s /
static_cast<double>(compSize_[
static_cast<std::size_t
>(
c)]);
286 Kokkos::parallel_for(
296 auto start = dStart_;
299 Kokkos::parallel_for(
301 double s = diag(
i) *
in(
i);
302 for (
Index k = start(
i); k < start(
i + 1); ++k)
303 s += coef(k) *
in(nbr(k));
310 Kokkos::parallel_reduce(
316 Kokkos::parallel_reduce(
317 "amr::amgb_maxabs", n,
319 const double v =
a(
i) < 0.0 ? -
a(
i) :
a(
i);
323 Kokkos::Max<double>(m));
327 void solveDevice()
const {
329 auto invVol = dInvVol_;
330 auto ident = dIdent_;
333 Kokkos::parallel_for(
336 projectDevice(dRhs_);
337 Kokkos::deep_copy(x, 0.0);
338 Kokkos::deep_copy(dR_, dRhs_);
346 for (
int it = 0;
it < kMaxIters; ++
it) {
347 amgD_.apply(dR_, dZ_);
351 Kokkos::deep_copy(dP_, dZ_);
353 const double beta =
rz /
rzOld;
356 Kokkos::parallel_for(
361 if (!(std::fabs(
pq) > 0.0))
363 const double alpha =
rz /
pq;
367 Kokkos::parallel_for(
369 x(
i) += alpha *
p(
i);
370 r(
i) -= alpha *
q(
i);
379 Kokkos::parallel_for(
388 Kokkos::parallel_reduce(
389 "amr::amgb_resid", n_,
391 const double v =
rr(
i) -
q(
i);
392 const double av =
v < 0.0 ? -
v :
v;
396 Kokkos::Max<double>(
e));
406 void buildComponents(
const typename Poisson::FvAssembled&
A) {
407 parent_.resize(
static_cast<std::size_t
>(n_));
409 parent_[
static_cast<std::size_t
>(
i)] =
i;
411 if (identity_[
static_cast<std::size_t
>(
i)])
413 for (
Index k =
A.start[
static_cast<std::size_t
>(
i)];
414 k <
A.start[
static_cast<std::size_t
>(
i) + 1]; ++k) {
415 if (!(
A.coef[
static_cast<std::size_t
>(k)] > 0.0))
417 const Index j =
A.nbr[
static_cast<std::size_t
>(k)];
418 if (
j < 0 || j >= n_ || identity_[
static_cast<std::size_t
>(
j)])
423 comp_.assign(
static_cast<std::size_t
>(n_), -1);
425 std::vector<Index>
label(
static_cast<std::size_t
>(n_), -1);
427 if (identity_[
static_cast<std::size_t
>(
i)])
430 if (
label[
static_cast<std::size_t
>(
r)] < 0)
431 label[
static_cast<std::size_t
>(
r)] = nComp_++;
432 comp_[
static_cast<std::size_t
>(
i)] =
label[
static_cast<std::size_t
>(
r)];
434 compSize_.assign(
static_cast<std::size_t
>(nComp_), 0);
436 if (comp_[
static_cast<std::size_t
>(
i)] >= 0)
437 ++compSize_[
static_cast<std::size_t
>(comp_[
static_cast<std::size_t
>(
i)])];
441 while (parent_[
static_cast<std::size_t
>(
i)] !=
i) {
442 parent_[
static_cast<std::size_t
>(
i)] =
443 parent_[
static_cast<std::size_t
>(parent_[
static_cast<std::size_t
>(
i)])];
444 i = parent_[
static_cast<std::size_t
>(
i)];
451 parent_[
static_cast<std::size_t
>(
ra)] =
rb;
462 static constexpr double kTol = 1
e-10;
463 static constexpr int kMaxIters = 100;
465 Index n_ = 0, nIdentity_ = 0;
466 bool singular_ =
true, onDevice_ =
false;
468 core::solver::HostCsrOp S_;
469 core::solver::GraphAMG amg_;
470 core::solver::GraphAMGDevice amgD_;
471 std::vector<double> invVol_;
472 std::vector<char> identity_;
473 mutable std::vector<Index> parent_;
474 std::vector<Index> comp_, compSize_;
475 mutable std::vector<double> r_, z_, p_, q_, rhs_, bHost_, xHost_;
476 mutable Kokkos::View<double*, Kokkos::HostSpace> bMirror_, xMirror_;
479 mutable View<double> dR_, dZ_, dP_, dQ_, dRhs_, dIn_, dOut_;
480 mutable int lastIters_ = 0;
481 mutable double lastRel_ = 0.0;
std::vector< std::array< double, Dim > > transferFieldGradients(const BlockOctree< Dim, Bits > &oldT, const std::vector< double > &oldF)
Per-old-leaf minmod prolongation gradients (per fine-coordinate unit) — transferField's stencil,...