Dear Yves, Another thing that seems illogical to me is that geotrans_inv_convex::invert() returns convergence information, both as a return value and through a boolean argument "converged", with two possibly different values. Shouldn't we simplify this?
The reason that I am looking into this is because I am experiencing some geometric inversion failures which are due to too strict checks with IN_EPS/100. But I don't want to just change the threshold value, I would like to improve the robustness of this quite central function in general. Best regards Kostas On Sun, Apr 3, 2022 at 9:36 AM Konstantinos Poulios <logar...@googlemail.com> wrote: > Dear Yves, > > I assume this change > [image: image.png] > was not intentional, right? I cannot imagine why one would use a factor > equal to 2. > > Best regards > Kostas > > On Fri, Jun 15, 2018 at 5:14 PM Yves Renard <yves.ren...@insa-lyon.fr> > wrote: > >> branch: master >> commit 93ea20ccf0e03d841f600d928764a694a0047ab8 >> Author: Yves Renard <yves.ren...@insa-lyon.fr> >> Date: Fri Jun 15 16:34:52 2018 +0200 >> >> fix a problem in inverting transformation for pyramids >> --- >> src/bgeot_geotrans_inv.cc | 10 +++---- >> src/getfem/getfem_generic_assembly_tree.h | 5 ---- >> src/getfem_generic_assembly_compile_and_exec.cc | 35 >> ++++++++++++++++++------- >> 3 files changed, 29 insertions(+), 21 deletions(-) >> >> diff --git a/src/bgeot_geotrans_inv.cc b/src/bgeot_geotrans_inv.cc >> index f87e9df..f3fb9d0 100644 >> --- a/src/bgeot_geotrans_inv.cc >> +++ b/src/bgeot_geotrans_inv.cc >> @@ -227,6 +227,7 @@ namespace bgeot >> } >> >> if (res < res0) copy(storage.x_ref, x); >> + x *= 0.999888783; // For pyramid element to avoid the singularity >> } >> >> >> @@ -242,12 +243,11 @@ namespace bgeot >> auto res = vect_norm2(nonlinear_storage.diff); >> auto res0 = std::numeric_limits<scalar_type>::max(); >> double factor = 1.0; >> - auto cnt = 0; >> >> while (res > IN_EPS) { >> if ((abs(res - res0) < IN_EPS) || (factor < IN_EPS)) { >> - converged = false; >> - return point_in_convex(*pgt, x, res, IN_EPS); >> + converged = false; >> + return point_in_convex(*pgt, x, res, IN_EPS); >> } >> >> if (res > res0) { >> @@ -258,10 +258,9 @@ namespace bgeot >> factor *= 0.5; >> } >> else { >> - if (factor < 1.0) factor *= 2.0; >> + if (factor < 1.0-IN_EPS) factor = 2.0; >> res0 = res; >> } >> - >> pgt->poly_vector_grad(x, pc); >> update_B(); >> mult(transposed(B), nonlinear_storage.diff, >> nonlinear_storage.x_ref); >> @@ -271,7 +270,6 @@ namespace bgeot >> add(nonlinear_storage.x_real, scaled(xreal, -1.0), >> nonlinear_storage.diff); >> res = vect_norm2(nonlinear_storage.diff); >> - ++cnt; >> } >> >> return point_in_convex(*pgt, x, res, IN_EPS); >> diff --git a/src/getfem/getfem_generic_assembly_tree.h >> b/src/getfem/getfem_generic_assembly_tree.h >> index 9ca3bd9..18682c0 100644 >> --- a/src/getfem/getfem_generic_assembly_tree.h >> +++ b/src/getfem/getfem_generic_assembly_tree.h >> @@ -54,11 +54,6 @@ extern "C"{ >> } >> #endif >> >> -// #define GA_USES_BLAS // not so interesting, at least for debian blas >> - >> -// #define GA_DEBUG_INFO(a) { cout << a << endl; } >> -#define GA_DEBUG_INFO(a) >> - >> #define GA_DEBUG_ASSERT(a, b) GMM_ASSERT1(a, b) >> // #define GA_DEBUG_ASSERT(a, b) >> >> diff --git a/src/getfem_generic_assembly_compile_and_exec.cc >> b/src/getfem_generic_assembly_compile_and_exec.cc >> index 3212b25..5a77635 100644 >> --- a/src/getfem_generic_assembly_compile_and_exec.cc >> +++ b/src/getfem_generic_assembly_compile_and_exec.cc >> @@ -25,6 +25,13 @@ >> #include "getfem/getfem_generic_assembly_compile_and_exec.h" >> #include "getfem/getfem_generic_assembly_functions_and_operators.h" >> >> +// #define GA_USES_BLAS // not so interesting, at least for debian blas >> + >> +// #define GA_DEBUG_INFO(a) { cout << a << endl; } >> +#define GA_DEBUG_INFO(a) >> + >> + >> + >> namespace getfem { >> >> >> @@ -766,6 +773,7 @@ namespace getfem { >> virtual int exec() { >> GA_DEBUG_INFO("Instruction: value of test functions"); >> if (qdim == 1) { >> + GA_DEBUG_ASSERT(t.size() == Z.size(), "Wrong size for base >> vector"); >> std::copy(Z.begin(), Z.end(), t.begin()); >> } else { >> size_type target_dim = Z.sizes()[1]; >> @@ -3781,7 +3789,7 @@ namespace getfem { >> if (inin.pt_type) { >> if (cv != size_type(-1)) { >> inin.m->points_of_convex(cv, inin.G); >> - inin.ctx.change((inin.m)->trans_of_convex(cv), >> + inin.ctx.change((inin.m)->trans_of_convex(cv), >> 0, P_ref, inin.G, cv, face_num); >> inin.has_ctx = true; >> if (face_num != short_type(-1)) { >> @@ -3826,7 +3834,7 @@ namespace getfem { >> >> virtual int exec() { >> bool cancel_optimization = false; >> - GA_DEBUG_INFO("Instruction: call interpolate transformation"); >> + GA_DEBUG_INFO("Instruction: call interpolate neighbour >> transformation"); >> if (ipt == 0) { >> if (!(ctx.have_pgp()) || !pai || pai->is_built_on_the_fly() >> || cancel_optimization) { >> @@ -3873,7 +3881,7 @@ namespace getfem { >> gic.init(m.points_of_convex(adj_face.cv), gpc.pgt2); >> size_type first_ind = pai->ind_first_point_on_face(f); >> const bgeot::stored_point_tab >> - &spt = *(pai->pintegration_points()); >> + &spt = *(pai->pintegration_points()); >> base_matrix G; >> m.points_of_convex(cv, G); >> fem_interpolation_context ctx_x(gpc.pgt1, 0, spt[0], G, >> cv, f); >> @@ -3882,7 +3890,8 @@ namespace getfem { >> for (size_type i = 0; i < nbpt; ++i) { >> ctx_x.set_xref(spt[first_ind+i]); >> bool converged = true; >> - bool is_in = gic.invert(ctx_x.xreal(), >> P_ref[i],converged,1E-4); >> + gic.invert(ctx_x.xreal(), P_ref[i], converged); >> + bool is_in = (gpc.pgt2->convex_ref()->is_in(P_ref[i]) < >> 1E-4); >> GMM_ASSERT1(is_in && converged,"Geometric transformation >> " >> "inversion has failed in neighbour >> transformation"); >> } >> @@ -3936,7 +3945,8 @@ namespace getfem { >> inin.has_ctx = false; >> } >> } >> - GA_DEBUG_INFO("Instruction: end of call interpolate >> transformation"); >> + GA_DEBUG_INFO("Instruction: end of call neighbour interpolate " >> + "transformation"); >> return 0; >> } >> ga_instruction_neighbour_transformation_call >> @@ -4746,6 +4756,7 @@ namespace getfem { >> const mesh_fem **mfg1 = 0, **mfg2 = 0; >> fem_interpolation_context *pctx1 = 0, *pctx2 = 0; >> bool tensor_to_clear = false; >> + bool tensor_to_adapt = false; >> >> if (pnode->test_function_type) { >> if (pnode->name_test1.size()) >> @@ -4754,6 +4765,7 @@ namespace getfem { >> pctx1 = &(gis.ctx); >> const std::string &intn1 = pnode->interpolate_name_test1; >> if (intn1.size()) { >> + tensor_to_adapt = true; >> pctx1 = &(rmi.interpolate_infos[intn1].ctx); >> if (workspace.variable_group_exists(pnode->name_test1)) { >> ga_instruction_set::variable_group_info &vgi = >> @@ -4769,6 +4781,7 @@ namespace getfem { >> pctx2 = &(gis.ctx); >> const std::string &intn2 = pnode->interpolate_name_test2; >> if (intn2.size()) { >> + tensor_to_adapt = true; >> pctx2 = &(rmi.interpolate_infos[intn2].ctx); >> if (workspace.variable_group_exists(pnode->name_test2)) { >> ga_instruction_set::variable_group_info &vgi = >> @@ -4781,7 +4794,7 @@ namespace getfem { >> } >> >> // Produce a resize instruction which is stored if no equivalent >> node is >> - // detected and is the mesh is not uniform. >> + // detected and if the mesh is not uniform. >> pnode->t.set_to_original(); pnode->t.set_sparsity(0, 0); >> bool is_uniform = false; >> if (pnode->test_function_type == 1) { >> @@ -4825,9 +4838,9 @@ namespace getfem { >> std::list<pga_tree_node> &node_list = >> rmi.node_list[pnode->hash_value]; >> for (std::list<pga_tree_node>::iterator it = node_list.begin(); >> it != node_list.end(); ++it) { >> - // cout << "found potential equivalent nodes "; >> - // ga_print_node(pnode, cout); >> - // cout << " and "; ga_print_node(*it, cout); cout << endl; >> + // cout << "found potential equivalent nodes "; >> + // ga_print_node(pnode, cout); >> + // cout << " and "; ga_print_node(*it, cout); cout << endl; >> if (sub_tree_are_equal(pnode, *it, workspace, 1)) { >> pnode->t.set_to_copy((*it)->t); >> return; >> @@ -4843,6 +4856,8 @@ namespace getfem { >> pgai = std::make_shared<ga_instruction_transpose_test> >> (pnode->tensor(), (*it)->tensor()); >> rmi.instructions.push_back(std::move(pgai)); >> + GMM_ASSERT1(false, >> + "No use of X is allowed in scalar functions"); >> } else { >> pnode->t.set_to_copy((*it)->t); >> } >> @@ -4860,7 +4875,7 @@ namespace getfem { >> if (pgai) { // resize instruction if needed and no equivalent node >> detected >> if (is_uniform) { pgai->exec(); } >> else { >> - if (mfg1 || mfg2) >> + if (tensor_to_adapt) >> rmi.instructions.push_back(std::move(pgai)); >> else >> rmi.elt_instructions.push_back(std::move(pgai)); >> >>