28 struct contact_boundary {
33 mutable const model_real_plain_vector *U;
34 mutable model_real_plain_vector U_unred;
36 contact_boundary(
size_type r,
const mesh_fem *mf,
const std::string &dn)
37 : region(r), mfu(mf), dispname(dn)
42 base_small_vector element_U(
const contact_boundary &cb,
size_type cv)
44 auto U_elm = base_small_vector{};
50 auto most_central_box(
const bgeot::rtree::pbox_set &bset,
55 auto itmax = begin(bset);
58 if (bset.size() > 1) {
59 auto rate_max = scalar_type{-1};
60 for (; it != end(bset); ++it) {
61 auto rate_box = scalar_type{1};
62 for (
size_type i = 0; i < pt.size(); ++i) {
63 auto h = (*it)->max[i] - (*it)->min[i];
65 auto rate = min((*it)->max[i] - pt[i], pt[i] - (*it)->min[i]) / h;
66 rate_box = min(rate, rate_box);
69 if (rate_box > rate_max) {
81 class interpolate_transformation_on_deformed_domains
82 :
public virtual_interpolate_transformation {
84 contact_boundary master;
85 contact_boundary slave;
88 mutable std::vector<size_type> box_to_convex;
91 mutable fem_precomp_pool fppool;
94 void compute_element_boxes()
const {
96 model_real_plain_vector Uelm;
97 element_boxes.clear();
99 auto bnum = master.region;
100 auto &mfu = *(master.mfu);
101 auto &U = *(master.U);
102 auto &m = mfu.linked_mesh();
105 base_node Xdeformed(N), bmin(N), bmax(N);
106 auto region = m.region(bnum);
111 region.prohibit_partitioning();
113 GMM_ASSERT1(mfu.get_qdim() == N,
"Wrong mesh_fem qdim");
115 dal::bit_vector points_already_interpolated;
116 std::vector<base_node> transformed_points(m.nb_max_points());
117 box_to_convex.clear();
118 box_to_convex.reserve(region.size());
122 auto pgt = m.trans_of_convex(cv);
123 auto pf_s = mfu.fem_of_element(cv);
124 auto pfp = fppool(pf_s, pgt->pgeometric_nodes());
127 mfu.linked_mesh().points_of_convex(cv, G);
129 auto ctx = fem_interpolation_context{pgt, pfp,
size_type(-1), G, cv};
130 auto nb_pt = pgt->structure()->nb_points();
133 auto ind = m.ind_points_of_convex(cv)[k];
137 if (points_already_interpolated.is_in(ind)) {
138 Xdeformed = transformed_points[ind];
140 pf_s->interpolation(ctx, Uelm, Xdeformed, dim_type{N});
141 Xdeformed += ctx.xreal();
142 transformed_points[ind] = Xdeformed;
143 points_already_interpolated.add(ind);
147 bmin = bmax = Xdeformed;
150 bmin[l] = std::min(bmin[l], Xdeformed[l]);
151 bmax[l] = std::max(bmax[l], Xdeformed[l]);
157 element_boxes.add_box(bmin, bmax, box_to_convex.size());
158 box_to_convex.push_back(cv);
162 fem_interpolation_context deformed_master_context(
size_type cv)
const 164 auto &mfu = *(master.mfu);
165 auto G = base_matrix{};
166 auto pfu = mfu.fem_of_element(cv);
167 auto pgt = master.mfu->linked_mesh().trans_of_convex(cv);
168 auto pfp = fppool(pfu, pgt->pgeometric_nodes());
169 master.mfu->linked_mesh().points_of_convex(cv, G);
173 std::vector<bgeot::base_node> deformed_master_nodes(
size_type cv)
const {
174 using namespace bgeot;
177 auto nodes = vector<base_node>{};
179 auto U_elm = element_U(master, cv);
180 auto &mfu = *(master.mfu);
181 auto G = base_matrix{};
182 auto pfu = mfu.fem_of_element(cv);
183 auto pgt = master.mfu->linked_mesh().trans_of_convex(cv);
184 auto pfp = fppool(pfu, pgt->pgeometric_nodes());
185 auto N = mfu.linked_mesh().dim();
186 auto pt = base_node(N);
188 master.mfu->linked_mesh().points_of_convex(cv, G);
189 auto ctx = fem_interpolation_context{pgt, pfp,
size_type(-1), G, cv};
190 auto nb_pt = pgt->structure()->nb_points();
191 nodes.reserve(nb_pt);
194 pfu->interpolation(ctx, U_elm, U, dim_type{N});
195 gmm::add(ctx.xreal(), U, pt);
204 interpolate_transformation_on_deformed_domains(
207 const std::string &source_displacements,
210 const std::string &target_displacements)
212 slave{source_region, &mf_source, source_displacements},
213 master{target_region, &mf_target, target_displacements}
217 void extract_variables(
const ga_workspace &workspace,
218 std::set<var_trans_pair> &vars,
221 const std::string &interpolate_name)
const override {
222 if (!ignore_data || !(workspace.is_constant(master.dispname))){
223 vars.emplace(master.dispname, interpolate_name);
224 vars.emplace(slave.dispname,
"");
228 void init(
const ga_workspace &workspace)
const override {
230 for (
auto pcb : std::list<const contact_boundary*>{&master, &slave}) {
231 auto &mfu = *(pcb->mfu);
232 if (mfu.is_reduced()) {
234 mfu.extend_vector(workspace.value(pcb->dispname), pcb->U_unred);
235 pcb->U = &(pcb->U_unred);
237 pcb->U = &(workspace.value(pcb->dispname));
240 compute_element_boxes();
243 void finalize()
const override {
244 element_boxes.clear();
245 box_to_convex.clear();
246 master.U_unred.clear();
247 slave.U_unred.clear();
251 int transform(
const ga_workspace &workspace,
253 fem_interpolation_context &ctx_x,
260 std::map<var_trans_pair, base_tensor> &derivatives,
261 bool compute_derivatives)
const override {
263 auto &target_mesh = master.mfu->linked_mesh();
265 auto transformation_success =
false;
268 using namespace bgeot;
272 auto cv_x = ctx_x.convex_num();
273 auto U_elm_x = element_U(slave, cv_x);
274 auto &mfu_x = *(slave.mfu);
275 auto pfu_x = mfu_x.fem_of_element(cv_x);
276 auto N = mfu_x.linked_mesh().dim();
278 auto G_x = base_matrix{};
279 m_x.points_of_convex(cv_x, G_x);
281 pfu_x->interpolation(ctx_x, U_elm_x, U_x, dim_type{N});
283 add(ctx_x.xreal(), U_x, pt_x);
291 auto bset = rtree::pbox_set{};
292 element_boxes.find_boxes_at_point(pt_x, bset);
293 while (!bset.empty())
295 auto itmax = most_central_box(bset, pt_x);
296 cv = box_to_convex[(*itmax)->id];
297 auto deformed_nodes_y = deformed_master_nodes(cv);
298 gic.init(deformed_nodes_y, target_mesh.trans_of_convex(cv));
299 auto converged =
true;
300 auto is_in = gic.
invert(pt_x, P_ref, converged);
301 if (is_in && converged) {
303 transformation_success =
true;
306 if (bset.size() == 1)
break;
315 if (compute_derivatives && transformation_success) {
316 GMM_ASSERT2(derivatives.size() == 2,
317 "Expecting to return derivatives only for Umaster and Uslave");
319 for (
auto &pair : derivatives)
321 if (pair.first.varname == slave.dispname)
323 auto base_ux = base_tensor{};
324 auto vbase_ux = base_matrix{} ;
325 ctx_x.base_value(base_ux);
326 auto qdim_ux = pfu_x->target_dim();
327 auto ndof_ux = pfu_x->nb_dof(cv_x) * N / qdim_ux;
328 vectorize_base_tensor(base_ux, vbase_ux, ndof_ux, qdim_ux, N);
329 pair.second.adjust_sizes(ndof_ux, N);
330 copy(vbase_ux.as_vector(), pair.second.as_vector());
333 if (pair.first.varname == master.dispname)
335 auto ctx_y = deformed_master_context(cv);
336 ctx_y.set_xref(P_ref);
337 auto base_uy = base_tensor{};
338 auto vbase_uy = base_matrix{} ;
339 ctx_y.base_value(base_uy);
340 auto pfu_y = master.mfu->fem_of_element(cv);
341 auto dim_y = master.mfu->linked_mesh().dim();
342 auto qdim_uy = pfu_y->target_dim();
343 auto ndof_uy = pfu_y->nb_dof(cv) * dim_y / qdim_uy;
344 vectorize_base_tensor(base_uy, vbase_uy, ndof_uy, qdim_uy, dim_y);
345 pair.second.adjust_sizes(ndof_uy, dim_y);
346 copy(vbase_uy.as_vector(), pair.second.as_vector());
347 scale(pair.second.as_vector(), -1.);
349 else GMM_ASSERT2(
false,
"unexpected derivative variable");
353 return transformation_success ? 1 : 0;
359 (ga_workspace &workspace,
const std::string &transname,
360 const mesh &source_mesh,
const std::string &source_displacements,
362 const std::string &target_displacements,
const mesh_region &target_region)
364 auto pmf_source = workspace.associated_mf(source_displacements);
365 auto pmf_target = workspace.associated_mf(target_displacements);
366 auto p_transformation
367 = std::make_shared<interpolate_transformation_on_deformed_domains>(source_region.id(),
369 source_displacements,
372 target_displacements);
373 workspace.add_interpolate_transformation(transname, p_transformation);
377 (
model &md,
const std::string &transname,
378 const mesh &source_mesh,
const std::string &source_displacements,
380 const std::string &target_displacements,
const mesh_region &target_region)
384 auto p_transformation
385 = std::make_shared<interpolate_transformation_on_deformed_domains>(source_region.id(),
387 source_displacements,
390 target_displacements);
structure used to hold a set of convexes and/or convex faces.
void add_interpolate_transformation_on_deformed_domains(ga_workspace &workspace, const std::string &transname, const mesh &source_mesh, const std::string &source_displacements, const mesh_region &source_region, const mesh &target_mesh, const std::string &target_displacements, const mesh_region &target_region)
Add a transformation to the workspace that creates an identity mapping between two meshes in deformed...
void slice_vector_on_basic_dof_of_element(const mesh_fem &mf, const VEC1 &vec, size_type cv, VEC2 &coeff, size_type qmult1=size_type(-1), size_type qmult2=size_type(-1))
Given a mesh_fem.
Describe a mesh (collection of convexes (elements) and points).
does the inversion of the geometric transformation for a given convex
const mesh_fem & mesh_fem_of_variable(const std::string &name) const
Gives the access to the mesh_fem of a variable if any.
``Model'' variables store the variables, the data and the description of a model. ...
size_t size_type
used as the common size type in the library
void copy(const L1 &l1, L2 &l2)
*/
Model representation in Getfem.
bool invert(const base_node &n, base_node &n_ref, scalar_type IN_EPS=1e-12)
given the node on the real element, returns the node on the reference element (even if it is outside ...
"iterator" class for regions.
void add_interpolate_transformation(const std::string &name, pinterpolate_transformation ptrans)
Add a interpolate transformation to the model to be used with the generic assembly.
A langage for generic assembly of pde boundary value problems.
GEneric Tool for Finite Element Methods.
Describe a finite element method linked to a mesh.
gmm::uint16_type short_type
used as the common short type integer in the library
Balanced tree of n-dimensional rectangles.
void resize(M &v, size_type m, size_type n)
*/
void add(const L1 &l1, L2 &l2)
*/