36#include <AMReX_ParallelDescriptor.H>
38#include <boost/filesystem.hpp>
45 const std::string& bsolver,
46 const std::string& prec,
47 const bool& rebalance,
48 const std::string& reuse,
49 const std::string& bcx,
50 const std::string& bcy,
51 const std::string& bcz,
52 const std::string& smoother,
53 const std::size_t& nSweeps,
54 const std::string& interp,
55 const std::string& norm)
57 , comm_mp( new
comm_t( amrex::ParallelDescriptor::Communicator() ) )
70 , fname_m(
OpalData::getInstance()->getInputBasename() +
std::string(
".solver"))
71 , flag_m(
std::ios::out)
77 const Boundary bcs[AMREX_SPACEDIM] = {
103 if (boost::filesystem::exists(
fname_m)) {
115 unsigned short baseLevel,
116 unsigned short finestLevel,
128 bool reset = !prevAsGuess;
143 for (
int lev =
nlevel_m - 1; lev > -1; --lev) {
151 for (
int lev = 0; lev <
nlevel_m; ++lev) {
154 phi[ilev]->setVal(0.0, phi[ilev]->nGrow());
174 throw OpalException(
"AmrMultiGrid::setMaxNumberOfIterations()",
175 "The max. number of iterations needs to be positive!");
206 for (
unsigned int i = 0; i < AMREX_SPACEDIM; ++i) {
208 case Boundary::DIRICHLET:
214 case Boundary::PERIODIC:
218 throw OpalException(
"AmrMultiGrid::initPhysicalBoundary_m()",
219 "This type of boundary is not supported");
222 go_t tmp =
bc_m[i]->getNumberOfPoints();
230 const amrex::Vector<AmrGeometry_t>& geom,
243 amrex::Periodicity period(
AmrIntVect_t(D_DECL(0, 0, 0)));
247 for (
int lev = 0; lev <
nlevel_m; ++lev) {
253 rho[ilev]->boxArray(),
254 rho[ilev]->DistributionMap(),
267 mglevel_m[lev]->refmask->setVal(AmrMultiGridLevel_t::Refined::NO, 2);
268 mglevel_m[lev]->refmask->FillBoundary(period);
270 amrex::BoxArray ba =
mglevel_m[lev]->grids;
276 mglevel_m[lev]->crsemask->setVal(AmrMultiGridLevel_t::Refined::NO, 2);
279 for (
int lev = 1; lev <
nlevel_m; ++lev) {
280 mglevel_m[lev]->crsemask->setVal(AmrMultiGridLevel_t::Refined::YES, 0);
283 mglevel_m[lev]->crsemask->setDomainBndry(AmrMultiGridLevel_t::Mask::PHYSBNDRY,
286 mglevel_m[lev]->crsemask->FillBoundary(period);
292 for (
int lev = 0; lev <
nlevel_m-1; ++lev) {
294 amrex::BoxArray ba =
mglevel_m[lev]->grids;
296 ba = amrex::intersect(
mglevel_m[lev+1]->grids, ba);
300 amrex::DistributionMapping dmap(ba,
comm_mp->getSize());
302 refined.setVal(AmrMultiGridLevel_t::Refined::YES);
306 mglevel_m[lev]->refmask->copy(refined, 0, 0, 1, 0, 2);
311 mglevel_m[lev]->refmask->setDomainBndry(AmrMultiGridLevel_t::Mask::PHYSBNDRY,
314 mglevel_m[lev]->refmask->FillBoundary(period);
320 for (
int lev = 0; lev <
nlevel_m; ++lev) {
333 for (
int lev = 0; lev <
nlevel_m; ++lev)
341 std::vector<scalar_t> rhsNorms;
342 std::vector<scalar_t> resNorms;
347 [
this](
double& val){ val *= eps_m; });
366 for (
int lev = 0; lev <
nlevel_m; ++lev) {
381 this->writeResidualNorm_m();
387 return std::accumulate(resNorms.begin(),
389 std::plus<scalar_t>());
394 std::vector<scalar_t>& resNorms)
396 return std::equal(resNorms.begin(), resNorms.end(),
398 std::less<scalar_t>());
403 Teuchos::RCP<vector_t>& r,
404 const Teuchos::RCP<vector_t>& b,
405 const Teuchos::RCP<vector_t>& x)
415 if (
mglevel_m[level]->Bfine_p != Teuchos::null ) {
420 mglevel_m[level]->Awf_p->apply(*x, fine2crse,
425 if (
mglevel_m[level]->Bcrse_p != Teuchos::null ) {
434 Teuchos::RCP<vector_t> uncov_Ax = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
435 mglevel_m[level]->UnCovered_p->apply(fine2crse, *uncov_Ax);
437 Teuchos::RCP<vector_t> uncov_b = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
439 mglevel_m[level]->UnCovered_p->apply(*b, *uncov_b);
444 r->update(1.0, *uncov_b, -1.0, *uncov_Ax, 0.0);
449 Teuchos::RCP<vector_t> Ax = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
452 if (
mglevel_m[level]->Bcrse_p != Teuchos::null ) {
460 r->update(1.0, *b, -1.0, *Ax, 0.0);
472 Teuchos::RCP<vector_t> Ax = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
487 Teuchos::RCP<vector_t> phi_save = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p) );
488 Tpetra::deep_copy(*phi_save, *
mglevel_m[level]->phi_p);
490 mglevel_m[level-1]->error_p->putScalar(0.0);
514 Teuchos::RCP<vector_t> tmp = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p) );
520 Tpetra::deep_copy(*
mglevel_m[level]->residual_p, *tmp);
523 Teuchos::RCP<vector_t> derror = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
529 mglevel_m[level]->error_p->update(1.0, *derror, 1.0);
532 mglevel_m[level]->phi_p->update(1.0, *phi_save, 1.0, *
mglevel_m[level]->error_p, 0.0);
553 Teuchos::RCP<vector_t>& result,
554 const Teuchos::RCP<vector_t>& rhs,
555 const Teuchos::RCP<vector_t>& crs_rhs,
556 const Teuchos::RCP<vector_t>& b)
561 if (
mglevel_m[level]->Bcrse_p != Teuchos::null ) {
562 mglevel_m[level]->Bcrse_p->apply(*crs_rhs, crse2fine);
566 mglevel_m[level]->Anf_p->apply(*rhs, crse2fine,
571 result->update(1.0, *b, -1.0, crse2fine, 0.0);
576void AmrMultiGrid::writeResidualNorm_m() {
581 out.open(
"residual.dat", std::ios::app);
583 for (
int lev = 0; lev <
nlevel_m; ++lev) {
587 out << std::setw(15) << std::right << tmp;
619 "This type of norm not suppported.");
626 std::vector<scalar_t>& resNorms)
634 if (
comm_mp->getRank() == 0) {
635 out.open(
"residual.dat", std::ios::out);
637 for (
int lev = 0; lev <
nlevel_m; ++lev)
638 out << std::setw(14) << std::right <<
"level" << lev;
643 for (
int lev = 0; lev <
nlevel_m; ++lev) {
653 out << std::setw(15) << std::right << resNorms.back();
670 Teuchos::RCP<vector_t> efield_p = Teuchos::null;
671 for (
int lev =
nlevel_m - 1; lev > -1; --lev) {
677 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
678 efield[ilev][d]->setVal(0.0, efield[ilev][d]->nGrow());
679 efield_p->putScalar(0.0);
691 const amrex::Vector<AmrField_u>& phi,
692 const bool& matrices)
720 const amrex::Vector<AmrField_u>& phi,
721 const bool& matrices)
728 D_DECL( invdx[0] * invdx[0],
730 invdx[2] * invdx[2] )
735 mfi.isValid(); ++mfi)
737 const box_t& tbx = mfi.tilebox();
742 const int* lo = tbx.loVect();
743 const int* hi = tbx.hiVect();
745 for (
int i = lo[0]; i <= hi[0]; ++i) {
746 for (
int j = lo[1]; j <= hi[1]; ++j) {
747#if AMREX_SPACEDIM == 3
748 for (
int k = lo[2]; k <= hi[2]; ++k) {
761#if AMREX_SPACEDIM == 3
781 const amrex::Vector<AmrField_u>& phi,
782 const bool& matrices)
793 for (
int lev = 0; lev <
nlevel_m; ++lev) {
794 this->
open_m(lev, matrices);
804 D_DECL( invdx[0] * invdx[0],
806 invdx[2] * invdx[2] )
810 for (amrex::MFIter mfi(*
mglevel_m[lev]->mask,
true);
811 mfi.isValid(); ++mfi)
813 const box_t& tbx = mfi.tilebox();
820 const int* lo = tbx.loVect();
821 const int* hi = tbx.hiVect();
823 for (
int i = lo[0]; i <= hi[0]; ++i) {
825 for (
int j = lo[1]; j <= hi[1]; ++j) {
827#if AMREX_SPACEDIM == 3
828 for (
int k = lo[2]; k <= hi[2]; ++k) {
835 D_DECL(ii, jj, kk), rfab);
853 mglevel_m[lev]->rho_p->replaceGlobalValue(gidx, rhofab(iv, 0));
854 mglevel_m[lev]->phi_p->replaceGlobalValue(gidx, pfab(iv, 0));
855#if AMREX_SPACEDIM == 3
870 if ( matrices && lev >
lbase_m ) {
879 const bool& matrices)
893 Tpetra::StaticProfile) );
902 mglevel_m[level]->Bcrse_p = Teuchos::rcp(
904 Tpetra::StaticProfile) );
916 int nNeighbours = AMREX_D_TERM(2, * 2, * 2);
920 Tpetra::StaticProfile) );
927 nNeighbours = 2 * AMREX_SPACEDIM * AMREX_D_TERM(2, * 2, * 2);
929 mglevel_m[level]->Bfine_p = Teuchos::rcp(
931 Tpetra::StaticProfile) );
939 int nPhysBoundary = 2 * AMREX_SPACEDIM *
nBcPoints_m;
942 int nIntBoundary = AMREX_SPACEDIM *
interface_mp->getNumberOfPoints();
944 int nEntries = (AMREX_SPACEDIM << 1) + 2 + nPhysBoundary + nIntBoundary;
949 Tpetra::StaticProfile) );
956 nEntries = (AMREX_SPACEDIM << 1) + 5 + nPhysBoundary + nIntBoundary;
960 Tpetra::StaticProfile) );
965 mglevel_m[level]->UnCovered_p = Teuchos::rcp(
967 Tpetra::StaticProfile) );
976 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
979 Tpetra::StaticProfile) );
995 const bool& matrices)
1017 mglevel_m[level]->Anf_p->fillComplete();
1019 for (
int d = 0; d < AMREX_SPACEDIM; ++d)
1020 mglevel_m[level]->G_p[d]->fillComplete();
1024 mglevel_m[level]->Awf_p->fillComplete();
1026 mglevel_m[level]->UnCovered_p->fillComplete();
1055 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1056 for (
int shift = -1; shift <= 1; shift += 2) {
1060 switch ( mfab(biv) )
1062 case AmrMultiGridLevel_t::Mask::INTERIOR:
1063 case AmrMultiGridLevel_t::Mask::COVERED:
1065 map[
mglevel_m[level]->serialize(biv)] += invdx2[d];
1068 case AmrMultiGridLevel_t::Mask::BNDRY:
1074 throw OpalException(
"AmrMultiGrid::buildNoFinePoissonMatrix_m()",
1075 "Error in mask for level "
1076 + std::to_string(level) +
"!");
1084 case AmrMultiGridLevel_t::Mask::PHYSBNDRY:
1087 mglevel_m[level]->applyBoundary(biv, d, map,
1092 throw OpalException(
"AmrMultiGrid::buildNoFinePoissonMatrix_m()",
1093 "Error in mask for level "
1094 + std::to_string(level) +
"!");
1100 map[gidx] += AMREX_D_TERM(- 2.0 * invdx2[0],
1106 mglevel_m[level]->Anf_p->insertGlobalValues(gidx,
1125 if ( rfab(iv) == AmrMultiGridLevel_t::Refined::YES )
1148 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1149 for (
int shift = -1; shift <= 1; shift += 2) {
1153 if ( rfab(biv) != AmrMultiGridLevel_t::Refined::YES )
1158 switch ( mfab(biv) )
1160 case AmrMultiGridLevel_t::Mask::COVERED:
1162 case AmrMultiGridLevel_t::Mask::INTERIOR:
1164 map[
mglevel_m[level]->serialize(biv)] += invdx2[d];
1165 map[gidx] -= invdx2[d];
1168 case AmrMultiGridLevel_t::Mask::BNDRY:
1174 throw OpalException(
"AmrMultiGrid::buildCompositePoissonMatrix_m()",
1175 "Error in mask for level "
1176 + std::to_string(level) +
"!");
1191 map[gidx] -= invdx2[d];
1194 case AmrMultiGridLevel_t::Mask::PHYSBNDRY:
1197 mglevel_m[level]->applyBoundary(biv, d, map,
1201 map[gidx] -= invdx2[d];
1205 throw OpalException(
"AmrMultiGrid::buildCompositePoissonMatrix_m()",
1206 "Error in mask for level "
1207 + std::to_string(level) +
"!");
1228 scalar_t invavg = AMREX_D_PICK(1.0, 0.5, 0.25);
1229 scalar_t value = - invavg * invcdx[d] * invfdx[d];
1231 for (
int d1 = 0; d1 < 2; ++d1) {
1232#if AMREX_SPACEDIM == 3
1233 for (
int d2 = 0; d2 < 2; ++d2) {
1241 fake[(d+1)%AMREX_SPACEDIM] = d1;
1242#if AMREX_SPACEDIM == 3
1243 fake[(d+2)%AMREX_SPACEDIM] = d2;
1248#if AMREX_SPACEDIM == 3
1258 mglevel_m[level]->Awf_p->insertGlobalValues(gidx,
1264 mglevel_m[level]->UnCovered_p->insertGlobalValues(gidx,
1274 D_DECL(
const go_t& ii,
1284 if ( rfab(iv) == AmrMultiGridLevel_t::Refined::NO || level ==
lfine_m )
1296 indices.reserve(2 << (AMREX_SPACEDIM - 1));
1298 values.reserve(2 << (AMREX_SPACEDIM -1));
1301 for (
int iref = 0; iref < 2; ++iref) {
1302 for (
int jref = 0; jref < 2; ++jref) {
1303#if AMREX_SPACEDIM == 3
1304 for (
int kref = 0; kref < 2; ++kref) {
1306 AmrIntVect_t riv(D_DECL(ii + iref, jj + jref, kk + kref));
1309 values.push_back( AMREX_D_PICK(0.5, 0.25, 0.125) );
1310#if AMREX_SPACEDIM == 3
1316 mglevel_m[level]->R_p->insertGlobalValues(gidx,
1353 mglevel_m[level]->I_p->insertGlobalValues(gidx,
1383 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1384 for (
int shift = -1; shift <= 1; shift += 2) {
1389 if ( mfab(niv) == AmrMultiGridLevel_t::Mask::BNDRY )
1397 civ.coarsen(
mglevel_m[level]->refinement());
1403 interface_mp->coarse(civ, map, invdx2[d], d, shift, cfab,
1407 else if ( mfab(niv) == AmrMultiGridLevel_t::Mask::PHYSBNDRY ) {
1408 throw OpalException(
"AmrMultiGrid::buildCrseBoundaryMatrix_m()",
1409 "Fine meshes shouldn't be connected "
1410 "to physical (i.e. mesh) boundary!");
1418 mglevel_m[level]->Bcrse_p->insertGlobalValues(gidx,
1436 if ( rfab(iv) == AmrMultiGridLevel_t::Refined::YES || level ==
lfine_m )
1443 scalar_t invavg = AMREX_D_PICK(1, 0.5, 0.25);
1449 auto fill = [&](
umap_t& map,
1450 D_DECL(
int ii,
int jj,
int kk),
1454 for (
int iref = ii -
begin[0]; iref <= ii +
end[0]; ++iref) {
1455 for (
int jref = jj -
begin[1]; jref <= jj +
end[1]; ++jref) {
1456#if AMREX_SPACEDIM == 3
1457 for (
int kref = kk -
begin[2]; kref <= kk +
end[2]; ++kref) {
1464 if ( (riv[d] >> 1) == iv[d] ) {
1468 scalar_t value = - invavg * invcdx[d] * invfdx[d];
1473 scalar_t value = invavg * invcdx[d] * invfdx[d];
1474 map[
mglevel_m[level+1]->serialize(riv)] += value;
1476#if AMREX_SPACEDIM == 3
1490 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1491 for (
int shift = -1; shift <= 1; shift += 2) {
1494 covered[d] += shift;
1496 if ( rfab(covered) == AmrMultiGridLevel_t::Refined::YES &&
1511 int begin[AMREX_SPACEDIM] = { D_DECL(
int(d == 0),
int(d == 1),
int(d == 2) ) };
1512 int end[AMREX_SPACEDIM] = { D_DECL(
int(d != 0),
int(d != 1),
int(d != 2) ) };
1527 int ii = iv[0] << 1;
1528 int jj = iv[1] << 1;
1529#if AMREX_SPACEDIM == 3
1530 int kk = iv[2] << 1;
1535 fill(map, D_DECL(ii, jj, kk), &
begin[0], &
end[0], d, iv, shift);
1542 int ii = covered[0] << 1;
1543 int jj = covered[1] << 1;
1544#if AMREX_SPACEDIM == 3
1545 int kk = covered[2] << 1;
1547 fill(map, D_DECL(ii, jj, kk), &
begin[0], &
end[0], d, iv, shift);
1559 mglevel_m[level]->Bfine_p->insertGlobalValues(gidx,
1597 case AmrMultiGridLevel_t::Mask::INTERIOR:
1599 case AmrMultiGridLevel_t::Mask::COVERED:
1601 map[
mglevel_m[level]->serialize(iv)] -= shift * 0.5 * invdx[dir];
1603 case AmrMultiGridLevel_t::Mask::BNDRY:
1608 throw OpalException(
"AmrMultiGrid::buildGradientMatrix_m()",
1609 "Error in mask for level "
1610 + std::to_string(level) +
"!");
1613 scalar_t value = - shift * 0.5 * invdx[dir];
1619 map[
mglevel_m[level]->serialize(tmp)] += 2.0 * value;
1623 map[
mglevel_m[level]->serialize(tmp)] -= value;
1626 case AmrMultiGridLevel_t::Mask::PHYSBNDRY:
1630 scalar_t value = - shift * 0.5 * invdx[dir];
1632 mglevel_m[level]->applyBoundary(iv, dir,
1641 for (
int d = 0; d < AMREX_SPACEDIM; ++d) {
1642 for (
int shift = -1; shift <= 1; shift += 2) {
1645 check(niv, mfab, d, shift);
1650 mglevel_m[level]->G_p[d]->insertGlobalValues(gidx,
1661 Teuchos::RCP<vector_t>& mv)
1666 for (amrex::MFIter mfi(mf,
true); mfi.isValid(); ++mfi) {
1667 const amrex::Box& tbx = mfi.tilebox();
1668 const amrex::FArrayBox& fab = mf[mfi];
1670 const int* lo = tbx.loVect();
1671 const int* hi = tbx.hiVect();
1673 for (
int i = lo[0]; i <= hi[0]; ++i) {
1674 for (
int j = lo[1]; j <= hi[1]; ++j) {
1675#if AMREX_SPACEDIM == 3
1676 for (
int k = lo[2]; k <= hi[2]; ++k) {
1682 mv->replaceGlobalValue(gidx, fab(iv, comp));
1683#if AMREX_SPACEDIM == 3
1695 const Teuchos::RCP<vector_t>& mv)
1697 Teuchos::ArrayRCP<const amr::scalar_t> data = mv->get1dView();
1699 for (amrex::MFIter mfi(mf,
true); mfi.isValid(); ++mfi) {
1700 const amrex::Box& tbx = mfi.tilebox();
1701 amrex::FArrayBox& fab = mf[mfi];
1703 const int* lo = tbx.loVect();
1704 const int* hi = tbx.hiVect();
1706 for (
int i = lo[0]; i <= hi[0]; ++i) {
1707 for (
int j = lo[1]; j <= hi[1]; ++j) {
1708#if AMREX_SPACEDIM == 3
1709 for (
int k = lo[2]; k <= hi[2]; ++k) {
1716 fab(iv, comp) = data[lidx];
1718#if AMREX_SPACEDIM == 3
1733 indices.reserve(map.size());
1734 values.reserve(map.size());
1737 [&](
const std::pair<const go_t, scalar_t>& entry)
1740 if ( entry.first < 0 ) {
1741 throw OpalException(
"AmrMultiGrid::map2vector_m()",
1742 "Negative matrix index!");
1746 indices.push_back(entry.first);
1747 values.push_back(entry.second);
1756 Teuchos::RCP<vector_t>&
e,
1757 Teuchos::RCP<vector_t>& r)
1778 Teuchos::RCP<vector_t> tmp = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p) );
1785 mglevel_m[level-1]->residual_p->putScalar(0.0);
1801 fine2crse, Teuchos::NO_TRANS,
1804 if (
mglevel_m[level-1]->Bcrse_p != Teuchos::null ) {
1807 fine2crse, Teuchos::NO_TRANS,
1811 Teuchos::RCP<vector_t> uncoveredRho = Teuchos::rcp(
new vector_t(
mglevel_m[level-1]->map_p,
true) );
1817 Teuchos::RCP<vector_t> tmp2 = Teuchos::rcp(
new vector_t(
mglevel_m[level-1]->map_p,
true) );
1818 mglevel_m[level-1]->UnCovered_p->apply(fine2crse, *tmp2);
1821 mglevel_m[level-1]->residual_p->update(1.0, *uncoveredRho, -1.0, *tmp2, 1.0);
1853 Teuchos::RCP<vector_t> phicrse = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
false) );
1858 Teuchos::RCP<vector_t> uncov_phi = Teuchos::rcp(
new vector_t(
mglevel_m[level]->map_p,
true) );
1862 mglevel_m[level]->phi_p->update(1.0, *phicrse, 1.0, *uncov_phi, 0.0);
1871 case Interpolater::TRILINEAR:
1874 case Interpolater::LAGRANGE:
1876 "Not yet implemented.");
1877 case Interpolater::PIECEWISE_CONST:
1882 "No such interpolater available.");
1888 switch ( interface ) {
1889 case Interpolater::TRILINEAR:
1892 case Interpolater::LAGRANGE:
1896 case Interpolater::PIECEWISE_CONST:
1901 "No such interpolater for the coarse-fine interface available.");
1907 const bool& rebalance,
1908 const std::string& reuse)
1912 case BaseSolver::BICGSTAB:
1915 case BaseSolver::MINRES:
1918 case BaseSolver::PCPG:
1921 case BaseSolver::CG:
1924 case BaseSolver::GMRES:
1927 case BaseSolver::STOCHASTIC_CG:
1930 case BaseSolver::RECYCLING_CG:
1933 case BaseSolver::RECYCLING_GMRES:
1937#ifdef HAVE_AMESOS2_KLU2
1938 case BaseSolver::KLU2:
1942#if HAVE_AMESOS2_SUPERLU
1943 case BaseSolver::SUPERLU:
1947#ifdef HAVE_AMESOS2_UMFPACK
1948 case BaseSolver::UMFPACK:
1952#ifdef HAVE_AMESOS2_PARDISO_MKL
1953 case BaseSolver::PARDISO_MKL:
1957#ifdef HAVE_AMESOS2_MUMPS
1958 case BaseSolver::MUMPS:
1962#ifdef HAVE_AMESOS2_LAPACK
1963 case BaseSolver::LAPACK:
1975 "No such bottom solver available.");
1981 const std::string& reuse)
1999 case Preconditioner::NONE:
2004 "No such preconditioner available.");
2011 std::map<std::string, Boundary> map;
2013 map[
"DIRICHLET"] = Boundary::DIRICHLET;
2014 map[
"OPEN"] = Boundary::OPEN;
2015 map[
"PERIODIC"] = Boundary::PERIODIC;
2017 auto boundary = map.find(bc);
2019 if ( boundary == map.end() )
2020 throw OpalException(
"AmrMultiGrid::convertToEnumBoundary_m()",
2021 "No boundary type '" + bc +
"'.");
2022 return boundary->second;
2027 std::map<std::string, Interpolater> map;
2029 map[
"TRILINEAR"] = Interpolater::TRILINEAR;
2030 map[
"LAGRANGE"] = Interpolater::LAGRANGE;
2031 map[
"PC"] = Interpolater::PIECEWISE_CONST;
2033 auto interpolater = map.find(interp);
2035 if ( interpolater == map.end() )
2036 throw OpalException(
"AmrMultiGrid::convertToEnumInterpolater_m()",
2037 "No interpolater '" + interp +
"'.");
2038 return interpolater->second;
2044 std::map<std::string, BaseSolver> map;
2046 map[
"BICGSTAB"] = BaseSolver::BICGSTAB;
2047 map[
"MINRES"] = BaseSolver::MINRES;
2048 map[
"PCPG"] = BaseSolver::PCPG;
2049 map[
"CG"] = BaseSolver::CG;
2050 map[
"GMRES"] = BaseSolver::GMRES;
2051 map[
"STOCHASTIC_CG"] = BaseSolver::STOCHASTIC_CG;
2052 map[
"RECYCLING_CG"] = BaseSolver::RECYCLING_GMRES;
2053 map[
"RECYCLING_GMRES"] = BaseSolver::RECYCLING_GMRES;
2054#ifdef HAVE_AMESOS2_KLU2
2055 map[
"KLU2"] = BaseSolver::KLU2;
2057#ifdef HAVE_AMESOS2_SUPERLU
2058 map[
"SUPERLU"] = BaseSolver::SUPERLU;
2060#ifdef HAVE_AMESOS2_UMFPACK
2061 map[
"UMFPACK"] = BaseSolver::UMFPACK;
2063#ifdef HAVE_AMESOS2_PARDISO_MKL
2064 map[
"PARDISO_MKL"] = BaseSolver::PARDISO_MKL;
2066#ifdef HAVE_AMESOS2_MUMPS
2067 map[
"MUMPS"] = BaseSolver::MUMPS;
2069#ifdef HAVE_AMESOS2_LAPACK
2070 map[
"LAPACK"] = BaseSolver::LAPACK;
2074 auto solver = map.find(bsolver);
2076 if ( solver == map.end() )
2077 throw OpalException(
"AmrMultiGrid::convertToEnumBaseSolver_m()",
2078 "No bottom solver '" + bsolver +
"'.");
2079 return solver->second;
2085 std::map<std::string, Preconditioner> map;
2087 map[
"NONE"] = Preconditioner::NONE;
2093 auto precond = map.find(prec);
2095 if ( precond == map.end() )
2096 throw OpalException(
"AmrMultiGrid::convertToEnumPreconditioner_m()",
2097 "No preconditioner '" + prec +
"'.");
2098 return precond->second;
2110 std::map<std::string, Norm> map;
2112 map[
"L1_NORM"] = Norm::L1;
2113 map[
"L2_NORM"] = Norm::L2;
2114 map[
"LINF_NORM"] = Norm::LINF;
2116 auto n = map.find(norm);
2118 if (
n == map.end() )
2120 "No norm '" + norm +
"'.");
2128 std::string dateStr(simtimer.
date());
2129 std::string timeStr(simtimer.
time());
2130 std::string indent(
" ");
2133 outfile <<
"&description\n"
2135 <<
"' " << dateStr <<
"" << timeStr <<
"\",\n"
2136 << indent <<
"contents=\"solver info\"\n"
2138 outfile <<
"¶meter\n"
2139 << indent <<
"name=processors,\n"
2140 << indent <<
"type=long,\n"
2141 << indent <<
"description=\"Number of Cores used\"\n"
2143 outfile <<
"¶meter\n"
2144 << indent <<
"name=revision,\n"
2145 << indent <<
"type=string,\n"
2146 << indent <<
"description=\"git revision of opal\"\n"
2148 outfile <<
"¶meter\n"
2149 << indent <<
"name=flavor,\n"
2150 << indent <<
"type=string,\n"
2151 << indent <<
"description=\"OPAL flavor that wrote file\"\n"
2153 outfile <<
"&column\n"
2154 << indent <<
"name=t,\n"
2155 << indent <<
"type=double,\n"
2156 << indent <<
"units=ns,\n"
2157 << indent <<
"description=\"1 Time\"\n"
2159 outfile <<
"&column\n"
2160 << indent <<
"name=mg_iter,\n"
2161 << indent <<
"type=long,\n"
2162 << indent <<
"units=1,\n"
2163 << indent <<
"description=\"2 Number of Multigrid Iterations\"\n"
2165 outfile <<
"&column\n"
2166 << indent <<
"name=bottom_iter,\n"
2167 << indent <<
"type=long,\n"
2168 << indent <<
"units=1,\n"
2169 << indent <<
"description=\"3 Total Number of Bottom Solver Iterations\"\n"
2171 outfile <<
"&column\n"
2172 << indent <<
"name=regrid,\n"
2173 << indent <<
"type=bool,\n"
2174 << indent <<
"units=1,\n"
2175 << indent <<
"description=\"4 Regrid Step\"\n"
2177 outfile <<
"&column\n"
2178 << indent <<
"name=" +
snorm_m +
",\n"
2179 << indent <<
"type=double,\n"
2180 << indent <<
"units=1,\n"
2181 << indent <<
"description=\"5 Error\"\n"
2184 << indent <<
"mode=ascii,\n"
2185 << indent <<
"no_row_counts=1\n"
2198 unsigned int pwi = 10;
2200 std::ofstream outfile;
2202 if (
comm_mp->getRank() == 0 ) {
2204 outfile.precision(15);
2205 outfile.setf(std::ios::scientific, std::ios::floatfield);
2207 if (
flag_m == std::ios::out ) {
2213 << this->
nIter_m << std::setw(pwi) <<
'\t'
2214 << this->
bIter_m << std::setw(pwi) <<
'\t'
2215 << this->
regrid_m << std::setw(pwi) <<
'\t'
2225void AmrMultiGrid::initTimer_m() {
2269 os <<
"* ********************* A M R M u l t i G r i d ********************** " <<
endl
2271 <<
"* ******************************************************************** " <<
endl;
#define OPAL_PROJECT_VERSION
#define OPAL_PROJECT_NAME
amr::AmrScalarFieldContainer_t AmrScalarFieldContainer_t
amr::AmrVectorFieldContainer_t AmrVectorFieldContainer_t
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
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)