24 #include <moab/SpatialLocator.hpp>
26 using namespace MoFEM;
32 #define BOOST_UBLAS_NDEBUG 1
38 #include <VolumeLengthQuality.hpp>
42 static char help[] =
"Testing moving weighted least square approximation"
46 MOFEM_LOG_CHANNEL("WORLD"); \
47 MOFEM_LOG_FUNCTION(); \
48 MOFEM_LOG_TAG("WORLD", "mwls_at_gauss_point");
54 bool CrackPropagation::parallelReadAndBroadcast =
60 int main(
int argc,
char *argv[]) {
61 const char param_file[] =
"param_file.petsc";
71 CHKERR PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"mwls_at_gauss_point",
75 CHKERR PetscOptionsBool(
"-test",
"test code",
"", test, &test, PETSC_NULL);
76 CHKERR PetscOptionsScalar(
"-young_modulus",
77 "fix nodes below given threshold",
"",
79 CHKERR PetscOptionsScalar(
"-poisson_ratio",
80 "fix nodes below given threshold",
"",
83 ierr = PetscOptionsEnd();
87 DMType dm_name =
"DMMOFEM";
97 Simple *simple_interface_ptr;
111 CHKERR m_field.
get_moab().get_entities_by_dimension(whole_mesh, 3, ents,
131 "MESH_NODE_POSITIONS");
133 CHKERR m_field.
loop_dofs(
"MESH_NODE_POSITIONS", ent_method_material2, 0);
138 boost::make_shared<NonlinearElasticElement>(m_field,
ELASTIC_TAG);
146 CHKERR it->getAttributeDataStructure(mydata);
147 int id = it->getMeshsetId();
150 meshset, MBTET, elastic_fe->setOfBlocks[
id].tEts,
true);
151 elastic_fe->setOfBlocks[id].iD = id;
153 elastic_fe->setOfBlocks[id].materialDoublePtr =
154 boost::make_shared<Hooke<double>>();
155 elastic_fe->setOfBlocks[id].materialAdoublePtr =
156 boost::make_shared<Hooke<adouble>>();
159 elastic_fe->commonData.spatialPositions =
"SPATIAL_POSITION";
160 elastic_fe->commonData.meshPositions =
"MESH_NODE_POSITIONS";
166 auto mwls_approx = boost::make_shared<MWLSApprox>(m_field);
181 CHKERR m_field.
get_moab().get_entities_by_type(whole_mesh, MBTET, tets,
188 std::vector<Tag> tag_handles;
190 CHKERR mwls_approx->mwlsMoab.tag_get_tags(tag_handles);
191 ublas::vector<Tag> tag_approx_handles(tag_handles.size());
192 ublas::matrix<Tag> tag_approx_handles_diff(3, tag_handles.size());
193 ublas::matrix<Tag> tag_approx_handles_diff_diff(9, tag_handles.size());
195 fill(def_vals, &def_vals[9], 0);
197 ublas::vector<Tag> tag_difference_handles(tag_handles.size());
198 double def_differece_vals[9];
199 fill(def_differece_vals, &def_differece_vals[9], 0);
201 ublas::vector<Tag> tag_error_handles(tag_handles.size());
202 double def_error_vals = 0;
204 ublas::vector<Tag> tag_hydro_static_error_handles(tag_handles.size());
205 double def_hydro_static_error_vals = 0;
207 ublas::vector<Tag> tag_deviatoric_difference_handles(
209 double def_deviatoric_differece_vals[9];
210 fill(def_deviatoric_differece_vals, &def_deviatoric_differece_vals[9],
213 ublas::vector<Tag> tag_deviatoric_error_handles(tag_handles.size());
214 double def_deviatoric_error_vals = 0;
217 for (
int t = 0;
t != tag_handles.size();
t++) {
220 CHKERR mwls_approx->mwlsMoab.tag_get_name(tag_handles[
t], name);
223 name.compare(
"RHO") != 0) {
227 Range ref_node_edges;
229 PetscBool
boolean = PETSC_FALSE;
231 auto error_volume_fe = boost::shared_ptr<CrackFrontElement>(
233 ref_node_edges, ref_element,
boolean));
237 error_volume_fe->meshPositionsFieldName =
"NONE";
238 error_volume_fe->addToRule = 0;
240 boost::shared_ptr<MatrixDouble> mat_pos_at_pts_ptr(
242 error_volume_fe->getOpPtrVector().push_back(
244 mat_pos_at_pts_ptr));
246 boost::shared_ptr<MatrixDouble> mat_grad_pos_at_pts_ptr(
249 error_volume_fe->getOpPtrVector().push_back(
251 mat_pos_at_pts_ptr, mat_grad_pos_at_pts_ptr,
255 boost::shared_ptr<VectorDouble> vec_gp_weights(
258 error_volume_fe->getOpPtrVector().push_back(
267 CHKERR mwls_approx->mwlsMoab.tag_get_handle(
269 CHKERR mwls_approx->getValuesToNodes(
th);
271 auto dm = simple_interface_ptr->
getDM();
276 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Pre-process tag data < %s >",
279 CHKERR mwls_approx->getValuesToNodes(tag_handles[
t]);
282 std::string approx_name =
"APPROX_" + name;
283 std::string approx_diff_name[] = {
"APPROX_DX_" + name,
285 "APPROX_DZ_" + name};
288 CHKERR mwls_approx->mwlsMoab.tag_get_length(tag_handles[
t],
291 CHKERR mwls_approx->mwlsMoab.tag_get_data_type(tag_handles[
t],
295 CHKERR moab.tag_get_handle(
296 approx_name.c_str(), length, data_type, th_approx,
297 MB_TAG_CREAT | MB_TAG_SPARSE, def_vals);
299 tag_approx_handles[
t] = th_approx;
300 for (
int d = 0;
d != 3;
d++) {
302 CHKERR moab.tag_get_handle(
303 approx_diff_name[
d].c_str(), length, data_type,
304 th_approx_diff, MB_TAG_CREAT | MB_TAG_SPARSE, def_vals);
305 tag_approx_handles_diff(
d,
t) = th_approx_diff;
308 std::string error_name =
"STRESS_ERROR";
311 CHKERR moab.tag_get_handle(error_name.c_str(), 1, data_type,
312 th_error, MB_TAG_CREAT | MB_TAG_SPARSE,
315 tag_error_handles[
t] = th_error;
317 std::string hydro_static_error_name =
"HYDRO_STATIC_ERROR";
319 Tag th_hydro_static_error;
320 CHKERR moab.tag_get_handle(hydro_static_error_name.c_str(), 1,
321 data_type, th_hydro_static_error,
322 MB_TAG_CREAT | MB_TAG_SPARSE,
323 &def_hydro_static_error_vals);
325 tag_hydro_static_error_handles[
t] = th_hydro_static_error;
327 std::string deviatoric_error_name =
"DEVIATORIC_ERROR";
329 Tag th_deviatoric_error;
330 CHKERR moab.tag_get_handle(deviatoric_error_name.c_str(), 1,
331 data_type, th_deviatoric_error,
332 MB_TAG_CREAT | MB_TAG_SPARSE,
333 &def_deviatoric_error_vals);
335 tag_deviatoric_error_handles[
t] = th_deviatoric_error;
340 if (name.compare(
"RHO") == 0) {
342 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Pre-process tag data < %s >",
345 CHKERR mwls_approx->getValuesToNodes(tag_handles[
t]);
346 std::string approx_name =
"RHO";
347 std::string approx_diff_name[] = {
348 "APPROX_DX_" + name,
"APPROX_DY_" + name,
"APPROX_DZ_" + name};
349 std::string approx_diff_diff_name[] = {
350 "APPROX_DX_DX_" + name,
"APPROX_DX_DY_" + name,
351 "APPROX_DX_DZ_" + name,
"APPROX_DY_DX_" + name,
352 "APPROX_DY_DY_" + name,
"APPROX_DY_DZ_" + name,
353 "APPROX_DZ_DX_" + name,
"APPROX_DZ_DY_" + name,
354 "APPROX_DZ_DZ_" + name};
356 CHKERR mwls_approx->mwlsMoab.tag_get_length(tag_handles[
t], length);
358 CHKERR mwls_approx->mwlsMoab.tag_get_data_type(tag_handles[
t],
362 CHKERR moab.tag_get_handle(approx_name.c_str(), length, data_type,
363 th_approx, MB_TAG_CREAT | MB_TAG_SPARSE,
365 tag_approx_handles[
t] = th_approx;
367 for (
int d = 0;
d != 3;
d++) {
369 CHKERR moab.tag_get_handle(
370 approx_diff_name[
d].c_str(), length, data_type,
371 th_approx_diff, MB_TAG_CREAT | MB_TAG_SPARSE, def_vals);
372 tag_approx_handles_diff(
d,
t) = th_approx_diff;
373 for (
int n = 0;
n != 3;
n++) {
374 Tag th_approx_diff_diff;
375 CHKERR moab.tag_get_handle(
376 approx_diff_diff_name[
d + 3 *
n].c_str(), length, data_type,
377 th_approx_diff_diff, MB_TAG_CREAT | MB_TAG_SPARSE,
379 tag_approx_handles_diff_diff(
d + 3 *
n,
t) =
387 CHKERR m_field.
get_moab().create_meshset(MESHSET_SET, part_meshset);
389 auto approx_and_eval_errors = [&](
auto &tets) {
392 double stress_sum = 0;
393 double stress_error_sum = 0;
394 double hydro_static_error_sum = 0;
395 double deviatoric_error_sum = 0;
396 double mesh_volume = 0;
397 double energy_sum = 0;
398 double energy_error_sum = 0;
400 std::string printing_name;
402 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab,
MYPCOMM_INDEX);
404 auto mwls_approximate = [&](
auto &tets) {
407 auto fe_error_eval = boost::make_shared<FEMethod>();
412 auto tet = fe_error_eval->numeredEntFiniteElementPtr->getEnt();
413 int rank = pcomm->rank();
414 CHKERR moab.tag_set_data(pcomm->part_tag(), &tet, 1, &rank);
415 CHKERR moab.add_entities(part_meshset, &tet, 1);
416 MOFEM_LOG(
"WORLD", Sev::noisy) << tet <<
" partition " << rank;
420 CHKERR moab.get_connectivity(tet, conn, num_nodes,
true);
422 CHKERR moab.get_coords(conn, num_nodes,
423 &*tet_coords.data().begin());
428 double coords[3] = {0, 0, 0};
429 for (
size_t n = 0;
n != num_nodes; ++
n)
430 for (
auto d : {0, 1, 2})
431 coords[
d] += tet_coords(
n,
d) / num_nodes;
434 CHKERR mwls_approx->getInfluenceNodes(coords);
436 CHKERR mwls_approx->calculateApproxCoeff(
true,
true);
437 CHKERR mwls_approx->evaluateApproxFun(coords);
438 CHKERR mwls_approx->evaluateFirstDiffApproxFun(coords,
true);
439 CHKERR mwls_approx->evaluateSecondDiffApproxFun(coords,
false);
445 for (
int t = 0;
t != tag_handles.size();
t++) {
447 CHKERR mwls_approx->mwlsMoab.tag_get_name(tag_handles[
t], name);
449 printing_name = name;
451 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Approximate tag < %s >",
455 CHKERR mwls_approx->getTagData(tag_handles[
t]);
457 const auto &vals = mwls_approx->getDataApprox();
459 const auto &diff_vals = mwls_approx->getDiffDataApprox();
461 double total_energy_value = 0;
462 double total_energy_error_value = 0;
463 double total_stress_value = 0;
464 double total_stress_error_value = 0;
465 double hydro_static_error_value = 0;
466 double deviatoric_error_value = 0;
468 CHKERR mwls_approx->getErrorAtNode(
469 tag_handles[
t], total_stress_value,
470 total_stress_error_value, hydro_static_error_value,
471 deviatoric_error_value, total_energy_value,
475 CHKERR moab.tag_set_data(tag_approx_handles[
t], &tet, 1,
476 &*vals.data().begin());
478 for (
int d = 0;
d != 3;
d++)
479 CHKERR moab.tag_set_data(tag_approx_handles_diff(
d,
t),
480 &tet, 1, &diff_vals(
d, 0));
483 total_stress_error_value =
484 sqrt(total_stress_error_value / total_stress_value);
485 CHKERR moab.tag_set_data(tag_error_handles[
t], &tet, 1,
486 &total_stress_error_value);
489 hydro_static_error_value =
490 sqrt(hydro_static_error_value / total_stress_value);
491 CHKERR moab.tag_set_data(tag_hydro_static_error_handles[
t],
492 &tet, 1, &hydro_static_error_value);
495 deviatoric_error_value =
496 sqrt(deviatoric_error_value / total_stress_value);
497 CHKERR moab.tag_set_data(tag_deviatoric_error_handles[
t],
498 &tet, 1, &deviatoric_error_value);
500 energy_sum += vol * total_energy_value;
501 energy_error_sum += vol * total_energy_error_value;
502 stress_sum += vol * total_stress_value;
503 stress_error_sum += vol * total_stress_error_value;
504 hydro_static_error_sum += vol * hydro_static_error_value;
505 deviatoric_error_sum += vol * deviatoric_error_value;
508 if (name.compare(
"RHO") == 0) {
511 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Approximate tag < %s >",
515 CHKERR mwls_approx->getTagData(tag_handles[
t]);
518 const auto &vals = mwls_approx->getDataApprox();
520 const auto &diff_vals = mwls_approx->getDiffDataApprox();
521 const auto &diff_diff_vals =
522 mwls_approx->getDiffDiffDataApprox();
524 CHKERR moab.tag_set_data(tag_approx_handles[
t], &tet, 1,
525 &*vals.data().begin());
527 for (
int d = 0;
d != 3;
d++) {
528 CHKERR moab.tag_set_data(tag_approx_handles_diff(
d,
t),
529 &tet, 1, &diff_vals(
d, 0));
530 for (
int n = 0;
n != 3;
n++) {
532 tag_approx_handles_diff_diff(
d + 3 *
n,
t), &tet, 1,
533 &diff_diff_vals(
d + 3 *
n, 0));
545 stress_error_sum = 0;
546 hydro_static_error_sum = 0;
547 deviatoric_error_sum = 0;
550 energy_error_sum = 0;
558 std::array<double, 7> data = {stress_sum,
560 hydro_static_error_sum,
561 deviatoric_error_sum,
565 constexpr std::array<int, 7> indices = {0, 1, 2, 3, 4, 5, 6};
568 CHKERR VecAssemblyBegin(petsc_vec);
569 CHKERR VecAssemblyEnd(petsc_vec);
571 CHKERR VecGetValues(petsc_vec, 7, indices.data(), data.data());
572 stress_sum = data[0];
573 stress_error_sum = data[1];
574 hydro_static_error_sum = data[2];
575 deviatoric_error_sum = data[3];
576 mesh_volume = data[4];
577 energy_sum = data[5];
578 energy_error_sum = data[6];
583 struct FEEvalError :
public FEMethod {
584 FEEvalError() =
default;
588 fe_error_eval->operatorHook = eval_error_op;
589 fe_error_eval->postProcessHook = post_proc;
591 auto dm = simple_interface_ptr->
getDM();
595 stress_sum = sqrt(stress_sum);
596 stress_error_sum = sqrt(stress_error_sum);
597 hydro_static_error_sum = sqrt(hydro_static_error_sum);
598 deviatoric_error_sum = sqrt(deviatoric_error_sum);
603 auto print_information_out = [&]() {
606 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Number of tetrahedrons < %d >",
609 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Mesh volume < %e > ",
611 MOFEM_LOG_C(
"WORLD", Sev::inform,
"Stress L2 norm < %e >",
614 "WORLD", Sev::inform,
615 "Stress error L2 norm <absolute> < %e > (relative) ( %e ) ",
616 stress_error_sum, stress_error_sum / stress_sum);
618 "Hydrostatic stress error L2 norm <absolute> < %e "
619 "> (relative) ( %e ) ",
620 hydro_static_error_sum,
621 hydro_static_error_sum / stress_sum);
623 "WORLD", Sev::inform,
624 "Deviator error L2 norm <absolute> < %e > (relative) ( %e ) ",
625 deviatoric_error_sum, deviatoric_error_sum / stress_sum);
627 "Energy norm <absolute> < %e > ", energy_sum);
629 "WORLD", Sev::inform,
630 "Energy norm error <absolute> < %e > (relative) ( %e ) ",
631 energy_error_sum, energy_error_sum / energy_sum);
636 CHKERR mwls_approximate(tets);
637 CHKERR print_information_out();
639 if (test == PETSC_TRUE) {
640 constexpr
double test_tol = 1e-6;
641 if ((stress_error_sum / stress_sum) > test_tol)
643 "Approximation of stress has big error %e",
644 stress_error_sum / stress_sum);
651 CHKERR approx_and_eval_errors(tets);
654 CHKERR moab.write_file(
"out_mwls.h5m",
"MOAB",
"PARALLEL=WRITE_PART",