34 #include <AMReX_ParallelDescriptor.H>
36 #include <boost/filesystem.hpp>
43 const std::string& bsolver,
44 const std::string& prec,
45 const bool& rebalance,
46 const std::string& reuse,
47 const std::string& bcx,
48 const std::string& bcy,
49 const std::string& bcz,
50 const std::string& smoother,
51 const std::size_t& nSweeps,
52 const std::string& interp,
53 const std::string& norm)
55 , comm_mp( new
comm_t( amrex::ParallelDescriptor::Communicator() ) )
68 , fname_m(
OpalData::getInstance()->getInputBasename() +
std::string(
".solver"))
69 , flag_m(
std::ios::out)
75 const Boundary bcs[AMREX_SPACEDIM] = {
101 if (boost::filesystem::exists(
fname_m)) {
113 unsigned short baseLevel,
114 unsigned short finestLevel,
126 bool reset = !prevAsGuess;
141 for (
int lev =
nlevel_m - 1; lev > -1; --lev) {
149 for (
int lev = 0; lev <
nlevel_m; ++lev) {
152 phi[ilev]->setVal(0.0, phi[ilev]->nGrow());
172 throw OpalException(
"AmrMultiGrid::setMaxNumberOfIterations()",
173 "The max. number of iterations needs to be positive!");
204 for (
unsigned int i = 0; i < AMREX_SPACEDIM; ++i) {
206 case Boundary::DIRICHLET:
212 case Boundary::PERIODIC:
216 throw OpalException(
"AmrMultiGrid::initPhysicalBoundary_m()",
217 "This type of boundary is not supported");
220 go_t tmp =
bc_m[i]->getNumberOfPoints();
228 const amrex::Vector<AmrGeometry_t>& geom,
241 amrex::Periodicity period(
AmrIntVect_t(D_DECL(0, 0, 0)));
245 for (
int lev = 0; lev <
nlevel_m; ++lev) {
251 rho[ilev]->boxArray(),
252 rho[ilev]->DistributionMap(),
265 mglevel_m[lev]->refmask->setVal(AmrMultiGridLevel_t::Refined::NO, 2);
266 mglevel_m[lev]->refmask->FillBoundary(period);
268 amrex::BoxArray ba =
mglevel_m[lev]->grids;
274 mglevel_m[lev]->crsemask->setVal(AmrMultiGridLevel_t::Refined::NO, 2);
277 for (
int lev = 1; lev <
nlevel_m; ++lev) {
278 mglevel_m[lev]->crsemask->setVal(AmrMultiGridLevel_t::Refined::YES, 0);
281 mglevel_m[lev]->crsemask->setDomainBndry(AmrMultiGridLevel_t::Mask::PHYSBNDRY,
284 mglevel_m[lev]->crsemask->FillBoundary(period);
290 for (
int lev = 0; lev <
nlevel_m-1; ++lev) {
292 amrex::BoxArray ba =
mglevel_m[lev]->grids;
294 ba = amrex::intersect(
mglevel_m[lev+1]->grids, ba);
298 amrex::DistributionMapping dmap(ba,
comm_mp->getSize());
300 refined.setVal(AmrMultiGridLevel_t::Refined::YES);
304 mglevel_m[lev]->refmask->copy(refined, 0, 0, 1, 0, 2);
309 mglevel_m[lev]->refmask->setDomainBndry(AmrMultiGridLevel_t::Mask::PHYSBNDRY,
312 mglevel_m[lev]->refmask->FillBoundary(period);
318 for (
int lev = 0; lev <
nlevel_m; ++lev) {
331 for (
int lev = 0; lev <
nlevel_m; ++lev)
339 std::vector<scalar_t> rhsNorms;
340 std::vector<scalar_t> resNorms;
345 [
this](
double& val){ val *= eps_m; });
364 for (
int lev = 0; lev <
nlevel_m; ++lev) {
379 this->writeResidualNorm_m();
385 return std::accumulate(resNorms.begin(),
387 std::plus<scalar_t>());
392 std::vector<scalar_t>& resNorms)
394 return std::equal(resNorms.begin(), resNorms.end(),
396 std::less<scalar_t>());
401 Teuchos::RCP<vector_t>& r,
402 const Teuchos::RCP<vector_t>& b,
403 const Teuchos::RCP<vector_t>& x)
413 if (
mglevel_m[level]->Bfine_p != Teuchos::null ) {
418 mglevel_m[level]->Awf_p->apply(*x, fine2crse,
423 if (
mglevel_m[level]->Bcrse_p != Teuchos::null ) {
432 Teuchos::RCP<vector_t> uncov_Ax = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
433 mglevel_m[level]->UnCovered_p->apply(fine2crse, *uncov_Ax);
435 Teuchos::RCP<vector_t> uncov_b = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
437 mglevel_m[level]->UnCovered_p->apply(*b, *uncov_b);
442 r->update(1.0, *uncov_b, -1.0, *uncov_Ax, 0.0);
447 Teuchos::RCP<vector_t> Ax = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
450 if (
mglevel_m[level]->Bcrse_p != Teuchos::null ) {
458 r->update(1.0, *b, -1.0, *Ax, 0.0);
470 Teuchos::RCP<vector_t> Ax = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
485 Teuchos::RCP<vector_t> phi_save = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p) );
486 Tpetra::deep_copy(*phi_save, *
mglevel_m[level]->phi_p);
488 mglevel_m[level-1]->error_p->putScalar(0.0);
512 Teuchos::RCP<vector_t> tmp = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p) );
518 Tpetra::deep_copy(*
mglevel_m[level]->residual_p, *tmp);
521 Teuchos::RCP<vector_t> derror = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
527 mglevel_m[level]->error_p->update(1.0, *derror, 1.0);
530 mglevel_m[level]->phi_p->update(1.0, *phi_save, 1.0, *
mglevel_m[level]->error_p, 0.0);
551 Teuchos::RCP<vector_t>& result,
552 const Teuchos::RCP<vector_t>& rhs,
553 const Teuchos::RCP<vector_t>& crs_rhs,
554 const Teuchos::RCP<vector_t>& b)
559 if (
mglevel_m[level]->Bcrse_p != Teuchos::null ) {
560 mglevel_m[level]->Bcrse_p->apply(*crs_rhs, crse2fine);
564 mglevel_m[level]->Anf_p->apply(*rhs, crse2fine,
569 result->update(1.0, *b, -1.0, crse2fine, 0.0);
574 void AmrMultiGrid::writeResidualNorm_m() {
579 out.open(
"residual.dat", std::ios::app);
581 for (
int lev = 0; lev <
nlevel_m; ++lev) {
585 out << std::setw(15) << std::right << tmp;
617 "This type of norm not suppported.");
624 std::vector<scalar_t>& resNorms)
632 if (
comm_mp->getRank() == 0) {
633 out.open(
"residual.dat", std::ios::out);
635 for (
int lev = 0; lev <
nlevel_m; ++lev)
636 out << std::setw(14) << std::right <<
"level" << lev;
641 for (
int lev = 0; lev <
nlevel_m; ++lev) {
651 out << std::setw(15) << std::right << resNorms.back();
668 Teuchos::RCP<vector_t> efield_p = Teuchos::null;
669 for (
int lev =
nlevel_m - 1; lev > -1; --lev) {
675 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
676 efield[ilev][d]->setVal(0.0, efield[ilev][d]->nGrow());
677 efield_p->putScalar(0.0);
689 const amrex::Vector<AmrField_u>& phi,
690 const bool& matrices)
718 const amrex::Vector<AmrField_u>& phi,
719 const bool& matrices)
726 D_DECL( invdx[0] * invdx[0],
728 invdx[2] * invdx[2] )
733 mfi.isValid(); ++mfi)
735 const box_t& tbx = mfi.tilebox();
740 const int* lo = tbx.loVect();
741 const int* hi = tbx.hiVect();
743 for (
int i = lo[0]; i <= hi[0]; ++i) {
744 for (
int j = lo[1]; j <= hi[1]; ++j) {
745 #if AMREX_SPACEDIM == 3
746 for (
int k = lo[2]; k <= hi[2]; ++k) {
759 #if AMREX_SPACEDIM == 3
779 const amrex::Vector<AmrField_u>& phi,
780 const bool& matrices)
791 for (
int lev = 0; lev <
nlevel_m; ++lev) {
792 this->
open_m(lev, matrices);
802 D_DECL( invdx[0] * invdx[0],
804 invdx[2] * invdx[2] )
808 for (amrex::MFIter mfi(*
mglevel_m[lev]->mask,
true);
809 mfi.isValid(); ++mfi)
811 const box_t& tbx = mfi.tilebox();
818 const int* lo = tbx.loVect();
819 const int* hi = tbx.hiVect();
821 for (
int i = lo[0]; i <= hi[0]; ++i) {
823 for (
int j = lo[1]; j <= hi[1]; ++j) {
825 #if AMREX_SPACEDIM == 3
826 for (
int k = lo[2]; k <= hi[2]; ++k) {
833 D_DECL(ii, jj, kk), rfab);
851 mglevel_m[lev]->rho_p->replaceGlobalValue(gidx, rhofab(iv, 0));
852 mglevel_m[lev]->phi_p->replaceGlobalValue(gidx, pfab(iv, 0));
853 #if AMREX_SPACEDIM == 3
868 if ( matrices && lev >
lbase_m ) {
877 const bool& matrices)
891 Tpetra::StaticProfile) );
900 mglevel_m[level]->Bcrse_p = Teuchos::rcp(
902 Tpetra::StaticProfile) );
914 int nNeighbours = AMREX_D_TERM(2, * 2, * 2);
918 Tpetra::StaticProfile) );
925 nNeighbours = 2 * AMREX_SPACEDIM * AMREX_D_TERM(2, * 2, * 2);
927 mglevel_m[level]->Bfine_p = Teuchos::rcp(
929 Tpetra::StaticProfile) );
937 int nPhysBoundary = 2 * AMREX_SPACEDIM *
nBcPoints_m;
940 int nIntBoundary = AMREX_SPACEDIM *
interface_mp->getNumberOfPoints();
942 int nEntries = (AMREX_SPACEDIM << 1) + 2 + nPhysBoundary + nIntBoundary;
947 Tpetra::StaticProfile) );
954 nEntries = (AMREX_SPACEDIM << 1) + 5 + nPhysBoundary + nIntBoundary;
958 Tpetra::StaticProfile) );
963 mglevel_m[level]->UnCovered_p = Teuchos::rcp(
965 Tpetra::StaticProfile) );
974 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
977 Tpetra::StaticProfile) );
993 const bool& matrices)
1015 mglevel_m[level]->Anf_p->fillComplete();
1017 for (
int d = 0; d < AMREX_SPACEDIM; ++d)
1018 mglevel_m[level]->G_p[d]->fillComplete();
1022 mglevel_m[level]->Awf_p->fillComplete();
1024 mglevel_m[level]->UnCovered_p->fillComplete();
1053 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1054 for (
int shift = -1; shift <= 1; shift += 2) {
1058 switch ( mfab(biv) )
1060 case AmrMultiGridLevel_t::Mask::INTERIOR:
1061 case AmrMultiGridLevel_t::Mask::COVERED:
1063 map[
mglevel_m[level]->serialize(biv)] += invdx2[d];
1066 case AmrMultiGridLevel_t::Mask::BNDRY:
1072 throw OpalException(
"AmrMultiGrid::buildNoFinePoissonMatrix_m()",
1073 "Error in mask for level "
1074 + std::to_string(level) +
"!");
1082 case AmrMultiGridLevel_t::Mask::PHYSBNDRY:
1085 mglevel_m[level]->applyBoundary(biv, d, map,
1090 throw OpalException(
"AmrMultiGrid::buildNoFinePoissonMatrix_m()",
1091 "Error in mask for level "
1092 + std::to_string(level) +
"!");
1098 map[gidx] += AMREX_D_TERM(- 2.0 * invdx2[0],
1104 mglevel_m[level]->Anf_p->insertGlobalValues(gidx,
1123 if ( rfab(iv) == AmrMultiGridLevel_t::Refined::YES )
1146 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1147 for (
int shift = -1; shift <= 1; shift += 2) {
1151 if ( rfab(biv) != AmrMultiGridLevel_t::Refined::YES )
1156 switch ( mfab(biv) )
1158 case AmrMultiGridLevel_t::Mask::COVERED:
1160 case AmrMultiGridLevel_t::Mask::INTERIOR:
1162 map[
mglevel_m[level]->serialize(biv)] += invdx2[d];
1163 map[gidx] -= invdx2[d];
1166 case AmrMultiGridLevel_t::Mask::BNDRY:
1172 throw OpalException(
"AmrMultiGrid::buildCompositePoissonMatrix_m()",
1173 "Error in mask for level "
1174 + std::to_string(level) +
"!");
1189 map[gidx] -= invdx2[d];
1192 case AmrMultiGridLevel_t::Mask::PHYSBNDRY:
1195 mglevel_m[level]->applyBoundary(biv, d, map,
1199 map[gidx] -= invdx2[d];
1203 throw OpalException(
"AmrMultiGrid::buildCompositePoissonMatrix_m()",
1204 "Error in mask for level "
1205 + std::to_string(level) +
"!");
1226 scalar_t invavg = AMREX_D_PICK(1.0, 0.5, 0.25);
1227 scalar_t value = - invavg * invcdx[d] * invfdx[d];
1229 for (
int d1 = 0; d1 < 2; ++d1) {
1230 #if AMREX_SPACEDIM == 3
1231 for (
int d2 = 0; d2 < 2; ++d2) {
1239 fake[(d+1)%AMREX_SPACEDIM] = d1;
1240 #if AMREX_SPACEDIM == 3
1241 fake[(d+2)%AMREX_SPACEDIM] = d2;
1246 #if AMREX_SPACEDIM == 3
1256 mglevel_m[level]->Awf_p->insertGlobalValues(gidx,
1262 mglevel_m[level]->UnCovered_p->insertGlobalValues(gidx,
1272 D_DECL(
const go_t& ii,
1282 if ( rfab(iv) == AmrMultiGridLevel_t::Refined::NO || level ==
lfine_m )
1294 indices.reserve(2 << (AMREX_SPACEDIM - 1));
1296 values.reserve(2 << (AMREX_SPACEDIM -1));
1299 for (
int iref = 0; iref < 2; ++iref) {
1300 for (
int jref = 0; jref < 2; ++jref) {
1301 #if AMREX_SPACEDIM == 3
1302 for (
int kref = 0; kref < 2; ++kref) {
1304 AmrIntVect_t riv(D_DECL(ii + iref, jj + jref, kk + kref));
1307 values.push_back( AMREX_D_PICK(0.5, 0.25, 0.125) );
1308 #if AMREX_SPACEDIM == 3
1314 mglevel_m[level]->R_p->insertGlobalValues(gidx,
1351 mglevel_m[level]->I_p->insertGlobalValues(gidx,
1381 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1382 for (
int shift = -1; shift <= 1; shift += 2) {
1387 if ( mfab(niv) == AmrMultiGridLevel_t::Mask::BNDRY )
1395 civ.coarsen(
mglevel_m[level]->refinement());
1401 interface_mp->coarse(civ, map, invdx2[d], d, shift, cfab,
1405 else if ( mfab(niv) == AmrMultiGridLevel_t::Mask::PHYSBNDRY ) {
1406 throw OpalException(
"AmrMultiGrid::buildCrseBoundaryMatrix_m()",
1407 "Fine meshes shouldn't be connected "
1408 "to physical (i.e. mesh) boundary!");
1416 mglevel_m[level]->Bcrse_p->insertGlobalValues(gidx,
1434 if ( rfab(iv) == AmrMultiGridLevel_t::Refined::YES || level ==
lfine_m )
1441 scalar_t invavg = AMREX_D_PICK(1, 0.5, 0.25);
1447 auto fill = [&](
umap_t& map,
1448 D_DECL(
int ii,
int jj,
int kk),
1452 for (
int iref = ii -
begin[0]; iref <= ii +
end[0]; ++iref) {
1453 for (
int jref = jj -
begin[1]; jref <= jj +
end[1]; ++jref) {
1454 #if AMREX_SPACEDIM == 3
1455 for (
int kref = kk -
begin[2]; kref <= kk +
end[2]; ++kref) {
1462 if ( (riv[d] >> 1) == iv[d] ) {
1466 scalar_t value = - invavg * invcdx[d] * invfdx[d];
1471 scalar_t value = invavg * invcdx[d] * invfdx[d];
1472 map[
mglevel_m[level+1]->serialize(riv)] += value;
1474 #if AMREX_SPACEDIM == 3
1488 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1489 for (
int shift = -1; shift <= 1; shift += 2) {
1492 covered[d] += shift;
1494 if ( rfab(covered) == AmrMultiGridLevel_t::Refined::YES &&
1509 int begin[AMREX_SPACEDIM] = { D_DECL(
int(d == 0),
int(d == 1),
int(d == 2) ) };
1510 int end[AMREX_SPACEDIM] = { D_DECL(
int(d != 0),
int(d != 1),
int(d != 2) ) };
1525 int ii = iv[0] << 1;
1526 int jj = iv[1] << 1;
1527 #if AMREX_SPACEDIM == 3
1528 int kk = iv[2] << 1;
1533 fill(map, D_DECL(ii, jj, kk), &
begin[0], &
end[0], d, iv, shift);
1540 int ii = covered[0] << 1;
1541 int jj = covered[1] << 1;
1542 #if AMREX_SPACEDIM == 3
1543 int kk = covered[2] << 1;
1545 fill(map, D_DECL(ii, jj, kk), &
begin[0], &
end[0], d, iv, shift);
1557 mglevel_m[level]->Bfine_p->insertGlobalValues(gidx,
1595 case AmrMultiGridLevel_t::Mask::INTERIOR:
1597 case AmrMultiGridLevel_t::Mask::COVERED:
1599 map[
mglevel_m[level]->serialize(iv)] -= shift * 0.5 * invdx[dir];
1601 case AmrMultiGridLevel_t::Mask::BNDRY:
1606 throw OpalException(
"AmrMultiGrid::buildGradientMatrix_m()",
1607 "Error in mask for level "
1608 + std::to_string(level) +
"!");
1611 scalar_t value = - shift * 0.5 * invdx[dir];
1617 map[
mglevel_m[level]->serialize(tmp)] += 2.0 * value;
1621 map[
mglevel_m[level]->serialize(tmp)] -= value;
1624 case AmrMultiGridLevel_t::Mask::PHYSBNDRY:
1628 scalar_t value = - shift * 0.5 * invdx[dir];
1630 mglevel_m[level]->applyBoundary(iv, dir,
1639 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1640 for (
int shift = -1; shift <= 1; shift += 2) {
1643 check(niv, mfab, d, shift);
1648 mglevel_m[level]->G_p[d]->insertGlobalValues(gidx,
1659 Teuchos::RCP<vector_t>& mv)
1664 for (amrex::MFIter mfi(mf,
true); mfi.isValid(); ++mfi) {
1665 const amrex::Box& tbx = mfi.tilebox();
1666 const amrex::FArrayBox& fab = mf[mfi];
1668 const int* lo = tbx.loVect();
1669 const int* hi = tbx.hiVect();
1671 for (
int i = lo[0]; i <= hi[0]; ++i) {
1672 for (
int j = lo[1]; j <= hi[1]; ++j) {
1673 #if AMREX_SPACEDIM == 3
1674 for (
int k = lo[2]; k <= hi[2]; ++k) {
1680 mv->replaceGlobalValue(gidx, fab(iv, comp));
1681 #if AMREX_SPACEDIM == 3
1693 const Teuchos::RCP<vector_t>& mv)
1695 Teuchos::ArrayRCP<const amr::scalar_t> data = mv->get1dView();
1697 for (amrex::MFIter mfi(mf,
true); mfi.isValid(); ++mfi) {
1698 const amrex::Box& tbx = mfi.tilebox();
1699 amrex::FArrayBox& fab = mf[mfi];
1701 const int* lo = tbx.loVect();
1702 const int* hi = tbx.hiVect();
1704 for (
int i = lo[0]; i <= hi[0]; ++i) {
1705 for (
int j = lo[1]; j <= hi[1]; ++j) {
1706 #if AMREX_SPACEDIM == 3
1707 for (
int k = lo[2]; k <= hi[2]; ++k) {
1714 fab(iv, comp) = data[lidx];
1716 #if AMREX_SPACEDIM == 3
1731 indices.reserve(map.size());
1732 values.reserve(map.size());
1735 [&](
const std::pair<const go_t, scalar_t>& entry)
1738 if ( entry.first < 0 ) {
1739 throw OpalException(
"AmrMultiGrid::map2vector_m()",
1740 "Negative matrix index!");
1744 indices.push_back(entry.first);
1745 values.push_back(entry.second);
1754 Teuchos::RCP<vector_t>&
e,
1755 Teuchos::RCP<vector_t>& r)
1776 Teuchos::RCP<vector_t> tmp = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p) );
1783 mglevel_m[level-1]->residual_p->putScalar(0.0);
1799 fine2crse, Teuchos::NO_TRANS,
1802 if (
mglevel_m[level-1]->Bcrse_p != Teuchos::null ) {
1805 fine2crse, Teuchos::NO_TRANS,
1809 Teuchos::RCP<vector_t> uncoveredRho = Teuchos::rcp(
new vector_t(
mglevel_m[level-1]->map_p,
true) );
1815 Teuchos::RCP<vector_t> tmp2 = Teuchos::rcp(
new vector_t(
mglevel_m[level-1]->map_p,
true) );
1816 mglevel_m[level-1]->UnCovered_p->apply(fine2crse, *tmp2);
1819 mglevel_m[level-1]->residual_p->update(1.0, *uncoveredRho, -1.0, *tmp2, 1.0);
1851 Teuchos::RCP<vector_t> phicrse = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
false) );
1856 Teuchos::RCP<vector_t> uncov_phi = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
1860 mglevel_m[level]->phi_p->update(1.0, *phicrse, 1.0, *uncov_phi, 0.0);
1869 case Interpolater::TRILINEAR:
1872 case Interpolater::LAGRANGE:
1874 "Not yet implemented.");
1875 case Interpolater::PIECEWISE_CONST:
1880 "No such interpolater available.");
1886 switch ( interface ) {
1887 case Interpolater::TRILINEAR:
1890 case Interpolater::LAGRANGE:
1894 case Interpolater::PIECEWISE_CONST:
1899 "No such interpolater for the coarse-fine interface available.");
1905 const bool& rebalance,
1906 const std::string& reuse)
1910 case BaseSolver::BICGSTAB:
1913 case BaseSolver::MINRES:
1916 case BaseSolver::PCPG:
1919 case BaseSolver::CG:
1922 case BaseSolver::GMRES:
1925 case BaseSolver::STOCHASTIC_CG:
1928 case BaseSolver::RECYCLING_CG:
1931 case BaseSolver::RECYCLING_GMRES:
1935 #ifdef HAVE_AMESOS2_KLU2
1936 case BaseSolver::KLU2:
1940 #if HAVE_AMESOS2_SUPERLU
1941 case BaseSolver::SUPERLU:
1945 #ifdef HAVE_AMESOS2_UMFPACK
1946 case BaseSolver::UMFPACK:
1950 #ifdef HAVE_AMESOS2_PARDISO_MKL
1951 case BaseSolver::PARDISO_MKL:
1955 #ifdef HAVE_AMESOS2_MUMPS
1956 case BaseSolver::MUMPS:
1960 #ifdef HAVE_AMESOS2_LAPACK
1961 case BaseSolver::LAPACK:
1973 "No such bottom solver available.");
1979 const std::string& reuse)
2002 "No such preconditioner available.");
2009 std::map<std::string, Boundary> map;
2011 map[
"DIRICHLET"] = Boundary::DIRICHLET;
2012 map[
"OPEN"] = Boundary::OPEN;
2013 map[
"PERIODIC"] = Boundary::PERIODIC;
2015 auto boundary = map.find(bc);
2017 if ( boundary == map.end() )
2018 throw OpalException(
"AmrMultiGrid::convertToEnumBoundary_m()",
2019 "No boundary type '" + bc +
"'.");
2020 return boundary->second;
2025 std::map<std::string, Interpolater> map;
2027 map[
"TRILINEAR"] = Interpolater::TRILINEAR;
2028 map[
"LAGRANGE"] = Interpolater::LAGRANGE;
2029 map[
"PC"] = Interpolater::PIECEWISE_CONST;
2031 auto interpolater = map.find(interp);
2033 if ( interpolater == map.end() )
2034 throw OpalException(
"AmrMultiGrid::convertToEnumInterpolater_m()",
2035 "No interpolater '" + interp +
"'.");
2036 return interpolater->second;
2042 std::map<std::string, BaseSolver> map;
2044 map[
"BICGSTAB"] = BaseSolver::BICGSTAB;
2045 map[
"MINRES"] = BaseSolver::MINRES;
2046 map[
"PCPG"] = BaseSolver::PCPG;
2047 map[
"CG"] = BaseSolver::CG;
2048 map[
"GMRES"] = BaseSolver::GMRES;
2049 map[
"STOCHASTIC_CG"] = BaseSolver::STOCHASTIC_CG;
2050 map[
"RECYCLING_CG"] = BaseSolver::RECYCLING_GMRES;
2051 map[
"RECYCLING_GMRES"] = BaseSolver::RECYCLING_GMRES;
2052 #ifdef HAVE_AMESOS2_KLU2
2053 map[
"KLU2"] = BaseSolver::KLU2;
2055 #ifdef HAVE_AMESOS2_SUPERLU
2056 map[
"SUPERLU"] = BaseSolver::SUPERLU;
2058 #ifdef HAVE_AMESOS2_UMFPACK
2059 map[
"UMFPACK"] = BaseSolver::UMFPACK;
2061 #ifdef HAVE_AMESOS2_PARDISO_MKL
2062 map[
"PARDISO_MKL"] = BaseSolver::PARDISO_MKL;
2064 #ifdef HAVE_AMESOS2_MUMPS
2065 map[
"MUMPS"] = BaseSolver::MUMPS;
2067 #ifdef HAVE_AMESOS2_LAPACK
2068 map[
"LAPACK"] = BaseSolver::LAPACK;
2072 auto solver = map.find(bsolver);
2074 if ( solver == map.end() )
2075 throw OpalException(
"AmrMultiGrid::convertToEnumBaseSolver_m()",
2076 "No bottom solver '" + bsolver +
"'.");
2077 return solver->second;
2083 std::map<std::string, Preconditioner> map;
2091 auto precond = map.find(prec);
2093 if ( precond == map.end() )
2094 throw OpalException(
"AmrMultiGrid::convertToEnumPreconditioner_m()",
2095 "No preconditioner '" + prec +
"'.");
2096 return precond->second;
2108 std::map<std::string, Norm> map;
2110 map[
"L1_NORM"] = Norm::L1;
2111 map[
"L2_NORM"] = Norm::L2;
2112 map[
"LINF_NORM"] = Norm::LINF;
2114 auto n = map.find(norm);
2116 if (
n == map.end() )
2118 "No norm '" + norm +
"'.");
2126 std::string dateStr(simtimer.
date());
2127 std::string timeStr(simtimer.
time());
2128 std::string indent(
" ");
2131 outfile <<
"&description\n"
2133 <<
"' " << dateStr <<
"" << timeStr <<
"\",\n"
2134 << indent <<
"contents=\"solver info\"\n"
2136 outfile <<
"¶meter\n"
2137 << indent <<
"name=processors,\n"
2138 << indent <<
"type=long,\n"
2139 << indent <<
"description=\"Number of Cores used\"\n"
2141 outfile <<
"¶meter\n"
2142 << indent <<
"name=revision,\n"
2143 << indent <<
"type=string,\n"
2144 << indent <<
"description=\"git revision of opal\"\n"
2146 outfile <<
"¶meter\n"
2147 << indent <<
"name=flavor,\n"
2148 << indent <<
"type=string,\n"
2149 << indent <<
"description=\"OPAL flavor that wrote file\"\n"
2151 outfile <<
"&column\n"
2152 << indent <<
"name=t,\n"
2153 << indent <<
"type=double,\n"
2154 << indent <<
"units=ns,\n"
2155 << indent <<
"description=\"1 Time\"\n"
2157 outfile <<
"&column\n"
2158 << indent <<
"name=mg_iter,\n"
2159 << indent <<
"type=long,\n"
2160 << indent <<
"units=1,\n"
2161 << indent <<
"description=\"2 Number of Multigrid Iterations\"\n"
2163 outfile <<
"&column\n"
2164 << indent <<
"name=bottom_iter,\n"
2165 << indent <<
"type=long,\n"
2166 << indent <<
"units=1,\n"
2167 << indent <<
"description=\"3 Total Number of Bottom Solver Iterations\"\n"
2169 outfile <<
"&column\n"
2170 << indent <<
"name=regrid,\n"
2171 << indent <<
"type=bool,\n"
2172 << indent <<
"units=1,\n"
2173 << indent <<
"description=\"4 Regrid Step\"\n"
2175 outfile <<
"&column\n"
2176 << indent <<
"name=" +
snorm_m +
",\n"
2177 << indent <<
"type=double,\n"
2178 << indent <<
"units=1,\n"
2179 << indent <<
"description=\"5 Error\"\n"
2182 << indent <<
"mode=ascii,\n"
2183 << indent <<
"no_row_counts=1\n"
2196 unsigned int pwi = 10;
2198 std::ofstream outfile;
2200 if (
comm_mp->getRank() == 0 ) {
2202 outfile.precision(15);
2203 outfile.setf(std::ios::scientific, std::ios::floatfield);
2205 if (
flag_m == std::ios::out ) {
2211 << this->
nIter_m << std::setw(pwi) <<
'\t'
2212 << this->
bIter_m << std::setw(pwi) <<
'\t'
2213 << this->
regrid_m << std::setw(pwi) <<
'\t'
2223 void AmrMultiGrid::initTimer_m() {
2267 os <<
"* ********************* A M R M u l t i G r i d ********************** " <<
endl
2269 <<
"* ******************************************************************** " <<
endl;
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
amr::AmrScalarFieldContainer_t AmrScalarFieldContainer_t
amr::AmrVectorFieldContainer_t AmrVectorFieldContainer_t
#define OPAL_PROJECT_VERSION
#define OPAL_PROJECT_NAME
bool for_each(const BareFieldIterator< T, D > &p, SameFieldID s, C)
Inform & endl(Inform &inf)
void serialize(Param_t params, std::ostringstream &os)
serializes params using Boost archive
@ GS
Gauss-Seidel point relaxation.
@ JACOBI
Jacobi point relaxation.
@ SA
smoothed aggregation multigrid
@ BLOCK_JACOBI
Jacobi block relaxation.
@ BLOCK_GS
Gauss-Seidel block relaxation.
constexpr double e
The value of.
std::string getGitRevision()
The global OPAL structure.
std::string getInputFn()
get opals input filename
static OpalData * getInstance()
const Vector_t & getMeshScaling() const
void trilinos2amrex_m(const lo_t &level, const lo_t &comp, AmrField_t &mf, const Teuchos::RCP< vector_t > &mv)
void buildCrseBoundaryMatrix_m(const lo_t &level, const go_t &gidx, const AmrIntVect_t &iv, const basefab_t &mfab, const basefab_t &cfab, const scalar_t *invdx2)
amrex::BaseFab< int > basefab_t
void relax_m(const lo_t &level)
void initGuess_m(bool reset)
void close_m(const lo_t &level, const bool &matrices)
AmrMultiGrid(AmrBoxLib *itsAmrObject_p, const std::string &bsolver, const std::string &prec, const bool &rebalance, const std::string &reuse, const std::string &bcx, const std::string &bcy, const std::string &bcz, const std::string &smoother, const std::size_t &nSweeps, const std::string &interp, const std::string &norm)
double getZRangeMax(unsigned short level=0)
void restrict_m(const lo_t &level)
Boundary
Supported physical boundaries.
Boundary convertToEnumBoundary_m(const std::string &bc)
std::shared_ptr< bsolver_t > solver_mp
bottom solver
BaseSolver convertToEnumBaseSolver_m(const std::string &bsolver)
void setup_m(const amrex::Vector< AmrField_u > &rho, const amrex::Vector< AmrField_u > &phi, const bool &matrices=true)
double getXRangeMin(unsigned short level=0)
void initPhysicalBoundary_m(const Boundary *bc)
AmrMultiGridLevel_t::coefficients_t coefficients_t
Teuchos::RCP< comm_t > comm_mp
communicator
std::string fname_m
SDDS filename.
BaseSolver
Supported bottom solvers.
AmrMultiGridLevel_t::umap_t umap_t
amrex::FArrayBox farraybox_t
std::string snorm_m
norm for convergence criteria
std::size_t nSweeps_m
number of smoothing iterations
void map2vector_m(umap_t &map, indices_t &indices, coefficients_t &values)
void buildFineBoundaryMatrix_m(const lo_t &level, const go_t &gidx, const AmrIntVect_t &iv, const basefab_t &mfab, const basefab_t &rfab)
void writeSDDSHeader_m(std::ofstream &outfile)
std::vector< std::unique_ptr< AmrMultiGridLevel_t > > mglevel_m
container for levels
void amrex2trilinos_m(const lo_t &level, const lo_t &comp, const AmrField_t &mf, Teuchos::RCP< vector_t > &mv)
scalar_t getLevelResidualNorm(lo_t level)
scalar_t evalNorm_m(const Teuchos::RCP< const vector_t > &x)
void buildSingleLevel_m(const amrex::Vector< AmrField_u > &rho, const amrex::Vector< AmrField_u > &phi, const bool &matrices=true)
int lbase_m
base level (currently only 0 supported)
void initPrec_m(const Preconditioner &prec, const std::string &reuse)
void setVerbose(bool verbose)
void initInterpolater_m(const Interpolater &interp)
std::unique_ptr< AmrInterpolater< AmrMultiGridLevel_t > > interp_mp
interpolater without coarse-fine interface
void buildGradientMatrix_m(const lo_t &level, const go_t &gidx, const AmrIntVect_t &iv, const basefab_t &mfab, const scalar_t *invdx)
BelosBottomSolver< AmrMultiGridLevel_t > BelosSolver_t
void initCrseFineInterp_m(const Interpolater &interface)
std::shared_ptr< preconditioner_t > prec_mp
preconditioner for bottom solver
std::unique_ptr< AmrInterpolater< AmrMultiGridLevel_t > > interface_mp
interpolater for coarse-fine interface
Norm convertToEnumNorm_m(const std::string &norm)
Interpolater convertToEnumInterpolater_m(const std::string &interp)
amr::global_ordinal_t go_t
void averageDown_m(const lo_t &level)
Smoother convertToEnumSmoother_m(const std::string &smoother)
double getZRangeMin(unsigned short level=0)
Amesos2BottomSolver< AmrMultiGridLevel_t > Amesos2Solver_t
void buildPotentialVector_m(const lo_t &level, const AmrField_t &phi)
void residual_no_fine_m(const lo_t &level, Teuchos::RCP< vector_t > &result, const Teuchos::RCP< vector_t > &rhs, const Teuchos::RCP< vector_t > &crs_rhs, const Teuchos::RCP< vector_t > &b)
scalar_t eps_m
rhs scale for convergence
AmrMultiGridLevel_t::AmrField_t AmrField_t
std::size_t nIter_m
number of iterations till convergence
double getXRangeMax(unsigned short level=0)
Inform & print(Inform &os) const
AmrMultiGridLevel_t::AmrIntVect_t AmrIntVect_t
bool verbose_m
If true, a SDDS file is written.
std::size_t bIter_m
number of iterations of bottom solver
int nlevel_m
number of levelss
amr::local_ordinal_t lo_t
std::ios_base::openmode flag_m
std::ios::out or std::ios::app
void setNumberOfSweeps(const std::size_t &nSweeps)
void initResidual_m(std::vector< scalar_t > &rhsNorms, std::vector< scalar_t > &resNorms)
void buildMultiLevel_m(const amrex::Vector< AmrField_u > &rho, const amrex::Vector< AmrField_u > &phi, const bool &matrices=true)
void open_m(const lo_t &level, const bool &matrices)
void buildDensityVector_m(const lo_t &level, const AmrField_t &rho)
MueLuPreconditioner< AmrMultiGridLevel_t > MueLuPreconditioner_t
AmrMultiGridLevel< matrix_t, vector_t > AmrMultiGridLevel_t
std::size_t getNumIters()
std::size_t maxiter_m
maximum number of iterations allowed
void buildNoFinePoissonMatrix_m(const lo_t &level, const go_t &gidx, const AmrIntVect_t &iv, const basefab_t &mfab, const scalar_t *invdx2)
double getYRangeMin(unsigned short level=0)
void writeSDDSData_m(const scalar_t &error)
int nBcPoints_m
maximum number of stencils points for BC
void setMaxNumberOfIterations(const std::size_t &maxiter)
void initBaseSolver_m(const BaseSolver &solver, const bool &rebalance, const std::string &reuse)
Smoother smootherType_m
type of smoother
Norm
Supported convergence criteria.
void initLevels_m(const amrex::Vector< AmrField_u > &rho, const amrex::Vector< AmrGeometry_t > &geom, bool regrid)
void smooth_m(const lo_t &level, Teuchos::RCP< vector_t > &e, Teuchos::RCP< vector_t > &r)
Ifpack2Preconditioner< AmrMultiGridLevel_t > Ifpack2Preconditioner_t
boundary_t bc_m[AMREX_SPACEDIM]
boundary conditions
void residual_m(const lo_t &level, Teuchos::RCP< vector_t > &r, const Teuchos::RCP< vector_t > &b, const Teuchos::RCP< vector_t > &x)
std::vector< std::shared_ptr< AmrSmoother > > smoother_m
error smoother
void buildInterpolationMatrix_m(const lo_t &level, const go_t &gidx, const AmrIntVect_t &iv, const basefab_t &cfab)
void computeEfield_m(AmrVectorFieldContainer_t &efield)
AmrMultiGridLevel_t::indices_t indices_t
Interpolater
Supported interpolaters for prolongation operation.
void prolongate_m(const lo_t &level)
bool isConverged_m(std::vector< scalar_t > &rhsNorms, std::vector< scalar_t > &resNorms)
Norm norm_m
norm for convergence criteria (l1, l2, linf)
double getYRangeMax(unsigned short level=0)
void setTolerance(const scalar_t &eps)
void solve(AmrScalarFieldContainer_t &rho, AmrScalarFieldContainer_t &phi, AmrVectorFieldContainer_t &efield, unsigned short baseLevel, unsigned short finestLevel, bool prevAsGuess=true)
MueLuBottomSolver< AmrMultiGridLevel_t > MueLuSolver_t
void buildRestrictionMatrix_m(const lo_t &level, const go_t &gidx, const AmrIntVect_t &iv, D_DECL(const go_t &ii, const go_t &jj, const go_t &kk), const basefab_t &rfab)
Preconditioner convertToEnumPreconditioner_m(const std::string &prec)
void buildCompositePoissonMatrix_m(const lo_t &level, const go_t &gidx, const AmrIntVect_t &iv, const basefab_t &mfab, const basefab_t &rfab, const scalar_t *invdx2)
amrex::FabArray< basefab_t > mask_t
Smoother
All supported Ifpack2 smoothers.
static Smoother convertToEnumSmoother(const std::string &smoother)
static void fillMap(map_t &map)
static std::string convertToMueLuReuseOption(const std::string &reuse)
static std::string convertToMueLuReuseOption(const std::string &reuse)
static void fillMap(map_t &map)
bool regrid_m
is set to true by itsAmrObject_mp and reset to false by solver
AmrBoxLib * itsAmrObject_mp
The base class for all OPAL exceptions.
std::string date() const
Return date.
std::string time() const
Return time.
static TimerRef getTimer(const char *nm)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)