24 #include "getfem/getfem_generic_assembly_compile_and_exec.h"
25 #include "getfem/getfem_generic_assembly_functions_and_operators.h"
34 void ga_interpolation(ga_workspace &workspace,
35 ga_interpolation_context &gic) {
36 ga_instruction_set gis;
37 ga_compile_interpolation(workspace, gis);
38 ga_interpolation_exec(gis, workspace, gic);
42 struct ga_interpolation_context_fem_same_mesh
43 :
public ga_interpolation_context {
45 std::vector<int> dof_count;
51 virtual bgeot::pstored_point_tab
53 std::vector<size_type> &ind)
const {
54 pfem pf = mf.fem_of_element(cv);
55 GMM_ASSERT1(pf->is_lagrange(),
56 "Only Lagrange fems can be used in interpolation");
61 i < pf->node_convex(cv).structure()->nb_points_of_face(f); ++i)
63 (pf->node_convex(cv).structure()->ind_points_of_face(f)[i]);
65 for (
size_type i = 0; i < pf->node_convex(cv).nb_points(); ++i)
69 return pf->node_tab(cv);
72 virtual bool use_pgp(
size_type)
const {
return true; }
73 virtual bool use_mim()
const {
return false; }
85 size_type target_dim = mf.fem_of_element(cv)->target_dim();
86 GMM_ASSERT2(target_dim == 3,
"Invalid torus fem.");
89 if (!initialized) {init_(qdim, qdim, qdim);}
90 size_type idof = mf.ind_basic_dof_of_element(cv)[i];
91 result[idof] = t[idof%result_dim];
97 store_result_for_torus(cv, i, t);
103 GMM_ASSERT1( (si % q) == 0,
"Incompatibility between the mesh_fem and "
104 "the size of the expression to be interpolated");
105 if (!initialized) { init_(si, q, qmult); }
106 GMM_ASSERT1(s == si,
"Internal error");
107 size_type idof = mf.ind_basic_dof_of_element(cv)[i*q];
108 gmm::add(t.as_vector(),
109 gmm::sub_vector(result, gmm::sub_interval(qmult*idof, s)));
110 (dof_count[idof/q])++;
113 virtual void finalize() {
114 std::vector<size_type> data(3);
115 data[0] = initialized ? result.size() : 0;
116 data[1] = initialized ? dof_count.size() : 0;
117 data[2] = initialized ? s : 0;
118 MPI_MAX_VECTOR(data);
129 GMM_ASSERT1(gmm::vect_size(result) == data[0] && s == data[2] &&
130 gmm::vect_size(dof_count) == data[1],
"Incompatible sizes");
131 MPI_SUM_VECTOR(result);
132 MPI_SUM_VECTOR(dof_count);
133 for (
size_type i = 0; i < dof_count.size(); ++i)
135 gmm::scale(gmm::sub_vector(result, gmm::sub_interval(s*i, s)),
136 scalar_type(1) / scalar_type(dof_count[i]));
139 virtual const mesh &linked_mesh() {
return mf.linked_mesh(); }
141 ga_interpolation_context_fem_same_mesh(
const mesh_fem &mf_, base_vector &r)
142 : result(r), mf(mf_), initialized(false), is_torus(false) {
143 GMM_ASSERT1(!(mf.is_reduced()),
144 "Interpolation on reduced fem is not allowed");
145 if (
dynamic_cast<const torus_mesh_fem*
>(&mf)){
146 auto first_cv = mf.first_convex_of_basic_dof(0);
147 auto target_dim = mf.fem_of_element(first_cv)->target_dim();
148 if (target_dim == 3) is_torus =
true;
153 void ga_interpolation_Lagrange_fem
154 (ga_workspace &workspace,
const mesh_fem &mf, base_vector &result) {
155 ga_interpolation_context_fem_same_mesh gic(mf, result);
156 ga_interpolation(workspace, gic);
159 void ga_interpolation_Lagrange_fem
160 (
const getfem::model &md,
const std::string &expr,
const mesh_fem &mf,
161 base_vector &result,
const mesh_region &rg) {
162 ga_workspace workspace(md);
163 workspace.add_interpolation_expression(expr, mf.linked_mesh(), rg);
164 ga_interpolation_Lagrange_fem(workspace, mf, result);
168 struct ga_interpolation_context_mti
169 :
public ga_interpolation_context {
171 const mesh_trans_inv &mti;
176 virtual bgeot::pstored_point_tab
178 std::vector<size_type> &ind)
const {
179 std::vector<size_type> itab;
180 mti.points_on_convex(cv, itab);
181 std::vector<base_node> pt_tab(itab.size());
182 for (
size_type i = 0; i < itab.size(); ++i) {
183 pt_tab[i] = mti.reference_coords()[itab[i]];
186 return store_point_tab(pt_tab);
189 virtual bool use_pgp(
size_type)
const {
return false; }
190 virtual bool use_mim()
const {
return false; }
200 GMM_ASSERT1(s == si,
"Internal error");
201 size_type ipt = mti.point_on_convex(cv, i);
203 gmm::add(t.as_vector(),
204 gmm::sub_vector(result, gmm::sub_interval(s*dof_t, s)));
207 virtual void finalize() {
208 std::vector<size_type> data(2);
209 data[0] = initialized ? result.size() : 0;
210 data[1] = initialized ? s : 0;
211 MPI_MAX_VECTOR(data);
220 GMM_ASSERT1(gmm::vect_size(result) == data[0] && s == data[1],
221 "Incompatible sizes");
222 MPI_SUM_VECTOR(result);
225 virtual const mesh &linked_mesh() {
return mti.linked_mesh(); }
227 ga_interpolation_context_mti(
const mesh_trans_inv &mti_, base_vector &r,
229 : result(r), mti(mti_), initialized(false), nbdof(nbdof_) {
230 if (nbdof ==
size_type(-1)) nbdof = mti.nb_points();
235 void ga_interpolation_mti
236 (
const getfem::model &md,
const std::string &expr, mesh_trans_inv &mti,
237 base_vector &result,
const mesh_region &rg,
int extrapolation,
238 const mesh_region &rg_source,
size_type nbdof) {
240 ga_workspace workspace(md);
241 workspace.add_interpolation_expression(expr, mti.linked_mesh(), rg);
243 mti.distribute(extrapolation, rg_source);
244 ga_interpolation_context_mti gic(mti, result, nbdof);
245 ga_interpolation(workspace, gic);
250 struct ga_interpolation_context_im_data
251 :
public ga_interpolation_context {
257 virtual bgeot::pstored_point_tab
259 std::vector<size_type> &ind)
const {
260 pintegration_method pim =imd.linked_mesh_im().int_method_of_element(cv);
261 if (pim->type() == IM_NONE)
return bgeot::pstored_point_tab();
262 GMM_ASSERT1(pim->type() == IM_APPROX,
"Sorry, exact methods cannot "
263 "be used in high level generic assembly");
266 i_end = pim->approx_method()->nb_points_on_convex();
268 i_start = pim->approx_method()->ind_first_point_on_face(f);
269 i_end = i_start + pim->approx_method()->nb_points_on_face(f);
271 for (
size_type i = i_start; i < i_end; ++i) ind.push_back(i);
272 return pim->approx_method()->pintegration_points();
275 virtual bool use_pgp(
size_type cv)
const {
276 pintegration_method pim =imd.linked_mesh_im().int_method_of_element(cv);
277 if (pim->type() == IM_NONE)
return false;
278 GMM_ASSERT1(pim->type() == IM_APPROX,
"Sorry, exact methods cannot "
279 "be used in high level generic assembly");
280 return !(pim->approx_method()->is_built_on_the_fly());
282 virtual bool use_mim()
const {
return true; }
288 GMM_ASSERT1(imd.tensor_size() == t.sizes() ||
289 (imd.tensor_size().size() ==
size_type(1) &&
292 "Im_data tensor size " << imd.tensor_size() <<
293 " does not match the size of the interpolated "
294 "expression " << t.sizes() <<
".");
299 GMM_ASSERT1(s == si,
"Internal error");
300 size_type ipt = imd.filtered_index_of_point(cv, i);
302 "Im data with no data on the current integration point.");
303 gmm::add(t.as_vector(),
304 gmm::sub_vector(result, gmm::sub_interval(s*ipt, s)));
307 virtual void finalize() {
308 std::vector<size_type> data(2);
309 data[0] = initialized ? result.size() : 0;
310 data[1] = initialized ? s : 0;
311 MPI_MAX_VECTOR(data);
313 GMM_ASSERT1(gmm::vect_size(result) == data[0] && s == data[1],
314 "Incompatible sizes");
322 MPI_SUM_VECTOR(result);
325 virtual const mesh &linked_mesh() {
return imd.linked_mesh(); }
327 ga_interpolation_context_im_data(
const im_data &imd_, base_vector &r)
328 : result(r), imd(imd_), initialized(false) { }
331 void ga_interpolation_im_data
332 (ga_workspace &workspace,
const im_data &imd, base_vector &result) {
333 ga_interpolation_context_im_data gic(imd, result);
334 ga_interpolation(workspace, gic);
337 void ga_interpolation_im_data
338 (
const getfem::model &md,
const std::string &expr,
const im_data &imd,
339 base_vector &result,
const mesh_region &rg) {
340 ga_workspace workspace(md);
341 workspace.add_interpolation_expression
342 (expr, imd.linked_mesh_im(), rg);
344 ga_interpolation_im_data(workspace, imd, result);
349 struct ga_interpolation_context_mesh_slice
350 :
public ga_interpolation_context {
352 const stored_mesh_slice &sl;
355 std::vector<size_type> first_node;
357 virtual bgeot::pstored_point_tab
359 std::vector<size_type> &ind)
const {
360 GMM_ASSERT1(f ==
short_type(-1),
"No support for interpolation on faces"
361 " for a stored_mesh_slice yet.");
363 const mesh_slicer::cs_nodes_ct &nodes = sl.nodes(ic);
364 std::vector<base_node> pt_tab(nodes.size());
365 for (
size_type i=0; i < nodes.size(); ++i) {
366 pt_tab[i] = nodes[i].pt_ref;
369 return store_point_tab(pt_tab);
372 virtual bool use_pgp(
size_type )
const {
return false; }
373 virtual bool use_mim()
const {
return false; }
382 first_node.resize(sl.nb_convex());
383 for (
size_type ic=0; ic < sl.nb_convex()-1; ++ic)
384 first_node[ic+1] = first_node[ic] + sl.nodes(ic).size();
386 GMM_ASSERT1(s == si && result.size() == s * sl.nb_points(),
"Internal error");
389 gmm::add(t.as_vector(),
390 gmm::sub_vector(result, gmm::sub_interval(s*ipt, s)));
393 virtual void finalize() {
394 std::vector<size_type> data(2);
395 data[0] = initialized ? result.size() : 0;
396 data[1] = initialized ? s : 0;
397 MPI_MAX_VECTOR(data);
399 GMM_ASSERT1(gmm::vect_size(result) == data[0] && s == data[1],
400 "Incompatible sizes");
408 MPI_SUM_VECTOR(result);
411 virtual const mesh &linked_mesh() {
return sl.linked_mesh(); }
413 ga_interpolation_context_mesh_slice(
const stored_mesh_slice &sl_,
415 : result(r), sl(sl_), initialized(false) { }
418 void ga_interpolation_mesh_slice
419 (ga_workspace &workspace,
const stored_mesh_slice &sl, base_vector &result) {
420 ga_interpolation_context_mesh_slice gic(sl, result);
421 ga_interpolation(workspace, gic);
424 void ga_interpolation_mesh_slice
425 (
const getfem::model &md,
const std::string &expr,
const stored_mesh_slice &sl,
426 base_vector &result,
const mesh_region &rg) {
427 ga_workspace workspace(md);
428 workspace.add_interpolation_expression(expr, sl.linked_mesh(), rg);
429 ga_interpolation_mesh_slice(workspace, sl, result);
438 const std::string &expr,
const mesh_fem &mf,
447 model_real_sparse_matrix M(nbdof, nbdof);
451 ga_workspace workspace(md, ga_workspace::inherit::NONE);
452 gmm::sub_interval I(0,nbdof);
453 workspace.add_fem_variable(
"c__dummy_var_95_", mf, I, base_vector(nbdof));
454 if (mf.get_qdims().size() > 1)
455 workspace.add_expression(
"("+expr+
"):Test_c__dummy_var_95_",mim,region,2);
457 workspace.add_expression(
"("+expr+
").Test_c__dummy_var_95_",mim,region,2);
458 getfem::base_vector F(nbdof);
459 workspace.set_assembled_vector(F);
460 workspace.assembly(1);
461 gmm::resize(result, nbdof);
463 getfem::base_matrix loc_M;
464 getfem::base_vector loc_U;
468 loc_M.base_resize(nd, nd); gmm::resize(loc_U, nd);
470 gmm::copy(gmm::sub_matrix(M, J, J), loc_M);
471 gmm::lu_solve(loc_M, loc_U, gmm::sub_vector(F, J));
472 gmm::copy(loc_U, gmm::sub_vector(result, J));
475 MPI_SUM_VECTOR(result);
482 struct rated_box_index_compare {
484 const std::pair<scalar_type, const bgeot::box_index*> &x,
485 const std::pair<scalar_type, const bgeot::box_index*> &y)
const {
486 GMM_ASSERT2(x.second !=
nullptr,
"x contains nullptr");
487 GMM_ASSERT2(y.second !=
nullptr,
"y contains nullptr");
488 return (x.first < y.first) || (!(y.first < x.first) && (x.second->id < y.second->id));
492 class interpolate_transformation_expression
493 :
public virtual_interpolate_transformation,
public context_dependencies {
495 struct workspace_gis_pair :
public std::pair<ga_workspace, ga_instruction_set> {
496 inline ga_workspace &workspace() {
return this->first; }
497 inline ga_instruction_set &gis() {
return this->second; }
500 const mesh &source_mesh;
501 const mesh &target_mesh;
505 mutable bool recompute_elt_boxes;
506 mutable ga_workspace local_workspace;
507 mutable ga_instruction_set local_gis;
510 mutable std::set<var_trans_pair> used_vars;
511 mutable std::set<var_trans_pair> used_data;
512 mutable std::map<var_trans_pair,
513 workspace_gis_pair> compiled_derivatives;
514 mutable bool extract_variable_done;
515 mutable bool extract_data_done;
518 mutable std::map<size_type, std::vector<size_type>> box_to_convexes;
521 void update_from_context()
const {
522 recompute_elt_boxes =
true;
525 void extract_variables(
const ga_workspace &workspace,
526 std::set<var_trans_pair> &vars,
527 bool ignore_data,
const mesh &,
528 const std::string &)
const {
529 if ((ignore_data && !extract_variable_done) ||
530 (!ignore_data && !extract_data_done)) {
535 ga_workspace aux_workspace(workspace, ga_workspace::inherit::ALL);
536 aux_workspace.clear_expressions();
537 aux_workspace.add_interpolation_expression(expr, source_mesh);
538 for (
size_type i = 0; i < aux_workspace.nb_trees(); ++i)
539 ga_extract_variables(aux_workspace.tree_info(i).ptree->root,
540 aux_workspace, source_mesh,
541 ignore_data ? used_vars : used_data,
544 extract_variable_done =
true;
546 extract_data_done =
true;
549 vars.insert(used_vars.begin(), used_vars.end());
551 vars.insert(used_data.begin(), used_data.end());
554 void init(
const ga_workspace &workspace)
const {
558 local_workspace = ga_workspace(workspace, ga_workspace::inherit::ALL);
559 local_workspace.clear_expressions();
561 local_workspace.add_interpolation_expression(expr, source_mesh);
562 local_gis = ga_instruction_set();
563 ga_compile_interpolation(local_workspace, local_gis);
566 for (
const std::string &transname : local_gis.transformations)
567 local_workspace.interpolate_transformation(transname)
568 ->init(local_workspace);
570 if (!extract_variable_done) {
571 std::set<var_trans_pair> vars;
572 extract_variables(workspace, vars,
true, source_mesh,
"");
575 for (
const var_trans_pair &var : used_vars) {
576 workspace_gis_pair &pwi = compiled_derivatives[var];
577 pwi.workspace() = local_workspace;
578 pwi.gis() = ga_instruction_set();
579 if (pwi.workspace().nb_trees()) {
580 ga_tree tree = *(pwi.workspace().tree_info(0).ptree);
581 ga_derivative(tree, pwi.workspace(), source_mesh,
582 var.varname, var.transname, 1);
584 ga_semantic_analysis(tree, local_workspace, dummy_mesh(),
586 ga_compile_interpolation(pwi.workspace(), pwi.gis());
591 if (recompute_elt_boxes) {
593 box_to_convexes.clear();
594 element_boxes.clear();
595 base_node bmin(N), bmax(N);
596 const dal::bit_vector&
598 ? target_mesh.convex_index()
599 : target_mesh.region(target_region).index();
600 for (dal::bv_visitor cv(convex_index); !cv.finished(); ++cv) {
606 gmm::copy(target_mesh.points_of_convex(cv)[0], bmin);
607 gmm::copy(bmin, bmax);
614 const base_node &pt = target_mesh.points_of_convex(cv)[ip];
617 bmin[k] = std::min(bmin[k], pt[k]);
618 bmax[k] = std::max(bmax[k], pt[k]);
622 scalar_type h = bmax[0] - bmin[0];
623 for (
size_type k = 1; k < N; ++k) h = std::max(h, bmax[k]-bmin[k]);
624 if (pgt->is_linear()) h *= 1E-4;
625 for (
auto &&val : bmin) val -= h*0.2;
626 for (
auto &&val : bmax) val += h*0.2;
628 box_to_convexes[element_boxes.add_box(bmin, bmax)].push_back(cv);
630 element_boxes.build_tree();
631 recompute_elt_boxes =
false;
635 void finalize()
const {
636 for (
const std::string &transname : local_gis.transformations)
637 local_workspace.interpolate_transformation(transname)->finalize();
638 local_gis = ga_instruction_set();
641 std::string expression()
const {
return expr; }
643 int transform(
const ga_workspace &,
const mesh &m,
644 fem_interpolation_context &ctx_x,
645 const base_small_vector &Normal,
650 std::map<var_trans_pair, base_tensor> &derivatives,
651 bool compute_derivatives)
const {
654 local_gis.ctx = ctx_x;
655 local_gis.Normal = Normal;
659 gmm::clear(local_workspace.assembled_tensor().as_vector());
661 for (
auto &&instr : local_gis.all_instructions) {
662 GMM_ASSERT1(instr.second.m == &m,
663 "Incompatibility of meshes in interpolation");
664 auto &gilb = instr.second.begin_instructions;
665 for (
size_type j = 0; j < gilb.size(); ++j) j += gilb[j]->exec();
666 auto &gile = instr.second.elt_instructions;
667 for (
size_type j = 0; j < gile.size(); ++j) j+=gile[j]->exec();
668 auto &gil = instr.second.instructions;
669 for (
size_type j = 0; j < gil.size(); ++j) j += gil[j]->exec();
672 GMM_ASSERT1(local_workspace.assembled_tensor().size()==target_mesh.dim(),
673 "Wrong dimension of the transformation expression");
674 P.resize(target_mesh.dim());
675 gmm::copy(local_workspace.assembled_tensor().as_vector(), P);
679 bgeot::rtree::pbox_cont boxes;
681 bgeot::rtree::pbox_set bset;
682 element_boxes.find_boxes_at_point(P, bset);
685 std::set<std::pair<scalar_type, const bgeot::box_index*>,
686 rated_box_index_compare> rated_boxes;
687 for (
const auto &box : bset) {
688 scalar_type rating = scalar_type(1);
689 for (
size_type i = 0; i < m.dim(); ++i) {
690 scalar_type h = box->max->at(i) - box->min->at(i);
691 if (h > scalar_type(0)) {
692 scalar_type r = std::min(box->max->at(i) - P[i],
693 P[i] - box->min->at(i)) / h;
694 rating = std::min(r, rating);
697 rated_boxes.insert(std::make_pair(rating, box));
701 for (
const auto &p : rated_boxes)
702 boxes.push_back(p.second);
706 scalar_type best_dist(1e10);
708 base_node best_P_ref;
709 for (
size_type i = boxes.size(); i > 0 && !ret_type; --i) {
710 for (
auto convex : box_to_convexes.at(boxes[i-1]->id)) {
711 gic.init(target_mesh.points_of_convex(convex),
712 target_mesh.trans_of_convex(convex));
715 bool is_in = gic.
invert(P, P_ref, converged, 1E-4);
730 = target_mesh.trans_of_convex(cv)->convex_ref()->is_in(P_ref);
731 if (dist < best_dist) {
741 if (ret_type == 0 && best_dist < 5e-3) {
753 if (compute_derivatives) {
754 for (
auto &&d : derivatives) {
755 workspace_gis_pair &pwi = compiled_derivatives[d.first];
757 gmm::clear(pwi.workspace().assembled_tensor().as_vector());
758 ga_function_exec(pwi.gis());
759 d.second = pwi.workspace().assembled_tensor();
765 interpolate_transformation_expression
766 (
const mesh &sm,
const mesh &tm,
size_type trg,
const std::string &expr_)
767 : source_mesh(sm), target_mesh(tm), target_region(trg), expr(expr_),
768 recompute_elt_boxes(true), extract_variable_done(false),
769 extract_data_done(false)
770 { this->add_dependency(tm); }
776 (ga_workspace &workspace,
const std::string &name,
const mesh &sm,
777 const mesh &tm,
const std::string &expr) {
779 (workspace, name, sm, tm,
size_type(-1), expr);
783 (ga_workspace &workspace,
const std::string &name,
const mesh &sm,
784 const mesh &tm,
size_type trg,
const std::string &expr) {
785 pinterpolate_transformation
786 p = std::make_shared<interpolate_transformation_expression>
788 workspace.add_interpolate_transformation(name, p);
792 (model &md,
const std::string &name,
const mesh &sm,
const mesh &tm,
793 const std::string &expr) {
799 (model &md,
const std::string &name,
const mesh &sm,
const mesh &tm,
800 size_type trg,
const std::string &expr) {
801 pinterpolate_transformation
802 p = std::make_shared<interpolate_transformation_expression>
804 md.add_interpolate_transformation(name, p);
811 class interpolate_transformation_neighbor
812 :
public virtual_interpolate_transformation,
public context_dependencies {
815 void update_from_context()
const {}
816 void extract_variables(
const ga_workspace &,
817 std::set<var_trans_pair> &,
819 const std::string &)
const {}
820 void init(
const ga_workspace &)
const {}
821 void finalize()
const {}
823 std::string expression(
void)
const {
return "X"; }
825 int transform(
const ga_workspace &,
const mesh &m_x,
826 fem_interpolation_context &ctx_x,
827 const base_small_vector &,
const mesh **m_t,
831 std::map<var_trans_pair, base_tensor> &,
832 bool compute_derivatives)
const {
838 GMM_ASSERT1(face_x !=
short_type(-1),
"Neighbor transformation can "
839 "only be applied to internal faces");
841 auto adj_face = m_x.adjacent_face(cv_x, face_x);
845 gic.init(m_x.points_of_convex(adj_face.cv),
846 m_x.trans_of_convex(adj_face.cv));
847 bool converged =
true;
848 gic.
invert(ctx_x.xreal(), P_ref, converged);
849 bool is_in = (ctx_x.pgt()->convex_ref()->is_in(P_ref) < 1E-4);
850 GMM_ASSERT1(is_in && converged,
"Geometric transformation inversion "
851 "has failed in neighbor transformation");
852 face_num = adj_face.f;
856 GMM_ASSERT1(!compute_derivatives,
857 "No derivative for this transformation");
861 interpolate_transformation_neighbor() { }
867 return (std::make_shared<interpolate_transformation_neighbor>());
874 class interpolate_transformation_element_extrapolation
875 :
public virtual_interpolate_transformation,
public context_dependencies {
878 std::map<size_type, size_type> elt_corr;
881 void update_from_context()
const {}
882 void extract_variables(
const ga_workspace &,
883 std::set<var_trans_pair> &,
885 const std::string &)
const {}
886 void init(
const ga_workspace &)
const {}
887 void finalize()
const {}
888 std::string expression(
void)
const {
return "X"; }
890 int transform(
const ga_workspace &,
const mesh &m_x,
891 fem_interpolation_context &ctx_x,
892 const base_small_vector &,
const mesh **m_t,
896 std::map<var_trans_pair, base_tensor> &,
897 bool compute_derivatives)
const {
900 GMM_ASSERT1(&sm == &m_x,
"Bad mesh");
901 size_type cv_x = ctx_x.convex_num(), cv_y = cv_x;
902 auto it = elt_corr.find(cv_x);
903 if (it != elt_corr.end()) cv_y = it->second;
907 gic.init(m_x.points_of_convex(cv_y),
908 m_x.trans_of_convex(cv_y));
909 bool converged =
true;
910 gic.
invert(ctx_x.xreal(), P_ref, converged, 1E-4);
911 GMM_ASSERT1(converged,
"Geometric transformation inversion "
912 "has failed in element extrapolation transformation");
919 P_ref = ctx_x.xref();
922 GMM_ASSERT1(!compute_derivatives,
923 "No derivative for this transformation");
927 void set_correspondence(
const std::map<size_type, size_type> &ec) {
931 interpolate_transformation_element_extrapolation
932 (
const mesh &sm_,
const std::map<size_type, size_type> &ec)
933 : sm(sm_), elt_corr(ec) { }
937 void add_element_extrapolation_transformation
938 (model &md,
const std::string &name,
const mesh &sm,
939 std::map<size_type, size_type> &elt_corr) {
940 pinterpolate_transformation
941 p = std::make_shared<interpolate_transformation_element_extrapolation>
943 md.add_interpolate_transformation(name, p);
946 void add_element_extrapolation_transformation
947 (ga_workspace &workspace,
const std::string &name,
const mesh &sm,
948 std::map<size_type, size_type> &elt_corr) {
949 pinterpolate_transformation
950 p = std::make_shared<interpolate_transformation_element_extrapolation>
952 workspace.add_interpolate_transformation(name, p);
955 void set_element_extrapolation_correspondence
956 (ga_workspace &workspace,
const std::string &name,
957 std::map<size_type, size_type> &elt_corr) {
958 GMM_ASSERT1(workspace.interpolate_transformation_exists(name),
959 "Unknown transformation");
960 auto pit=workspace.interpolate_transformation(name).get();
962 =
dynamic_cast<const interpolate_transformation_element_extrapolation *
>
965 "The transformation is not of element extrapolation type");
966 const_cast<interpolate_transformation_element_extrapolation *
>(cpext)
967 ->set_correspondence(elt_corr);
970 void set_element_extrapolation_correspondence
971 (model &md,
const std::string &name,
972 std::map<size_type, size_type> &elt_corr) {
973 GMM_ASSERT1(md.interpolate_transformation_exists(name),
974 "Unknown transformation");
975 auto pit=md.interpolate_transformation(name).get();
977 =
dynamic_cast<const interpolate_transformation_element_extrapolation *
>
980 "The transformation is not of element extrapolation type");
981 const_cast<interpolate_transformation_element_extrapolation *
>(cpext)
982 ->set_correspondence(elt_corr);
991 class standard_secondary_domain :
public virtual_secondary_domain {
995 virtual const mesh_region &give_region(
const mesh &,
1001 standard_secondary_domain(
const mesh_im &mim__,
const mesh_region ®ion_)
1002 : virtual_secondary_domain(mim__, region_) {}
1005 void add_standard_secondary_domain
1006 (model &md,
const std::string &name,
const mesh_im &mim,
1007 const mesh_region &rg) {
1008 psecondary_domain p = std::make_shared<standard_secondary_domain>(mim, rg);
1009 md.add_secondary_domain(name, p);
1012 void add_standard_secondary_domain
1013 (ga_workspace &workspace,
const std::string &name,
const mesh_im &mim,
1014 const mesh_region &rg) {
1015 psecondary_domain p = std::make_shared<standard_secondary_domain>(mim, rg);
1016 workspace.add_secondary_domain(name, p);