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.
1407 {
1409
1410
1411
1412
1413
1418
1419
1420
1421 auto fe_domain_lhs = pip_mng->getDomainLhsFE();
1422 auto fe_domain_rhs = pip_mng->getDomainRhsFE();
1423 auto fe_bdy_lhs = pip_mng->getBoundaryLhsFE();
1424 auto fe_bdy_rhs = pip_mng->getBoundaryRhsFE();
1425
1426 pip_mng->getDomainLhsFE().reset();
1427 pip_mng->getDomainRhsFE().reset();
1428 pip_mng->getBoundaryLhsFE().reset();
1429 pip_mng->getBoundaryRhsFE().reset();
1430
1431 using UDO = ForcesAndSourcesCore::UserDataOperator;
1432
1433
1434 auto add_parent_field_domain = [&](
auto fe,
auto op,
auto field,
auto bit) {
1437
1438 [&]() {
1439 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1441 return fe_parent;
1442 },
1443
1445 };
1446
1447
1448 auto add_parent_field_bdy = [&](
auto fe,
auto op,
auto field,
auto bit) {
1451
1452 [&]() {
1453 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1455 return fe_parent;
1456 },
1457
1459 };
1460
1461
1462
1463 auto create_run_parent_op = [&](auto parent_fe_ptr, auto this_fe_ptr,
1464 auto fe_bit) {
1465 auto parent_mask = fe_bit;
1466 parent_mask.flip();
1469 Sev::inform);
1470 };
1471
1472
1473 auto get_parents_vel_fe_ptr = [&](auto this_fe_ptr, auto fe_bit) {
1474 std::vector<boost::shared_ptr<DomainParentEle>> parents_elems_ptr_vec;
1476 parents_elems_ptr_vec.emplace_back(
1477 boost::make_shared<DomainParentEle>(
mField));
1479 parents_elems_ptr_vec[
l - 1]->getOpPtrVector().push_back(
1480 create_run_parent_op(parents_elems_ptr_vec[
l], this_fe_ptr, fe_bit));
1481 }
1482 return parents_elems_ptr_vec[0];
1483 };
1484
1485
1486 auto solve_projection = [&](auto exe_test) {
1488
1489 auto set_domain_rhs = [&](auto fe) {
1491 auto &pip = fe->getOpPtrVector();
1492
1493 auto u_ptr = boost::make_shared<MatrixDouble>();
1494 auto p_ptr = boost::make_shared<VectorDouble>();
1495 auto h_ptr = boost::make_shared<VectorDouble>();
1496 auto g_ptr = boost::make_shared<VectorDouble>();
1497
1498 auto eval_fe_ptr = boost::make_shared<DomainParentEle>(
mField);
1499 {
1500 auto &pip = eval_fe_ptr->getOpPtrVector();
1504
1505 [&]() {
1506 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1508 return fe_parent;
1509 },
1510
1512
1513
1514 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPCOL,
"U",
1517 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPCOL,
"P",
1520 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPCOL,
"H",
1523 CHKERR add_parent_field_domain(eval_fe_ptr, UDO::OPCOL,
"G",
1526 }
1527 auto parent_eval_fe_ptr =
1529 pip.push_back(create_run_parent_op(parent_eval_fe_ptr, eval_fe_ptr,
1531
1532 auto assemble_fe_ptr = boost::make_shared<DomainParentEle>(
mField);
1533 {
1534 auto &pip = assemble_fe_ptr->getOpPtrVector();
1538
1539 [&]() {
1540 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1542 return fe_parent;
1543 },
1544
1546 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"U",
1549 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"P",
1552 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"H",
1555 CHKERR add_parent_field_domain(assemble_fe_ptr, UDO::OPROW,
"G",
1558 }
1559 auto parent_assemble_fe_ptr =
1561 pip.push_back(create_run_parent_op(
1563
1565 };
1566
1567 auto set_domain_lhs = [&](auto fe) {
1569
1570 auto &pip = fe->getOpPtrVector();
1571
1573
1576
1577 [&]() {
1578 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1580 return fe_parent;
1581 },
1582
1584
1585
1586
1587 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"U",
1589 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"U",
1592 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"P",
1594 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"P",
1597 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"H",
1599 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"H",
1602 CHKERR add_parent_field_domain(fe, UDO::OPROW,
"G",
1604 CHKERR add_parent_field_domain(fe, UDO::OPCOL,
"G",
1607
1609 };
1610
1611 auto set_bdy_rhs = [&](auto fe) {
1613 auto &pip = fe->getOpPtrVector();
1614
1615 auto l_ptr = boost::make_shared<VectorDouble>();
1616
1617 auto eval_fe_ptr = boost::make_shared<BoundaryParentEle>(
mField);
1618 {
1619 auto &pip = eval_fe_ptr->getOpPtrVector();
1622
1623 [&]() {
1624 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1626 return fe_parent;
1627 },
1628
1630
1631
1632 CHKERR add_parent_field_bdy(eval_fe_ptr, UDO::OPCOL,
"L",
1635 }
1636 auto parent_eval_fe_ptr =
1638 pip.push_back(create_run_parent_op(parent_eval_fe_ptr, eval_fe_ptr,
1640
1641 auto assemble_fe_ptr = boost::make_shared<BoundaryParentEle>(
mField);
1642 {
1643 auto &pip = assemble_fe_ptr->getOpPtrVector();
1646
1647 [&]() {
1648 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1650 return fe_parent;
1651 },
1652
1654
1656 OpLSize(boost::shared_ptr<VectorDouble> l_ptr)
1660 if (lPtr->size() != getGaussPts().size2()) {
1661 lPtr->resize(getGaussPts().size2());
1662 lPtr->clear();
1663 }
1665 }
1666
1667 private:
1668 boost::shared_ptr<VectorDouble> lPtr;
1669 };
1670
1671 pip.push_back(new OpLSize(l_ptr));
1672
1673 CHKERR add_parent_field_bdy(assemble_fe_ptr, UDO::OPROW,
"L",
1676 }
1677 auto parent_assemble_fe_ptr =
1679 pip.push_back(create_run_parent_op(
1681
1683 };
1684
1685 auto set_bdy_lhs = [&](auto fe) {
1687
1688 auto &pip = fe->getOpPtrVector();
1689
1692
1693 [&]() {
1694 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1696 return fe_parent;
1697 },
1698
1700
1701
1702
1703 CHKERR add_parent_field_bdy(fe, UDO::OPROW,
"L",
1705 CHKERR add_parent_field_bdy(fe, UDO::OPCOL,
"L",
1708
1710 };
1711
1713 auto level_ents_ptr = boost::make_shared<Range>();
1716
1717 auto get_prj_ents = [&]() {
1722 auto common_ents = intersect(prj_mesh, *level_ents_ptr);
1723 prj_mesh = subtract(unite(*level_ents_ptr, prj_mesh), common_ents)
1725
1726 return prj_mesh;
1727 };
1728
1729 auto prj_ents = get_prj_ents();
1730
1732
1733 auto rebuild = [&]() {
1736
1737 std::vector<std::string> fields{"U", "P", "H", "G", "L"};
1738 std::map<std::string, boost::shared_ptr<Range>> range_maps{
1739
1740 {"U", level_ents_ptr},
1741 {"P", level_ents_ptr},
1742 {"H", level_ents_ptr},
1743 {"G", level_ents_ptr},
1744 {"L", level_ents_ptr}
1745
1746 };
1747
1749 simple->getProblemName(), PETSC_TRUE,
1750 &range_maps, &range_maps);
1751
1752
1753 CHKERR prb_mng->partitionFiniteElements(
"SUB_SOLVER",
true, 0,
1755
1756 CHKERR prb_mng->partitionGhostDofsOnDistributedMesh(
"SUB_SOLVER");
1757
1759 };
1760
1761 MOFEM_LOG(
"FS", Sev::verbose) <<
"Create projection problem";
1762
1764
1765 auto dm =
simple->getDM();
1766 DM subdm;
1768 CHKERR DMSetType(subdm,
"DMMOFEM");
1771 }
1772
1773 MOFEM_LOG(
"FS", Sev::inform) <<
"Nothing to project";
1774
1776 };
1777
1778 auto create_dummy_dm = [&]() {
1781 simple->getProblemName().c_str(),
1783 "create dummy dm");
1784 return dummy_dm;
1785 };
1786
1787 auto subdm = create_subdm();
1788 if (subdm) {
1789
1790 pip_mng->getDomainRhsFE().reset();
1791 pip_mng->getDomainLhsFE().reset();
1792 pip_mng->getBoundaryRhsFE().reset();
1793 pip_mng->getBoundaryLhsFE().reset();
1798 pip_mng->getDomainLhsFE()->exeTestHook = exe_test;
1799 pip_mng->getDomainRhsFE()->exeTestHook = [](
FEMethod *fe_ptr) {
1801 };
1802 pip_mng->getBoundaryLhsFE()->exeTestHook = exe_test;
1803 pip_mng->getBoundaryRhsFE()->exeTestHook = [](
FEMethod *fe_ptr) {
1805 };
1806
1807 CHKERR set_domain_rhs(pip_mng->getCastDomainRhsFE());
1808 CHKERR set_domain_lhs(pip_mng->getCastDomainLhsFE());
1809 CHKERR set_bdy_rhs(pip_mng->getCastBoundaryRhsFE());
1810 CHKERR set_bdy_lhs(pip_mng->getCastBoundaryLhsFE());
1811
1814
1815 auto ksp = pip_mng->createKSP(subdm);
1816 CHKERR KSPSetFromOptions(ksp);
1818
1819
1820 auto get_norm = [&](auto x) {
1821 double nrm;
1822 CHKERR VecNorm(x, NORM_2, &nrm);
1823 return nrm;
1824 };
1825
1826
1827
1828
1829 auto zero_dofs = [](boost::shared_ptr<FieldEntity> ent_ptr) {
1831 for (
auto &
v : ent_ptr->getEntFieldData()) {
1833 }
1835 };
1836
1837 auto solve = [&](
auto S) {
1839 CHKERR VecZeroEntries(S);
1841 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
1842 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
1844 CHKERR VecGhostUpdateBegin(S, INSERT_VALUES, SCATTER_FORWARD);
1845 CHKERR VecGhostUpdateEnd(S, INSERT_VALUES, SCATTER_FORWARD);
1846
1847
1848
1850 };
1851
1852 MOFEM_LOG(
"FS", Sev::inform) <<
"Solve projection";
1854
1857 auto dummy_dm = create_dummy_dm();
1858
1859
1860
1861
1862 auto apply_restrict = [&]() {
1863 auto get_is = [](
auto v) {
1864 IS iy;
1865 auto create = [&]() {
1869 CHKERR VecGetOwnershipRange(
v, &ystart, NULL);
1870 CHKERR ISCreateStride(PETSC_COMM_SELF,
n, ystart, 1, &iy);
1872 };
1875 };
1876
1877 auto iy = get_is(glob_x);
1879
1881 DMSubDomainRestrict(
simple->getDM(), s, PETSC_NULLPTR, dummy_dm),
1882 "restrict");
1885 "get X0");
1887 DMGetNamedGlobalVector(dummy_dm, "TSTheta_Xdot", &Xdot),
1888 "get Xdot");
1889
1890 auto forward_ghost = [](
auto g) {
1892 CHKERR VecGhostUpdateBegin(
g, INSERT_VALUES, SCATTER_FORWARD);
1893 CHKERR VecGhostUpdateEnd(
g, INSERT_VALUES, SCATTER_FORWARD);
1895 };
1896
1899
1900 if constexpr (
debug) {
1902 << "Reverse restrict: X0 " << get_norm(X0) << " Xdot "
1903 << get_norm(Xdot);
1904 }
1905
1906 return std::vector<Vec>{X0, Xdot};
1907 };
1908
1909 auto ts_solver_vecs = apply_restrict();
1910
1911 if (ts_solver_vecs.size()) {
1912
1913 for (
auto v : ts_solver_vecs) {
1914 MOFEM_LOG(
"FS", Sev::inform) <<
"Solve projection vector";
1915
1917 SCATTER_REVERSE);
1919
1920 for (auto f : {"U", "P", "H", "G", "L"}) {
1921 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Zero field " <<
f;
1922 CHKERR field_blas->fieldLambdaOnEntities(zero_dofs, f);
1923 }
1924
1926 SCATTER_REVERSE);
1928 SCATTER_FORWARD);
1929
1930 MOFEM_LOG(
"FS", Sev::inform) <<
"Norm V " << get_norm(
v);
1931 }
1932
1933 CHKERR DMRestoreNamedGlobalVector(dummy_dm,
"TSTheta_X0",
1934 &ts_solver_vecs[0]);
1935 CHKERR DMRestoreNamedGlobalVector(dummy_dm,
"TSTheta_Xdot",
1936 &ts_solver_vecs[1]);
1937 }
1938
1939 for (auto f : {"U", "P", "H", "G", "L"}) {
1940 MOFEM_LOG(
"WORLD", Sev::verbose) <<
"Zero field " <<
f;
1941 CHKERR field_blas->fieldLambdaOnEntities(zero_dofs, f);
1942 }
1944 }
1945
1947 };
1948
1949
1950 auto post_proc = [&](auto exe_test) {
1952 auto post_proc_fe = boost::make_shared<PostProcEleDomain>(
mField);
1953 auto &pip = post_proc_fe->getOpPtrVector();
1954 post_proc_fe->exeTestHook = exe_test;
1955
1957
1960
1961 [&]() {
1962 boost::shared_ptr<ForcesAndSourcesCore> fe_parent(
1965 fe_parent->getOpPtrVector(), {H1});
1966 return fe_parent;
1967 },
1968
1970
1972
1973 auto u_ptr = boost::make_shared<MatrixDouble>();
1974 auto p_ptr = boost::make_shared<VectorDouble>();
1975 auto h_ptr = boost::make_shared<VectorDouble>();
1976 auto g_ptr = boost::make_shared<VectorDouble>();
1977
1978 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPCOL,
"U",
1981 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPCOL,
"P",
1984 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPCOL,
"H",
1987 CHKERR add_parent_field_domain(post_proc_fe, UDO::OPCOL,
"G",
1990
1991 post_proc_fe->getOpPtrVector().push_back(
1992
1993 new OpPPMap(post_proc_fe->getPostProcMesh(),
1994 post_proc_fe->getMapGaussPts(),
1995
1996 {{"P", p_ptr}, {"H", h_ptr}, {"G", g_ptr}},
1997
1998 {{"U", u_ptr}},
1999
2000 {},
2001
2002 {}
2003
2004 )
2005
2006 );
2007
2008 auto dm =
simple->getDM();
2010 CHKERR post_proc_fe->writeFile(
"out_projection.h5m");
2011
2013 };
2014
2017 });
2018
2019 if constexpr (
debug) {
2022 });
2023 }
2024
2025 fe_domain_lhs.swap(pip_mng->getDomainLhsFE());
2026 fe_domain_rhs.swap(pip_mng->getDomainRhsFE());
2027 fe_bdy_lhs.swap(pip_mng->getBoundaryLhsFE());
2028 fe_bdy_rhs.swap(pip_mng->getBoundaryRhsFE());
2029
2031}
OpDomainMassH OpDomainMassG
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpBaseTimesVector< BASE_DIM, SPACE_DIM, SPACE_DIM > 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.