Project solution data between mesh levels.
Projects field data from coarse to fine mesh levels during refinement. Handles both time stepping vectors (for theta method) and regular fields. Uses L2 projection with mass matrix assembly.
1391 {
1393
1394
1395
1396
1397
1402
1403
1404
1405 auto fe_domain_lhs = pip_mng->getDomainLhsFE();
1406 auto fe_domain_rhs = pip_mng->getDomainRhsFE();
1407 auto fe_bdy_lhs = pip_mng->getBoundaryLhsFE();
1408 auto fe_bdy_rhs = pip_mng->getBoundaryRhsFE();
1409
1410 pip_mng->getDomainLhsFE().reset();
1411 pip_mng->getDomainRhsFE().reset();
1412 pip_mng->getBoundaryLhsFE().reset();
1413 pip_mng->getBoundaryRhsFE().reset();
1414
1415 using UDO = ForcesAndSourcesCore::UserDataOperator;
1416
1417
1418 auto add_parent_field_domain = [&](
auto fe,
auto op,
auto field,
auto bit) {
1421
1422 [&]() {
1423 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1425 return fe_parent;
1426 },
1427
1429 };
1430
1431
1432 auto add_parent_field_bdy = [&](
auto fe,
auto op,
auto field,
auto bit) {
1435
1436 [&]() {
1437 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1439 return fe_parent;
1440 },
1441
1443 };
1444
1445
1446
1447 auto create_run_parent_op = [&](auto parent_fe_ptr, auto this_fe_ptr,
1448 auto fe_bit) {
1449 auto parent_mask = fe_bit;
1450 parent_mask.flip();
1453 Sev::inform);
1454 };
1455
1456
1457 auto get_parents_vel_fe_ptr = [&](auto this_fe_ptr, auto fe_bit) {
1458 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
1460 parents_elems_ptr_vec.emplace_back(
1461 boost::make_shared<DomainParentEle>(
mField));
1463 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
1464 create_run_parent_op(parents_elems_ptr_vec[
l], this_fe_ptr, fe_bit));
1465 }
1466 return parents_elems_ptr_vec[0];
1467 };
1468
1469
1470 auto solve_projection = [&](auto exe_test) {
1472
1473 auto set_domain_rhs = [&](auto fe) {
1475 auto &pip = fe->getOpPtrVector();
1476
1477 auto u_ptr = boost::make_shared<MatrixDouble>();
1478 auto p_ptr = boost::make_shared<VectorDouble>();
1479 auto h_ptr = boost::make_shared<VectorDouble>();
1480 auto g_ptr = boost::make_shared<VectorDouble>();
1481
1482 auto eval_fe_ptr = boost::make_shared<DomainParentEle>(
mField);
1483 {
1484 auto &pip = eval_fe_ptr->getOpPtrVector();
1488
1489 [&]() {
1490 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1492 return fe_parent;
1493 },
1494
1496
1497
1498 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPROW,
"U",
1501 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPROW,
"P",
1504 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPROW,
"H",
1507 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPROW,
"G",
1510 }
1511 auto parent_eval_fe_ptr =
1513 pip.push_back(create_run_parent_op(parent_eval_fe_ptr, eval_fe_ptr,
1515
1516 auto assemble_fe_ptr = boost::make_shared<DomainParentEle>(
mField);
1517 {
1518 auto &pip = assemble_fe_ptr->getOpPtrVector();
1522
1523 [&]() {
1524 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1526 return fe_parent;
1527 },
1528
1530 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"U",
1533 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"P",
1536 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"H",
1539 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"G",
1542 }
1543 auto parent_assemble_fe_ptr =
1545 pip.push_back(create_run_parent_op(
1547
1549 };
1550
1551 auto set_domain_lhs = [&](auto fe) {
1553
1554 auto &pip = fe->getOpPtrVector();
1555
1557
1560
1561 [&]() {
1562 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1564 return fe_parent;
1565 },
1566
1568
1569
1570
1571 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"U",
1573 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"U",
1576 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"P",
1578 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"P",
1581 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"H",
1583 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"H",
1586 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"G",
1588 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"G",
1591
1593 };
1594
1595 auto set_bdy_rhs = [&](auto fe) {
1597 auto &pip = fe->getOpPtrVector();
1598
1599 auto l_ptr = boost::make_shared<VectorDouble>();
1600
1601 auto eval_fe_ptr = boost::make_shared<BoundaryParentEle>(
mField);
1602 {
1603 auto &pip = eval_fe_ptr->getOpPtrVector();
1606
1607 [&]() {
1608 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1610 return fe_parent;
1611 },
1612
1614
1615
1616 CHKERR add_parent_field_bdy(eval_fe_ptr, UDO::OPROW,
"L",
1619 }
1620 auto parent_eval_fe_ptr =
1622 pip.push_back(create_run_parent_op(parent_eval_fe_ptr, eval_fe_ptr,
1624
1625 auto assemble_fe_ptr = boost::make_shared<BoundaryParentEle>(
mField);
1626 {
1627 auto &pip = assemble_fe_ptr->getOpPtrVector();
1630
1631 [&]() {
1632 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1634 return fe_parent;
1635 },
1636
1638
1640 OpLSize(boost::shared_ptr<VectorDouble> l_ptr)
1644 if (lPtr->size() != getGaussPts().size2()) {
1645 lPtr->resize(getGaussPts().size2());
1646 lPtr->clear();
1647 }
1649 }
1650
1651 private:
1652 boost::shared_ptr<VectorDouble> lPtr;
1653 };
1654
1655 pip.push_back(new OpLSize(l_ptr));
1656
1657 CHKERR add_parent_field_bdy(assemble_fe_ptr, UDO::OPROW,
"L",
1660 }
1661 auto parent_assemble_fe_ptr =
1663 pip.push_back(create_run_parent_op(
1665
1667 };
1668
1669 auto set_bdy_lhs = [&](auto fe) {
1671
1672 auto &pip = fe->getOpPtrVector();
1673
1676
1677 [&]() {
1678 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1680 return fe_parent;
1681 },
1682
1684
1685
1686
1687 CHKERR add_parent_field_bdy(fe, UDO::OPROW,
"L",
1689 CHKERR add_parent_field_bdy(fe, UDO::OPCOL,
"L",
1692
1694 };
1695
1697 auto level_ents_ptr = boost::make_shared<Range>();
1700
1701 auto get_prj_ents = [&]() {
1706 auto common_ents = intersect(prj_mesh, *level_ents_ptr);
1707 prj_mesh = subtract(unite(*level_ents_ptr, prj_mesh), common_ents)
1709
1710 return prj_mesh;
1711 };
1712
1713 auto prj_ents = get_prj_ents();
1714
1716
1717 auto rebuild = [&]() {
1720
1721 std::vector<std::string> fields{"U", "P", "H", "G", "L"};
1722 std::map<std::string, boost::shared_ptr<Range>> range_maps{
1723
1724 {"U", level_ents_ptr},
1725 {"P", level_ents_ptr},
1726 {"H", level_ents_ptr},
1727 {"G", level_ents_ptr},
1728 {"L", level_ents_ptr}
1729
1730 };
1731
1733 simple->getProblemName(), PETSC_TRUE,
1734 &range_maps, &range_maps);
1735
1736
1737 CHKERR prb_mng->partitionFiniteElements(
"SUB_SOLVER",
true, 0,
1739
1740 CHKERR prb_mng->partitionGhostDofsOnDistributedMesh(
"SUB_SOLVER");
1741
1743 };
1744
1745 MOFEM_LOG(
"FS", Sev::verbose) <<
"Create projection problem";
1746
1748
1749 auto dm =
simple->getDM();
1750 DM subdm;
1752 CHKERR DMSetType(subdm,
"DMMOFEM");
1755 }
1756
1757 MOFEM_LOG(
"FS", Sev::inform) <<
"Nothing to project";
1758
1760 };
1761
1762 auto create_dummy_dm = [&]() {
1765 simple->getProblemName().c_str(),
1767 "create dummy dm");
1768 return dummy_dm;
1769 };
1770
1771 auto subdm = create_subdm();
1772 if (subdm) {
1773
1774 pip_mng->getDomainRhsFE().reset();
1775 pip_mng->getDomainLhsFE().reset();
1776 pip_mng->getBoundaryRhsFE().reset();
1777 pip_mng->getBoundaryLhsFE().reset();
1782 pip_mng->getDomainLhsFE()->exeTestHook = exe_test;
1783 pip_mng->getDomainRhsFE()->exeTestHook = [](
FEMethod *fe_ptr) {
1785 };
1786 pip_mng->getBoundaryLhsFE()->exeTestHook = exe_test;
1787 pip_mng->getBoundaryRhsFE()->exeTestHook = [](
FEMethod *fe_ptr) {
1789 };
1790
1791 CHKERR set_domain_rhs(pip_mng->getCastDomainRhsFE());
1792 CHKERR set_domain_lhs(pip_mng->getCastDomainLhsFE());
1793 CHKERR set_bdy_rhs(pip_mng->getCastBoundaryRhsFE());
1794 CHKERR set_bdy_lhs(pip_mng->getCastBoundaryLhsFE());
1795
1798
1799 auto ksp = pip_mng->createKSP(subdm);
1800 CHKERR KSPSetFromOptions(ksp);
1802
1803
1804 auto get_norm = [&](auto x) {
1805 double nrm;
1806 CHKERR VecNorm(x, NORM_2, &nrm);
1807 return nrm;
1808 };
1809
1810
1811
1812
1813 auto zero_dofs = [](boost::shared_ptr<FieldEntity> ent_ptr) {
1815 for (
auto &
v : ent_ptr->getEntFieldData()) {
1817 }
1819 };
1820
1821 auto solve = [&](
auto S) {
1823 CHKERR VecZeroEntries(S);
1825 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
1826 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
1828 CHKERR VecGhostUpdateBegin(S, INSERT_VALUES, SCATTER_FORWARD);
1829 CHKERR VecGhostUpdateEnd(S, INSERT_VALUES, SCATTER_FORWARD);
1830
1831
1832
1834 };
1835
1836 MOFEM_LOG(
"FS", Sev::inform) <<
"Solve projection";
1838
1841 auto dummy_dm = create_dummy_dm();
1842
1843
1844
1845
1846 auto apply_restrict = [&]() {
1847 auto get_is = [](
auto v) {
1848 IS iy;
1849 auto create = [&]() {
1853 CHKERR VecGetOwnershipRange(
v, &ystart, NULL);
1854 CHKERR ISCreateStride(PETSC_COMM_SELF,
n, ystart, 1, &iy);
1856 };
1859 };
1860
1861 auto iy = get_is(glob_x);
1863
1865 DMSubDomainRestrict(
simple->getDM(), s, PETSC_NULLPTR, dummy_dm),
1866 "restrict");
1869 "get X0");
1871 DMGetNamedGlobalVector(dummy_dm, "TSTheta_Xdot", &Xdot),
1872 "get Xdot");
1873
1874 auto forward_ghost = [](
auto g) {
1876 CHKERR VecGhostUpdateBegin(
g, INSERT_VALUES, SCATTER_FORWARD);
1877 CHKERR VecGhostUpdateEnd(
g, INSERT_VALUES, SCATTER_FORWARD);
1879 };
1880
1883
1884 if constexpr (
debug) {
1886 << "Reverse restrict: X0 " << get_norm(X0) << " Xdot "
1887 << get_norm(Xdot);
1888 }
1889
1890 return std::vector<Vec>{X0, Xdot};
1891 };
1892
1893 auto ts_solver_vecs = apply_restrict();
1894
1895 if (ts_solver_vecs.size()) {
1896
1897 for (
auto v : ts_solver_vecs) {
1898 MOFEM_LOG(
"FS", Sev::inform) <<
"Solve projection vector";
1899
1901 SCATTER_REVERSE);
1903
1904 for (auto f : {"U", "P", "H", "G", "L"}) {
1905 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Zero field " <<
f;
1906 CHKERR field_blas->fieldLambdaOnEntities(zero_dofs, f);
1907 }
1908
1910 SCATTER_REVERSE);
1912 SCATTER_FORWARD);
1913
1914 MOFEM_LOG(
"FS", Sev::inform) <<
"Norm V " << get_norm(
v);
1915 }
1916
1917 CHKERR DMRestoreNamedGlobalVector(dummy_dm,
"TSTheta_X0",
1918 &ts_solver_vecs[0]);
1919 CHKERR DMRestoreNamedGlobalVector(dummy_dm,
"TSTheta_Xdot",
1920 &ts_solver_vecs[1]);
1921 }
1922
1923 for (auto f : {"U", "P", "H", "G", "L"}) {
1924 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Zero field " <<
f;
1925 CHKERR field_blas->fieldLambdaOnEntities(zero_dofs, f);
1926 }
1928 }
1929
1931 };
1932
1933
1934 auto post_proc = [&](auto exe_test) {
1936 auto post_proc_fe = boost::make_shared<PostProcEleDomain>(
mField);
1937 auto &pip = post_proc_fe->getOpPtrVector();
1938 post_proc_fe->exeTestHook = exe_test;
1939
1941
1944
1945 [&]() {
1946 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1949 fe_parent->getOpPtrVector(), {H1});
1950 return fe_parent;
1951 },
1952
1954
1956
1957 auto u_ptr = boost::make_shared<MatrixDouble>();
1958 auto p_ptr = boost::make_shared<VectorDouble>();
1959 auto h_ptr = boost::make_shared<VectorDouble>();
1960 auto g_ptr = boost::make_shared<VectorDouble>();
1961
1962 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPROW,
"U",
1965 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPROW,
"P",
1968 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPROW,
"H",
1971 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPROW,
"G",
1974
1975 post_proc_fe->getOpPtrVector().push_back(
1976
1977 new OpPPMap(post_proc_fe->getPostProcMesh(),
1978 post_proc_fe->getMapGaussPts(),
1979
1980 {{"P", p_ptr}, {"H", h_ptr}, {"G", g_ptr}},
1981
1982 {{"U", u_ptr}},
1983
1984 {},
1985
1986 {}
1987
1988 )
1989
1990 );
1991
1992 auto dm =
simple->getDM();
1994 CHKERR post_proc_fe->writeFile(
"out_projection.h5m");
1995
1997 };
1998
2001 });
2002
2003 if constexpr (
debug) {
2006 });
2007 }
2008
2009 fe_domain_lhs.swap(pip_mng->getDomainLhsFE());
2010 fe_domain_rhs.swap(pip_mng->getDomainRhsFE());
2011 fe_bdy_lhs.swap(pip_mng->getBoundaryLhsFE());
2012 fe_bdy_rhs.swap(pip_mng->getBoundaryRhsFE());
2013
2015}
OpDomainMassH OpDomainMassG
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpBaseTimesVector< BASE_DIM, SPACE_DIM, 1 > OpDomainAssembleVector
FormsIntegrators< DomainEleOp >::Assembly< A >::BiLinearForm< I >::OpMass< BASE_DIM, 1 > OpDomainMassH
auto get_skin_projection_bit
auto get_global_size
Get global size across all processors.
FormsIntegrators< BoundaryEleOp >::Assembly< A >::BiLinearForm< I >::OpMass< BASE_DIM, 1 > OpBoundaryMassL
FormsIntegrators< BoundaryEleOp >::Assembly< A >::LinearForm< I >::OpBaseTimesScalar< BASE_DIM > OpBoundaryAssembleScalar
FormsIntegrators< DomainEleOp >::Assembly< A >::BiLinearForm< I >::OpMass< BASE_DIM, U_FIELD_DIM > OpDomainMassU
PetscErrorCode DMMoFEMCreateMoFEM(DM dm, MoFEM::Interface *m_field_ptr, const char problem_name[], const MoFEM::BitRefLevel bit_level, const MoFEM::BitRefLevel bit_mask=MoFEM::BitRefLevel().set())
Must be called by user to set MoFEM data structures.
MoFEMErrorCode buildSubProblem(const std::string out_name, const std::vector< std::string > &fields_row, const std::vector< std::string > &fields_col, const std::string main_problem, const bool square_matrix=true, const map< std::string, boost::shared_ptr< Range > > *entityMapRow=nullptr, const map< std::string, boost::shared_ptr< Range > > *entityMapCol=nullptr, int verb=VERBOSE)
build sub problem
const double n
refractive index of diffusive medium
const FTensor::Tensor2< T, Dim, Dim > Vec
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto createVecScatter(Vec x, IS ix, Vec y, IS iy)
Create a Vec Scatter object.
static PetscErrorCode solve(Mat mat, Vec x, Vec y)
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
Data on single entity (This is passed as argument to DataOperator::doWork)
Operator to execute finite element instance on parent element. This operator is typically used to pro...
Problem manager is used to build and partition problems.