8 #ifndef _MIX_TRANPORT_ELEMENT_HPP_
9 #define _MIX_TRANPORT_ELEMENT_HPP_
14 using namespace MoFEM;
71 : mField(m_field), feVol(m_field), feTri(m_field){};
95 ids.insert(ids.begin(), bcIndices.begin(), bcIndices.end());
98 ids.empty() ? PETSC_NULL : &ids[0],
99 PETSC_COPY_VALUES, &is_local);
100 CHKERR ISAllGather(is_local, is);
101 CHKERR ISDestroy(&is_local);
115 const double y,
const double z,
132 const double y,
const double z,
136 for (
int dd = 0;
dd < 3;
dd++) {
152 const double x,
const double y,
153 const double z,
double &value) {
169 const double y,
const double z,
184 std::map<int, BlockData>
214 const std::string &values_name) {
250 CHKERR it->getAttributeDataStructure(temp_data);
251 setOfBlocks[it->getMeshsetId()].cOnductivity =
252 temp_data.
data.Conductivity;
253 setOfBlocks[it->getMeshsetId()].cApacity = temp_data.
data.HeatCapacity;
255 it->meshset, MBTET, setOfBlocks[it->getMeshsetId()].tEts,
true);
257 setOfBlocks[it->getMeshsetId()].tEts, MBTET,
"MIX");
261 setOfBlocks[it->getMeshsetId()].tEts, 2,
false, skeleton,
262 moab::Interface::UNION);
312 ref_tets = subtract(ref_tets, done_tets);
326 ref_faces = subtract(ref_faces, done_faces);
362 std::vector<EntityHandle> &map_gauss_pts)
365 postProcMesh(post_proc_mesh), mapGaussPts(map_gauss_pts) {}
371 EntityHandle fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
373 CHKERR getVolumeFE()->mField.get_moab().tag_get_handle(
"ERROR_FLUX",
375 double *error_flux_ptr;
376 CHKERR getVolumeFE()->mField.get_moab().tag_get_by_ptr(
377 th_error_flux, &fe_ent, 1, (
const void **)&error_flux_ptr);
380 CHKERR getVolumeFE()->mField.get_moab().tag_get_handle(
"ERROR_DIV",
382 double *error_div_ptr;
383 CHKERR getVolumeFE()->mField.get_moab().tag_get_by_ptr(
384 th_error_div, &fe_ent, 1, (
const void **)&error_div_ptr);
387 CHKERR getVolumeFE()->mField.get_moab().tag_get_handle(
"ERROR_JUMP",
389 double *error_jump_ptr;
390 CHKERR getVolumeFE()->mField.get_moab().tag_get_by_ptr(
391 th_error_jump, &fe_ent, 1, (
const void **)&error_jump_ptr);
396 CHKERR postProcMesh.tag_get_handle(
397 "ERROR_FLUX", 1, MB_TYPE_DOUBLE, th_error_flux,
398 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val);
399 for (vector<EntityHandle>::iterator vit = mapGaussPts.begin();
400 vit != mapGaussPts.end(); vit++) {
401 CHKERR postProcMesh.tag_set_data(th_error_flux, &*vit, 1,
406 CHKERR postProcMesh.tag_get_handle(
407 "ERROR_DIV", 1, MB_TYPE_DOUBLE, th_error_div,
408 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val);
409 for (vector<EntityHandle>::iterator vit = mapGaussPts.begin();
410 vit != mapGaussPts.end(); vit++) {
411 CHKERR postProcMesh.tag_set_data(th_error_div, &*vit, 1,
416 CHKERR postProcMesh.tag_get_handle(
417 "ERROR_JUMP", 1, MB_TYPE_DOUBLE, th_error_jump,
418 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val);
419 for (vector<EntityHandle>::iterator vit = mapGaussPts.begin();
420 vit != mapGaussPts.end(); vit++) {
421 CHKERR postProcMesh.tag_set_data(th_error_jump, &*vit, 1,
441 auto values_ptr = boost::make_shared<VectorDouble>();
442 auto grad_ptr = boost::make_shared<MatrixDouble>();
443 auto flux_ptr = boost::make_shared<MatrixDouble>();
458 {{
"VALUES", values_ptr}},
460 {{
"GRAD", grad_ptr}, {
"FLUXES", flux_ptr}},
466 post_proc.getOpPtrVector().push_back(
new OpPostProc(
467 post_proc.getPostProcMesh(), post_proc.getMapGaussPts()));
471 CHKERR post_proc.writeFile(out_file.c_str());
482 ->createMPIAIJWithArrays<PetscGlobalIdx_mi_tag>(
"MIX", &Aij);
495 CHKERR MatZeroEntries(Aij);
497 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
498 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
499 CHKERR VecZeroEntries(D0);
500 CHKERR VecGhostUpdateBegin(D0, INSERT_VALUES, SCATTER_FORWARD);
501 CHKERR VecGhostUpdateEnd(D0, INSERT_VALUES, SCATTER_FORWARD);
503 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
504 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
507 "MIX",
COL,
D, INSERT_VALUES, SCATTER_REVERSE);
520 CHKERR VecGhostUpdateBegin(D0, INSERT_VALUES, SCATTER_REVERSE);
521 CHKERR VecGhostUpdateEnd(D0, INSERT_VALUES, SCATTER_REVERSE);
522 CHKERR VecAssemblyBegin(D0);
523 CHKERR VecAssemblyEnd(D0);
547 CHKERR MatAssemblyBegin(Aij, MAT_FINAL_ASSEMBLY);
548 CHKERR MatAssemblyEnd(Aij, MAT_FINAL_ASSEMBLY);
549 CHKERR VecGhostUpdateBegin(
F, ADD_VALUES, SCATTER_REVERSE);
550 CHKERR VecGhostUpdateEnd(
F, ADD_VALUES, SCATTER_REVERSE);
556 CHKERR VecNorm(
F, NORM_2, &nrm2_F);
557 PetscPrintf(PETSC_COMM_WORLD,
"nrm2_F = %6.4e\n", nrm2_F);
567 CHKERR getDirichletBCIndices(&essential_bc_ids);
568 CHKERR MatZeroRowsColumnsIS(Aij, essential_bc_ids, 1, D0,
F);
569 CHKERR ISDestroy(&essential_bc_ids);
579 CHKERR VecNorm(
F, NORM_2, &nrm2_F);
580 PetscPrintf(PETSC_COMM_WORLD,
"With BC nrm2_F = %6.4e\n", nrm2_F);
593 CHKERR KSPCreate(PETSC_COMM_WORLD, &solver);
594 CHKERR KSPSetOperators(solver, Aij, Aij);
595 CHKERR KSPSetFromOptions(solver);
598 CHKERR KSPDestroy(&solver);
602 CHKERR VecNorm(
D, NORM_2, &nrm2_D);
604 PetscPrintf(PETSC_COMM_WORLD,
"nrm2_D = %6.4e\n", nrm2_D);
606 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
607 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
611 "MIX",
COL,
D, INSERT_VALUES, SCATTER_REVERSE);
620 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
621 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
641 CHKERR VecGhostUpdateBegin(
F, ADD_VALUES, SCATTER_REVERSE);
642 CHKERR VecGhostUpdateEnd(
F, ADD_VALUES, SCATTER_REVERSE);
648 std::vector<int> ids;
649 ids.insert(ids.begin(), bcIndices.begin(), bcIndices.end());
650 std::vector<double> vals(ids.size(), 0);
658 CHKERR VecNorm(
F, NORM_2, &nrm2_F);
659 PetscPrintf(PETSC_COMM_WORLD,
"nrm2_F = %6.4e\n", nrm2_F);
660 const double eps = 1e-8;
697 "Nb dofs %d error flux^2 = %6.4e error div^2 = %6.4e error "
698 "jump^2 = %6.4e error tot^2 = %6.4e\n",
700 sumErrorJump, sumErrorFlux + sumErrorDiv + sumErrorJump);
732 const std::string flux_name, Mat aij,
Vec f)
734 flux_name, flux_name,
736 cTx(ctx), Aij(aij),
F(
f) {
759 if (Aij == PETSC_NULL)
765 EntityHandle fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
768 NN.resize(nb_row, nb_col,
false);
772 invK.resize(3, 3,
false);
775 &invK(0, 0), &invK(0, 1), &invK(0, 2), &invK(1, 0), &invK(1, 1),
776 &invK(1, 2), &invK(2, 0), &invK(2, 1), &invK(2, 2));
780 int nb_gauss_pts = row_data.
getN().size1();
781 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
783 double w = getGaussPts()(3, gg) * getVolume();
784 const double x = getCoordsAtGaussPts()(gg, 0);
785 const double y = getCoordsAtGaussPts()(gg, 1);
786 const double z = getCoordsAtGaussPts()(gg, 2);
789 for (
int kk = 0; kk != nb_row; kk++) {
794 t_row(
j) =
w * t_n_hdiv_row(
i) * t_inv_k(
i,
j);
795 for (
int ll = 0; ll != nb_col; ll++) {
796 NN(kk, ll) += t_row(
j) * t_n_hdiv_col(
j);
802 Mat
a = (Aij != PETSC_NULL) ? Aij : getFEMethod()->ts_B;
804 &col_data.
getIndices()[0], &NN(0, 0), ADD_VALUES);
806 if (row_side != col_side || row_type != col_type) {
807 transNN.resize(nb_col, nb_row);
808 noalias(transNN) = trans(NN);
833 EntityHandle fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
838 invK.resize(3, 3,
false);
843 &invK(0, 0), &invK(0, 1), &invK(0, 2), &invK(1, 0), &invK(1, 1),
844 &invK(1, 2), &invK(2, 0), &invK(2, 1), &invK(2, 2));
848 int nb_gauss_pts = data.
getN().size1();
849 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
850 double w = getGaussPts()(3, gg) * getVolume();
851 const double x = getCoordsAtGaussPts()(gg, 0);
852 const double y = getCoordsAtGaussPts()(gg, 1);
853 const double z = getCoordsAtGaussPts()(gg, 2);
855 for (
int ll = 0; ll != nb_row; ll++) {
856 Nf[ll] +=
w * t_n_hdiv(
i) * t_inv_k(
i,
j) * t_flux(
j);
877 string val_name_col,
Vec f)
897 divVec.resize(data.
getN().size2() / 3, 0);
898 if (divVec.size() != data.
getIndices().size()) {
900 "data inconsistency");
902 int nb_gauss_pts = data.
getN().size1();
908 for (; gg < nb_gauss_pts; gg++) {
909 double w = getGaussPts()(3, gg) * getVolume();
910 for (
auto &
v : divVec) {
911 v = t_base_diff_hdiv(
i,
i);
937 string flux_name_col, Mat aij,
Vec f)
939 val_name_row, flux_name_col,
941 cTx(ctx), Aij(aij),
F(
f) {
969 if (Aij == PETSC_NULL)
977 NN.resize(nb_row, nb_col);
979 divVec.resize(nb_col,
false);
984 int nb_gauss_pts = row_data.
getN().size1();
985 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
986 double w = getGaussPts()(3, gg) * getVolume();
987 for (
auto &
v : divVec) {
988 v = t_base_diff_hdiv(
i,
i);
991 noalias(NN) +=
w * outer_prod(row_data.
getN(gg), divVec);
994 &col_data.
getIndices()[0], &NN(0, 0), ADD_VALUES);
995 transNN.resize(nb_col, nb_row);
996 ublas::noalias(transNN) = -trans(NN);
1010 "data inconsistency");
1015 int nb_gauss_pts = data.
getN().size1();
1016 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
1017 double w = getGaussPts()(3, gg) * getVolume();
1045 EntityHandle fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1047 Nf.resize(nb_row,
false);
1049 int nb_gauss_pts = data.
getN().size1();
1050 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
1051 double w = getGaussPts()(3, gg) * getVolume();
1052 const double x = getCoordsAtGaussPts()(gg, 0);
1053 const double y = getCoordsAtGaussPts()(gg, 1);
1054 const double z = getCoordsAtGaussPts()(gg, 2);
1057 noalias(Nf) +=
w * data.
getN(gg) * flux;
1102 EntityHandle fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1105 int nb_gauss_pts = data.
getN().size1();
1106 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
1107 const double x = getCoordsAtGaussPts()(gg, 0);
1108 const double y = getCoordsAtGaussPts()(gg, 1);
1109 const double z = getCoordsAtGaussPts()(gg, 2);
1114 double w = getGaussPts()(2, gg) * 0.5;
1115 if (getNormalsAtGaussPts().size1() == (
unsigned int)nb_gauss_pts) {
1117 w * prod(data.
getVectorN<3>(gg), getNormalsAtGaussPts(gg)) *
1120 noalias(nF) +=
w * prod(data.
getVectorN<3>(gg), getNormal()) * value;
1123 Vec f = (
F != PETSC_NULL) ?
F : getFEMethod()->ts_F;
1125 &nF[0], ADD_VALUES);
1161 EntityHandle fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1163 int nb_gauss_pts = data.
getN().size1();
1164 if (3 * nb_dofs !=
static_cast<int>(data.
getN().size2())) {
1166 "wrong number of dofs");
1168 NN.resize(nb_dofs, nb_dofs);
1177 if (getNormalsAtGaussPts().size1() == (
unsigned int)nb_gauss_pts) {
1179 normal_ptr = &getNormalsAtGaussPts(0)[0];
1182 normal_ptr = &getNormal()[0];
1193 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
1196 const double x = getCoordsAtGaussPts()(gg, 0);
1197 const double y = getCoordsAtGaussPts()(gg, 1);
1198 const double z = getCoordsAtGaussPts()(gg, 2);
1205 double w = getGaussPts()(2, gg);
1207 nrm2 = sqrt(t_normal(
i) * t_normal(
i));
1212 for (
int ll = 0; ll != nb_dofs; ll++) {
1218 for (
int kk = 0; kk <= ll; kk++) {
1219 NN(ll, kk) +=
w * t_n_hdiv_row(
i) * t_n_hdiv_col(
i);
1223 Nf[ll] +=
w * t_n_hdiv_row(
i) * t_normal(
i) * flux / nrm2;
1228 if (getNormalsAtGaussPts().size1() == (
unsigned int)nb_gauss_pts) {
1230 nrm2 = sqrt(t_normal(
i) * t_normal(
i));
1241 CHKERR VecSetOption(cTx.
D0, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE);
1243 &*Nf.begin(), INSERT_VALUES);
1244 for (
int dd = 0;
dd != nb_dofs; ++
dd)
1260 const std::string val_name =
"VALUES")
1273 int nb_gauss_pts = data.
getN().size1();
1275 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
1293 const std::string val_name =
"VALUES")
1304 int nb_gauss_pts = data.
getDiffN().size1();
1306 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
1307 ublas::matrix_column<MatrixDouble> values_grad_at_gauss_pts(
1309 noalias(values_grad_at_gauss_pts) =
1337 int nb_gauss_pts = data.
getDiffN().size1();
1341 if (
type == MBTRI && side == 0) {
1345 divVec.resize(nb_dofs);
1350 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
1351 for (
auto &
v : divVec) {
1352 v = t_base_diff_hdiv(
i,
i);
1356 ublas::matrix_column<MatrixDouble> flux_at_gauss_pt(
1391 invK.resize(3, 3,
false);
1392 int nb_gauss_pts = data.
getN().size1();
1393 EntityHandle fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1395 Tag th_error_flux, th_error_div;
1397 "ERROR_FLUX", 1, MB_TYPE_DOUBLE, th_error_flux,
1398 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val);
1399 double *error_flux_ptr;
1401 th_error_flux, &fe_ent, 1, (
const void **)&error_flux_ptr);
1404 "ERROR_DIV", 1, MB_TYPE_DOUBLE, th_error_div,
1405 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val);
1406 double *error_div_ptr;
1408 th_error_div, &fe_ent, 1, (
const void **)&error_div_ptr);
1412 "ERROR_JUMP", 1, MB_TYPE_DOUBLE, th_error_jump,
1413 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val);
1414 double *error_jump_ptr;
1416 th_error_jump, &fe_ent, 1, (
const void **)&error_jump_ptr);
1417 *error_jump_ptr = 0;
1420 const double h = pow(getVolume() * 12 / std::sqrt(2), (
double)1 / 3);
1422 for (
int ff = 0; ff != 4; ff++) {
1425 double *error_face_jump_ptr;
1427 th_error_jump, &face, 1, (
const void **)&error_face_jump_ptr);
1428 *error_face_jump_ptr = (1 / sqrt(
h)) * sqrt(*error_face_jump_ptr);
1429 *error_face_jump_ptr = pow(*error_face_jump_ptr, 2);
1430 *error_jump_ptr += *error_face_jump_ptr;
1433 *error_flux_ptr = 0;
1435 deltaFlux.resize(3,
false);
1436 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
1437 double w = getGaussPts()(3, gg) * getVolume();
1438 const double x = getCoordsAtGaussPts()(gg, 0);
1439 const double y = getCoordsAtGaussPts()(gg, 1);
1440 const double z = getCoordsAtGaussPts()(gg, 2);
1447 ublas::matrix_column<MatrixDouble> flux_at_gauss_pt(
1449 ublas::matrix_column<MatrixDouble> values_grad_at_gauss_pts(
1451 noalias(deltaFlux) =
1452 prod(invK, flux_at_gauss_pt) + values_grad_at_gauss_pts;
1453 *error_flux_ptr +=
w * inner_prod(deltaFlux, deltaFlux);
1455 *error_div_ptr =
h * sqrt(*error_div_ptr);
1456 *error_div_ptr = pow(*error_div_ptr, 2);
1457 cTx.
errorMap[sqrt(*error_flux_ptr + *error_div_ptr + *error_jump_ptr)] =
1464 *error_jump_ptr * getVolume();
1500 int nb_gauss_pts = data.
getN().size1();
1501 valMap[getFaceSense()].resize(nb_gauss_pts);
1502 for (
int gg = 0; gg < nb_gauss_pts; gg++) {
1503 valMap[getFaceSense()][gg] =
1515 volSideFe(ctx.mField), cTx(ctx) {
1523 if (
type == MBTRI) {
1524 EntityHandle fe_ent = getNumeredEntFiniteElementPtr()->getEnt();
1529 "ERROR_JUMP", 1, MB_TYPE_DOUBLE, th_error_jump,
1530 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val);
1531 double *error_jump_ptr;
1533 th_error_jump, &fe_ent, 1, (
const void **)&error_jump_ptr);
1534 *error_jump_ptr = 0;
1539 if (cTx.
mField.
get_moab().contains_entities(essential_bc_meshset,
1547 CHKERR loopSideVolumes(
"MIX", volSideFe);
1550 int nb_gauss_pts = data.
getN().size1();
1553 if (valMap.size() == 1) {
1554 if (
static_cast<int>(valMap.begin()->second.size()) != nb_gauss_pts) {
1556 "wrong number of integration points");
1558 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
1559 const double x = getCoordsAtGaussPts()(gg, 0);
1560 const double y = getCoordsAtGaussPts()(gg, 1);
1561 const double z = getCoordsAtGaussPts()(gg, 2);
1564 double w = getGaussPts()(2, gg);
1565 if (
static_cast<int>(getNormalsAtGaussPts().size1()) ==
1567 w *= norm_2(getNormalsAtGaussPts(gg)) * 0.5;
1571 *error_jump_ptr +=
w * pow(value - valMap.begin()->second[gg], 2);
1573 }
else if (valMap.size() == 2) {
1574 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
1575 double w = getGaussPts()(2, gg);
1576 if (getNormalsAtGaussPts().size1() == (
unsigned int)nb_gauss_pts) {
1577 w *= norm_2(getNormalsAtGaussPts(gg)) * 0.5;
1581 double delta = valMap.at(1)[gg] - valMap.at(-1)[gg];
1582 *error_jump_ptr +=
w * pow(
delta, 2);
1586 "data inconsistency, wrong number of neighbors "
1587 "valMap.size() = %d",
1599 #endif //_MIX_TRANPORT_ELEMENT_HPP_