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.
1402 {
1404
1405
1406
1407
1408
1413
1414
1415
1416 auto fe_domain_lhs = pip_mng->getDomainLhsFE();
1417 auto fe_domain_rhs = pip_mng->getDomainRhsFE();
1418 auto fe_bdy_lhs = pip_mng->getBoundaryLhsFE();
1419 auto fe_bdy_rhs = pip_mng->getBoundaryRhsFE();
1420
1421 pip_mng->getDomainLhsFE().reset();
1422 pip_mng->getDomainRhsFE().reset();
1423 pip_mng->getBoundaryLhsFE().reset();
1424 pip_mng->getBoundaryRhsFE().reset();
1425
1426 using UDO = ForcesAndSourcesCore::UserDataOperator;
1427
1428
1429 auto add_parent_field_domain = [&](
auto fe,
auto op,
auto field,
auto bit) {
1432
1433 [&]() {
1434 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1436 return fe_parent;
1437 },
1438
1440 };
1441
1442
1443 auto add_parent_field_bdy = [&](
auto fe,
auto op,
auto field,
auto bit) {
1446
1447 [&]() {
1448 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1450 return fe_parent;
1451 },
1452
1454 };
1455
1456
1457
1458 auto create_run_parent_op = [&](auto parent_fe_ptr, auto this_fe_ptr,
1459 auto fe_bit) {
1460 auto parent_mask = fe_bit;
1461 parent_mask.flip();
1464 Sev::inform);
1465 };
1466
1467
1468 auto get_parents_vel_fe_ptr = [&](auto this_fe_ptr, auto fe_bit) {
1469 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
1471 parents_elems_ptr_vec.emplace_back(
1472 boost::make_shared<DomainParentEle>(
mField));
1474 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
1475 create_run_parent_op(parents_elems_ptr_vec[
l], this_fe_ptr, fe_bit));
1476 }
1477 return parents_elems_ptr_vec[0];
1478 };
1479
1480
1481 auto solve_projection = [&](auto exe_test) {
1483
1484 auto set_domain_rhs = [&](auto fe) {
1486 auto &pip = fe->getOpPtrVector();
1487
1488 auto u_ptr = boost::make_shared<MatrixDouble>();
1489 auto p_ptr = boost::make_shared<VectorDouble>();
1490 auto h_ptr = boost::make_shared<VectorDouble>();
1491 auto g_ptr = boost::make_shared<VectorDouble>();
1492
1493 auto eval_fe_ptr = boost::make_shared<DomainParentEle>(
mField);
1494 {
1495 auto &pip = eval_fe_ptr->getOpPtrVector();
1499
1500 [&]() {
1501 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1503 return fe_parent;
1504 },
1505
1507
1508
1509 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPCOL,
"U",
1512 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPCOL,
"P",
1515 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPCOL,
"H",
1518 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPCOL,
"G",
1521 }
1522 auto parent_eval_fe_ptr =
1524 pip.push_back(create_run_parent_op(parent_eval_fe_ptr, eval_fe_ptr,
1526
1527 auto assemble_fe_ptr = boost::make_shared<DomainParentEle>(
mField);
1528 {
1529 auto &pip = assemble_fe_ptr->getOpPtrVector();
1533
1534 [&]() {
1535 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1537 return fe_parent;
1538 },
1539
1541 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"U",
1544 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"P",
1547 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"H",
1550 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"G",
1553 }
1554 auto parent_assemble_fe_ptr =
1556 pip.push_back(create_run_parent_op(
1558
1560 };
1561
1562 auto set_domain_lhs = [&](auto fe) {
1564
1565 auto &pip = fe->getOpPtrVector();
1566
1568
1571
1572 [&]() {
1573 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1575 return fe_parent;
1576 },
1577
1579
1580
1581
1582 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"U",
1584 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"U",
1587 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"P",
1589 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"P",
1592 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"H",
1594 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"H",
1597 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"G",
1599 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"G",
1602
1604 };
1605
1606 auto set_bdy_rhs = [&](auto fe) {
1608 auto &pip = fe->getOpPtrVector();
1609
1610 auto l_ptr = boost::make_shared<VectorDouble>();
1611
1612 auto eval_fe_ptr = boost::make_shared<BoundaryParentEle>(
mField);
1613 {
1614 auto &pip = eval_fe_ptr->getOpPtrVector();
1617
1618 [&]() {
1619 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1621 return fe_parent;
1622 },
1623
1625
1626
1627 CHKERR add_parent_field_bdy(eval_fe_ptr, UDO::OPCOL,
"L",
1630 }
1631 auto parent_eval_fe_ptr =
1633 pip.push_back(create_run_parent_op(parent_eval_fe_ptr, eval_fe_ptr,
1635
1636 auto assemble_fe_ptr = boost::make_shared<BoundaryParentEle>(
mField);
1637 {
1638 auto &pip = assemble_fe_ptr->getOpPtrVector();
1641
1642 [&]() {
1643 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1645 return fe_parent;
1646 },
1647
1649
1651 OpLSize(boost::shared_ptr<VectorDouble> l_ptr)
1655 if (lPtr->size() != getGaussPts().size2()) {
1656 lPtr->resize(getGaussPts().size2());
1657 lPtr->clear();
1658 }
1660 }
1661
1662 private:
1663 boost::shared_ptr<VectorDouble> lPtr;
1664 };
1665
1666 pip.push_back(new OpLSize(l_ptr));
1667
1668 CHKERR add_parent_field_bdy(assemble_fe_ptr, UDO::OPROW,
"L",
1671 }
1672 auto parent_assemble_fe_ptr =
1674 pip.push_back(create_run_parent_op(
1676
1678 };
1679
1680 auto set_bdy_lhs = [&](auto fe) {
1682
1683 auto &pip = fe->getOpPtrVector();
1684
1687
1688 [&]() {
1689 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1691 return fe_parent;
1692 },
1693
1695
1696
1697
1698 CHKERR add_parent_field_bdy(fe, UDO::OPROW,
"L",
1700 CHKERR add_parent_field_bdy(fe, UDO::OPCOL,
"L",
1703
1705 };
1706
1708 auto level_ents_ptr = boost::make_shared<Range>();
1711
1712 auto get_prj_ents = [&]() {
1717 auto common_ents = intersect(prj_mesh, *level_ents_ptr);
1718 prj_mesh = subtract(unite(*level_ents_ptr, prj_mesh), common_ents)
1720
1721 return prj_mesh;
1722 };
1723
1724 auto prj_ents = get_prj_ents();
1725
1727
1728 auto rebuild = [&]() {
1731
1732 std::vector<std::string> fields{"U", "P", "H", "G", "L"};
1733 std::map<std::string, boost::shared_ptr<Range>> range_maps{
1734
1735 {"U", level_ents_ptr},
1736 {"P", level_ents_ptr},
1737 {"H", level_ents_ptr},
1738 {"G", level_ents_ptr},
1739 {"L", level_ents_ptr}
1740
1741 };
1742
1744 simple->getProblemName(), PETSC_TRUE,
1745 &range_maps, &range_maps);
1746
1747
1748 CHKERR prb_mng->partitionFiniteElements(
"SUB_SOLVER",
true, 0,
1750
1751 CHKERR prb_mng->partitionGhostDofsOnDistributedMesh(
"SUB_SOLVER");
1752
1754 };
1755
1756 MOFEM_LOG(
"FS", Sev::verbose) <<
"Create projection problem";
1757
1759
1760 auto dm =
simple->getDM();
1761 DM subdm;
1763 CHKERR DMSetType(subdm,
"DMMOFEM");
1766 }
1767
1768 MOFEM_LOG(
"FS", Sev::inform) <<
"Nothing to project";
1769
1771 };
1772
1773 auto create_dummy_dm = [&]() {
1776 simple->getProblemName().c_str(),
1778 "create dummy dm");
1779 return dummy_dm;
1780 };
1781
1782 auto subdm = create_subdm();
1783 if (subdm) {
1784
1785 pip_mng->getDomainRhsFE().reset();
1786 pip_mng->getDomainLhsFE().reset();
1787 pip_mng->getBoundaryRhsFE().reset();
1788 pip_mng->getBoundaryLhsFE().reset();
1793 pip_mng->getDomainLhsFE()->exeTestHook = exe_test;
1794 pip_mng->getDomainRhsFE()->exeTestHook = [](
FEMethod *fe_ptr) {
1796 };
1797 pip_mng->getBoundaryLhsFE()->exeTestHook = exe_test;
1798 pip_mng->getBoundaryRhsFE()->exeTestHook = [](
FEMethod *fe_ptr) {
1800 };
1801
1802 CHKERR set_domain_rhs(pip_mng->getCastDomainRhsFE());
1803 CHKERR set_domain_lhs(pip_mng->getCastDomainLhsFE());
1804 CHKERR set_bdy_rhs(pip_mng->getCastBoundaryRhsFE());
1805 CHKERR set_bdy_lhs(pip_mng->getCastBoundaryLhsFE());
1806
1809
1810 auto ksp = pip_mng->createKSP(subdm);
1811 CHKERR KSPSetFromOptions(ksp);
1813
1814
1815 auto get_norm = [&](auto x) {
1816 double nrm;
1817 CHKERR VecNorm(x, NORM_2, &nrm);
1818 return nrm;
1819 };
1820
1821
1822
1823
1824 auto zero_dofs = [](boost::shared_ptr<FieldEntity> ent_ptr) {
1826 for (
auto &
v : ent_ptr->getEntFieldData()) {
1828 }
1830 };
1831
1832 auto solve = [&](
auto S) {
1834 CHKERR VecZeroEntries(S);
1836 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
1837 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
1839 CHKERR VecGhostUpdateBegin(S, INSERT_VALUES, SCATTER_FORWARD);
1840 CHKERR VecGhostUpdateEnd(S, INSERT_VALUES, SCATTER_FORWARD);
1841
1842
1843
1845 };
1846
1847 MOFEM_LOG(
"FS", Sev::inform) <<
"Solve projection";
1849
1852 auto dummy_dm = create_dummy_dm();
1853
1854
1855
1856
1857 auto apply_restrict = [&]() {
1858 auto get_is = [](
auto v) {
1859 IS iy;
1860 auto create = [&]() {
1864 CHKERR VecGetOwnershipRange(
v, &ystart, NULL);
1865 CHKERR ISCreateStride(PETSC_COMM_SELF,
n, ystart, 1, &iy);
1867 };
1870 };
1871
1872 auto iy = get_is(glob_x);
1874
1876 DMSubDomainRestrict(
simple->getDM(), s, PETSC_NULLPTR, dummy_dm),
1877 "restrict");
1880 "get X0");
1882 DMGetNamedGlobalVector(dummy_dm, "TSTheta_Xdot", &Xdot),
1883 "get Xdot");
1884
1885 auto forward_ghost = [](
auto g) {
1887 CHKERR VecGhostUpdateBegin(
g, INSERT_VALUES, SCATTER_FORWARD);
1888 CHKERR VecGhostUpdateEnd(
g, INSERT_VALUES, SCATTER_FORWARD);
1890 };
1891
1894
1895 if constexpr (
debug) {
1897 << "Reverse restrict: X0 " << get_norm(X0) << " Xdot "
1898 << get_norm(Xdot);
1899 }
1900
1901 return std::vector<Vec>{X0, Xdot};
1902 };
1903
1904 auto ts_solver_vecs = apply_restrict();
1905
1906 if (ts_solver_vecs.size()) {
1907
1908 for (
auto v : ts_solver_vecs) {
1909 MOFEM_LOG(
"FS", Sev::inform) <<
"Solve projection vector";
1910
1912 SCATTER_REVERSE);
1914
1915 for (auto f : {"U", "P", "H", "G", "L"}) {
1916 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Zero field " <<
f;
1917 CHKERR field_blas->fieldLambdaOnEntities(zero_dofs, f);
1918 }
1919
1921 SCATTER_REVERSE);
1923 SCATTER_FORWARD);
1924
1925 MOFEM_LOG(
"FS", Sev::inform) <<
"Norm V " << get_norm(
v);
1926 }
1927
1928 CHKERR DMRestoreNamedGlobalVector(dummy_dm,
"TSTheta_X0",
1929 &ts_solver_vecs[0]);
1930 CHKERR DMRestoreNamedGlobalVector(dummy_dm,
"TSTheta_Xdot",
1931 &ts_solver_vecs[1]);
1932 }
1933
1934 for (auto f : {"U", "P", "H", "G", "L"}) {
1935 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Zero field " <<
f;
1936 CHKERR field_blas->fieldLambdaOnEntities(zero_dofs, f);
1937 }
1939 }
1940
1942 };
1943
1944
1945 auto post_proc = [&](auto exe_test) {
1947 auto post_proc_fe = boost::make_shared<PostProcEleDomain>(
mField);
1948 auto &pip = post_proc_fe->getOpPtrVector();
1949 post_proc_fe->exeTestHook = exe_test;
1950
1952
1955
1956 [&]() {
1957 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1960 fe_parent->getOpPtrVector(), {H1});
1961 return fe_parent;
1962 },
1963
1965
1967
1968 auto u_ptr = boost::make_shared<MatrixDouble>();
1969 auto p_ptr = boost::make_shared<VectorDouble>();
1970 auto h_ptr = boost::make_shared<VectorDouble>();
1971 auto g_ptr = boost::make_shared<VectorDouble>();
1972
1973 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPCOL,
"U",
1976 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPCOL,
"P",
1979 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPCOL,
"H",
1982 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPCOL,
"G",
1985
1986 post_proc_fe->getOpPtrVector().push_back(
1987
1988 new OpPPMap(post_proc_fe->getPostProcMesh(),
1989 post_proc_fe->getMapGaussPts(),
1990
1991 {{"P", p_ptr}, {"H", h_ptr}, {"G", g_ptr}},
1992
1993 {{"U", u_ptr}},
1994
1995 {},
1996
1997 {}
1998
1999 )
2000
2001 );
2002
2003 auto dm =
simple->getDM();
2005 CHKERR post_proc_fe->writeFile(
"out_projection.h5m");
2006
2008 };
2009
2012 });
2013
2014 if constexpr (
debug) {
2017 });
2018 }
2019
2020 fe_domain_lhs.swap(pip_mng->getDomainLhsFE());
2021 fe_domain_rhs.swap(pip_mng->getDomainRhsFE());
2022 fe_bdy_lhs.swap(pip_mng->getBoundaryLhsFE());
2023 fe_bdy_rhs.swap(pip_mng->getBoundaryRhsFE());
2024
2026}
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.