GetFEM++  5.3
getfem_projected_fem.cc
1 /*===========================================================================
2 
3  Copyright (C) 2012-2017 Yves Renard, Konstantinos Poulios
4 
5  This file is a part of GetFEM++
6 
7  GetFEM++ is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program; if not, write to the Free Software Foundation,
18  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20 ===========================================================================*/
21 
23 
24 namespace getfem {
25 
26  typedef bgeot::convex<base_node>::dref_convex_pt_ct dref_convex_pt_ct;
27 // typedef bgeot::basic_mesh::ref_mesh_face_pt_ct ref_mesh_face_pt_ct;
28 
29  /* calculates the projection of a point on the face of a convex
30  * Input:
31  * pgt : the geometric transformation of the convex
32  * G_cv: the nodes of the convex, stored in columns
33  * fc : the face of the convex to project on
34  * pt : the point to be projected
35  * Output:
36  * proj_ref: the projected point in the reference element
37  */
38  void projection_on_convex_face
39  (const bgeot::pgeometric_trans pgt, const base_matrix &G_cv,
40  const short_type fc, const base_node &pt,
41  base_node &proj_ref) {
42 
43  size_type N = gmm::mat_nrows(G_cv); // dimension of the target space
44  size_type P = pgt->dim(); // dimension of the reference element space
45 
46  size_type nb_pts_cv = gmm::mat_ncols(G_cv);
47  size_type nb_pts_fc = pgt->structure()->nb_points_of_face(fc);
48 
49  GMM_ASSERT1( N == pt.size(), "Dimensions mismatch");
50  GMM_ASSERT1( nb_pts_cv == pgt->nb_points(), "Dimensions mismatch");
51 
52  bgeot::convex_ind_ct ind_pts_fc = pgt->structure()->ind_points_of_face(fc);
53 
54  base_matrix G_fc(N, nb_pts_fc);
55  for (size_type i=0; i < nb_pts_fc; i++)
56  gmm::copy(gmm::mat_col(G_cv,ind_pts_fc[i]),gmm::mat_col(G_fc,i));
57 
58  // Local base on reference face
59  base_matrix base_ref_fc(P,P-1);
60  {
61  dref_convex_pt_ct dref_pts_fc = pgt->convex_ref()->dir_points_of_face(fc);
62  GMM_ASSERT1( dref_pts_fc.size() == P, "Dimensions mismatch");
63  for (size_type i = 0; i < P-1; ++i)
64  gmm::copy(dref_pts_fc[i+1] - dref_pts_fc[0], gmm::mat_col(base_ref_fc,i));
65  }
66 
67  proj_ref.resize(P);
68 
69  base_node proj(N); // the projected point in the real element
70  base_node vres(P); // residual vector
71  scalar_type res= 1.;
72 
73  // initial guess
74  proj_ref = gmm::mean_value(pgt->convex_ref()->points_of_face(fc));
75 
76  base_vector val(nb_pts_fc);
77  pgt->poly_vector_val(proj_ref, ind_pts_fc, val);
78  gmm::mult(G_fc, val, proj);
79 
80  base_matrix K(N,P-1);
81 
82  base_matrix grad_fc(nb_pts_fc, P);
83  base_matrix grad_fc1(nb_pts_fc, P-1);
84  base_matrix B(N,P-1), BB(N,P), CS(P-1,P-1);
85 
86  scalar_type EPS = 10E-12;
87  unsigned cnt = 50;
88  while (res > EPS && --cnt) {
89  // computation of the pseudo inverse matrix B at point proj_ref
90  pgt->poly_vector_grad(proj_ref, ind_pts_fc, grad_fc);
91  gmm::mult(grad_fc, base_ref_fc, grad_fc1);
92  gmm::mult(G_fc, grad_fc1, K);
93  gmm::mult(gmm::transposed(K), K, CS);
94  gmm::lu_inverse(CS);
95  gmm::mult(K, CS, B);
96  gmm::mult(B, gmm::transposed(base_ref_fc), BB);
97 
98  // Projection onto the face of the convex
99  gmm::mult_add(gmm::transposed(BB), pt - proj, proj_ref);
100  pgt->poly_vector_val(proj_ref, ind_pts_fc, val);
101  gmm::mult(G_fc, val, proj);
102 
103  gmm::mult(gmm::transposed(BB), pt - proj, vres);
104  res = gmm::vect_norm2(vres);
105  }
106  GMM_ASSERT1( res <= EPS,
107  "Iterative pojection on convex face did not converge");
108  }
109 
110 
111  /* calculates the normal at a specific point on the face of a convex
112  * Input:
113  * pgt : the geometric transformation of the convex
114  * G_cv : the nodes of the convex, stored in columns
115  * fc : the face of the convex to project on
116  * ref_pt: the point in the reference element
117  * Output:
118  * normal: the surface normal in the real element corresponding at
119  * the location of ref_pt in the reference element
120  */
121  void normal_on_convex_face
122  (const bgeot::pgeometric_trans pgt, const base_matrix &G_cv,
123  const short_type fc, const base_node &ref_pt, base_node &normal) {
124 
125  size_type N = gmm::mat_nrows(G_cv); // dimension of the target space
126  size_type P = pgt->dim(); // dimension of the reference element space
127 
128  size_type nb_pts_cv = gmm::mat_ncols(G_cv);
129  size_type nb_pts_fc = pgt->structure()->nb_points_of_face(fc);
130 
131  GMM_ASSERT1( nb_pts_cv == pgt->nb_points(), "Dimensions mismatch");
132 
133  bgeot::convex_ind_ct ind_pts_fc = pgt->structure()->ind_points_of_face(fc);
134 
135  base_matrix G_fc(N, nb_pts_fc);
136  for (size_type i=0; i < nb_pts_fc; i++)
137  gmm::copy(gmm::mat_col(G_cv,ind_pts_fc[i]),gmm::mat_col(G_fc,i));
138 
139  // Local base on reference face
140  base_matrix base_ref_fc(P,P-1);
141  {
142  dref_convex_pt_ct dref_pts_fc = pgt->convex_ref()->dir_points_of_face(fc);
143  GMM_ASSERT1( dref_pts_fc.size() == P, "Dimensions mismatch");
144  for (size_type i = 0; i < P-1; ++i)
145  gmm::copy(dref_pts_fc[i+1] - dref_pts_fc[0], gmm::mat_col(base_ref_fc,i));
146  }
147 
148  normal.resize(N);
149 
150  base_matrix K(N,P-1);
151  { // calculate K at the final point
152  base_matrix grad_fc(nb_pts_fc, P);
153  base_matrix grad_fc1(nb_pts_fc, P-1);
154  pgt->poly_vector_grad(ref_pt, ind_pts_fc, grad_fc);
155  gmm::mult(grad_fc, base_ref_fc, grad_fc1);
156  gmm::mult(G_fc, grad_fc1, K);
157  }
158 
159  base_matrix KK(N,P);
160  { // calculate KK
161  base_matrix grad_cv(nb_pts_cv, P);
162  pgt->poly_vector_grad(ref_pt, grad_cv);
163  gmm::mult(G_cv, grad_cv, KK);
164  }
165 
166  base_matrix bases_product(P-1, P);
167  gmm::mult(gmm::transposed(K), KK, bases_product);
168 
169  for (size_type i = 0; i < P; ++i) {
170  std::vector<size_type> ind(0);
171  for (size_type j = 0; j < P; ++j)
172  if (j != i ) ind.push_back(j);
173  scalar_type det = gmm::lu_det(gmm::sub_matrix(bases_product,
174  gmm::sub_interval(0, P-1),
175  gmm::sub_index(ind) ) );
176  gmm::add(gmm::scaled(gmm::mat_col(KK, i), (i % 2) ? -det : +det ), normal);
177  }
178 
179  // normalizing
180  gmm::scale(normal, 1/gmm::vect_norm2(normal));
181 
182  // ensure that normal points outwards
183  base_node cv_center(N), fc_center(N);
184  for (size_type i=0; i < nb_pts_cv; i++)
185  gmm::add(gmm::mat_col(G_cv,i), cv_center);
186  for (size_type i=0; i < nb_pts_fc; i++)
187  gmm::add(gmm::mat_col(G_fc,i), fc_center);
188  gmm::scale(cv_center, scalar_type(1)/scalar_type(nb_pts_cv));
189  gmm::scale(fc_center, scalar_type(1)/scalar_type(nb_pts_fc));
190  if (gmm::vect_sp(normal, fc_center -cv_center) < 0)
191  gmm::scale(normal, scalar_type(-1));
192  }
193 
194  /* calculates the normal at a specific point of a convex in a higher
195  * dimension space
196  * Input:
197  * pgt : the geometric transformation of the convex
198  * G_cv : the nodes of the convex, stored in columns
199  * ref_pt: the point in the reference element
200  * Output:
201  * normal: the surface normal in the real element corresponding at
202  * the location of ref_pt in the reference element
203  * (or one of the possible normals if the space dimension
204  * is more than one higher than the convex dimension)
205  */
206  void normal_on_convex
207  (const bgeot::pgeometric_trans pgt, const base_matrix &G_cv,
208  const base_node &ref_pt, base_node &normal) {
209 
210  size_type N = gmm::mat_nrows(G_cv); // dimension of the target space
211  size_type P = pgt->dim(); // dimension of the reference element space
212 
213  GMM_ASSERT1( N == 2 || N == 3, "Normal on convexes calculation is supported "
214  "only for space dimension equal to 2 or 3.");
215  GMM_ASSERT1( P < N, "Normal on convex is defined only in a space of"
216  "higher dimension.");
217 
218  size_type nb_pts = gmm::mat_ncols(G_cv);
219  base_matrix K(N,P);
220  { // calculate K at the final point
221  base_matrix grad_cv(nb_pts, P);
222  pgt->poly_vector_grad(ref_pt, grad_cv);
223  gmm::mult(G_cv, grad_cv, K);
224  }
225 
226  gmm::resize(normal,N);
227  if (P==1 && N == 2) {
228  normal[0] = -K(1,0);
229  normal[1] = K(0,0);
230  }
231  else if (P==1 && N == 3) {
232  normal[0] = K(2,0)-K(1,0);
233  normal[1] = K(0,0)-K(2,0);
234  normal[2] = K(1,0)-K(0,0);
235  }
236  else if (P==2) {
237  normal[0] = K(1,0)*K(2,1)-K(2,0)*K(1,1);
238  normal[1] = K(2,0)*K(0,1)-K(0,0)*K(2,1);
239  normal[2] = K(0,0)*K(1,1)-K(1,0)*K(0,1);
240  }
241  gmm::scale(normal, 1/gmm::vect_norm2(normal));
242  }
243 
244  void projected_fem::build_kdtree(void) const {
245  tree.clear();
246  dal::bit_vector dofs=mf_source.basic_dof_on_region(rg_source);
247  dofs.setminus(blocked_dofs);
248  dim_type qdim=target_dim();
249  for (dal::bv_visitor dof(dofs); !dof.finished(); ++dof)
250  if (dof % qdim == 0)
251  tree.add_point_with_id(mf_source.point_of_basic_dof(dof), dof);
252  }
253 
254  bool projected_fem::find_a_projected_point(base_node pt, base_node &ptr_proj,
255  size_type &cv_proj, short_type &fc_proj) const {
256 
258  //scalar_type dist =
259  tree.nearest_neighbor(ipt, pt);
260 
261  size_type cv_sel = size_type(-1);
262  short_type fc_sel = short_type(-1);
263  scalar_type is_in_sel(1e10);
264  base_node proj_ref, proj_ref_sel;
265  const getfem::mesh::ind_cv_ct cvs = mf_source.convex_to_basic_dof(ipt.i);
266  for (size_type i=0; i < cvs.size(); ++i) {
267  size_type cv = cvs[i];
268  const bgeot::pgeometric_trans pgt = mf_source.linked_mesh().trans_of_convex(cv);
269  if (rg_source.is_in(cv)) { // project on the convex
270  bool gt_invertible;
271  gic = bgeot::geotrans_inv_convex(mf_source.linked_mesh().convex(cv), pgt);
272  gic.invert(pt, proj_ref, gt_invertible);
273  if (gt_invertible) {
274  scalar_type is_in = pgt->convex_ref()->is_in(proj_ref);
275  if (is_in < is_in_sel) {
276  is_in_sel = is_in;
277  cv_sel = cv;
278  fc_sel = short_type(-1);
279  proj_ref_sel = proj_ref;
280  }
281  }
282  }
283  else { // project on convex faces
284  mesh_region::face_bitset faces = rg_source.faces_of_convex(cv);
285  if (faces.count() > 0) { // this should rarely be more than one face
286  bgeot::vectors_to_base_matrix(G, mf_source.linked_mesh().points_of_convex(cv));
287  short_type nbf = mf_source.linked_mesh().nb_faces_of_convex(cv);
288  for (short_type f = 0; f < nbf; ++f) {
289  if (faces.test(f)) {
290  projection_on_convex_face(pgt, G, f, pt, proj_ref);
291  scalar_type is_in = pgt->convex_ref()->is_in(proj_ref);
292  if (is_in < is_in_sel) {
293  is_in_sel = is_in;
294  cv_sel = cv;
295  fc_sel = f;
296  proj_ref_sel = proj_ref;
297  }
298  }
299  }
300  }
301  }
302  }
303  if (cv_sel != size_type(-1) && is_in_sel < 0.05) { //FIXME
304  cv_proj = cv_sel;
305  fc_proj = fc_sel;
306  ptr_proj = proj_ref_sel;
307  return true;
308  }
309  return false;
310  }
311 
313  fictx_cv = size_type(-1);
314  dim_ = dim_type(-1);
315 
316  dim_type N = mf_source.linked_mesh().dim();
317  GMM_ASSERT1( N == mim_target.linked_mesh().dim(),
318  "Dimensions mismatch between the source and the target meshes");
319 
320  build_kdtree();
321 
322  elements.clear();
323  ind_dof.resize(mf_source.nb_basic_dof());
324  size_type max_dof = 0;
325  if (rg_target.id() != mesh_region::all_convexes().id() &&
326  rg_target.is_empty()) {
327  dim_ = mim_target.linked_mesh().dim();
328  return;
329  }
330 
331  for (mr_visitor i(rg_target); !i.finished(); ++i) {
332  size_type cv = i.cv(); // refers to the target mesh
333  short_type f = i.f(); // refers to the target mesh
334 
335  dim_type dim__ = mim_target.linked_mesh().structure_of_convex(cv)->dim();
336  if (dim_ == dim_type(-1)) {
337  dim_ = dim__;
338  if (i.is_face()) dim__ = dim_type(dim__ - 1);
339  GMM_ASSERT1(dim__ < N, "The projection should take place in lower "
340  "dimensions than the mesh dimension. Otherwise "
341  "use the interpolated_fem object instead.");
342  }
343  else
344  GMM_ASSERT1(dim_ == dim__,
345  "Convexes/faces of different dimension in the target mesh");
346 
347  pintegration_method pim = mim_target.int_method_of_element(cv);
348  GMM_ASSERT1(pim->type() == IM_APPROX,
349  "You have to use approximated integration to project a fem");
350  papprox_integration pai = pim->approx_method();
351  bgeot::pgeometric_trans pgt = mim_target.linked_mesh().trans_of_convex(cv);
352  bgeot::pgeotrans_precomp pgp =
353  bgeot::geotrans_precomp(pgt, pai->pintegration_points(), 0);
354  dal::bit_vector dofs;
355  size_type last_cv = size_type(-1); // refers to the source mesh
356  short_type last_f = short_type(-1); // refers to the source mesh
357  size_type nb_pts = i.is_face() ? pai->nb_points_on_face(f) : pai->nb_points();
358  size_type start_pt = i.is_face() ? pai->ind_first_point_on_face(f) : 0;
359  elt_projection_data &e = elements[cv];
360  base_node gpt(N);
361  for (size_type k = 0; k < nb_pts; ++k) {
362  pgp->transform(mim_target.linked_mesh().points_of_convex(cv),
363  start_pt + k, gpt);
364  gausspt_projection_data &gppd = e.gausspt[start_pt + k];
365  gppd.iflags = find_a_projected_point(gpt, gppd.ptref, gppd.cv, gppd.f) ? 1 : 0;
366  if (gppd.iflags) {
367  // calculate gppd.normal
368  const bgeot::pgeometric_trans pgt_source = mf_source.linked_mesh().trans_of_convex(gppd.cv);
369  bgeot::vectors_to_base_matrix(G, mf_source.linked_mesh().points_of_convex(gppd.cv));
370  if (gppd.f != short_type(-1))
371  normal_on_convex_face(pgt_source, G, gppd.f, gppd.ptref, gppd.normal);
372  else
373  normal_on_convex(pgt_source, G, gppd.ptref, gppd.normal);
374  // calculate gppd.gap
375  base_node ppt = pgt_source->transform(gppd.ptref, G);
376  gppd.gap = gmm::vect_sp(gpt-ppt, gppd.normal);
377  }
378 
379  if (gppd.iflags && (last_cv != gppd.cv || last_f != gppd.f)) {
380  if (gppd.f == short_type(-1)) { // convex
381  size_type nbdof = mf_source.nb_basic_dof_of_element(gppd.cv);
382  for (size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
383  size_type idof = mf_source.ind_basic_dof_of_element(gppd.cv)[loc_dof];
384  if (!(blocked_dofs[idof])) dofs.add(idof);
385  }
386  }
387  else { // convex face
388  size_type nbdof = mf_source.nb_basic_dof_of_face_of_element(gppd.cv, gppd.f);
389  for (size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
390  size_type idof = mf_source.ind_basic_dof_of_face_of_element(gppd.cv, gppd.f)[loc_dof];
391  if (!(blocked_dofs[idof])) dofs.add(idof);
392  }
393  }
394  last_cv = gppd.cv;
395  last_f = gppd.f;
396  }
397  }
398  e.nb_dof = dofs.card();
399  e.pim = pim;
400  e.inddof.resize(dofs.card());
401  max_dof = std::max(max_dof, dofs.card());
402  size_type cnt = 0;
403  for (dal::bv_visitor idof(dofs); !idof.finished(); ++idof)
404  { e.inddof[cnt] = idof; ind_dof[idof] = cnt++; }
405  for (size_type k = 0; k < nb_pts; ++k) {
406  gausspt_projection_data &gppd = e.gausspt[start_pt + k];
407  if (gppd.iflags) {
408  if (gppd.f == short_type(-1)) { // convex
409  size_type nbdof = mf_source.nb_basic_dof_of_element(gppd.cv);
410  for (size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
411  size_type idof = mf_source.ind_basic_dof_of_element(gppd.cv)[loc_dof];
412  gppd.local_dof[loc_dof] = dofs.is_in(idof) ? ind_dof[idof]
413  : size_type(-1);
414  }
415  }
416  else { // convex face
417  size_type nbdof = mf_source.nb_basic_dof_of_face_of_element(gppd.cv, gppd.f);
418  pfem pf = mf_source.fem_of_element(gppd.cv);
419  bgeot::convex_ind_ct ind_pts_fc = pf->structure(gppd.cv)->ind_points_of_face(gppd.f);
420  unsigned rdim = target_dim() / pf->target_dim();
421  if (rdim == 1)
422  for (size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) { // local dof with respect to the source convex face
423  size_type idof = mf_source.ind_basic_dof_of_face_of_element(gppd.cv, gppd.f)[loc_dof];
424  size_type loc_dof2 = ind_pts_fc[loc_dof]; // local dof with respect to the source convex
425  gppd.local_dof[loc_dof2] = dofs.is_in(idof) ? ind_dof[idof]
426  : size_type(-1);
427  }
428  else
429  for (size_type ii = 0; ii < nbdof/rdim; ++ii)
430  for (size_type jj = 0; jj < rdim; ++jj) {
431  size_type loc_dof = ii*rdim + jj; // local dof with respect to the source convex face
432  size_type idof = mf_source.ind_basic_dof_of_face_of_element(gppd.cv, gppd.f)[loc_dof];
433  size_type loc_dof2 = ind_pts_fc[ii]*rdim + jj; // local dof with respect to the source convex
434  gppd.local_dof[loc_dof2] = dofs.is_in(idof) ? ind_dof[idof]
435  : size_type(-1);
436  }
437  }
438  }
439  }
440  }
441  /** setup global dofs, with dummy coordinates */
442  base_node P(dim()); gmm::fill(P,1./20);
443  std::vector<base_node> node_tab_(max_dof, P);
444  pspt_override = bgeot::store_point_tab(node_tab_);
445  pspt_valid = false;
446  dof_types_.resize(max_dof);
447  std::fill(dof_types_.begin(), dof_types_.end(),
448  global_dof(dim()));
449 
450  /* ind_dof should be kept full of -1 ( real_base_value and
451  grad_base_value expect that)
452  */
453  std::fill(ind_dof.begin(), ind_dof.end(), size_type(-1));
454  }
455 
457  {
458  context_check();
459  GMM_ASSERT1(mim_target.linked_mesh().convex_index().is_in(cv),
460  "Wrong convex number: " << cv);
461  std::map<size_type,elt_projection_data>::const_iterator eit;
462  eit = elements.find(cv);
463  return (eit != elements.end()) ? eit->second.nb_dof : 0;
464  }
465 
466  size_type projected_fem::index_of_global_dof(size_type cv, size_type i) const
467  {
468  std::map<size_type,elt_projection_data>::const_iterator eit;
469  eit = elements.find(cv);
470  GMM_ASSERT1(eit != elements.end(), "Wrong convex number: " << cv);
471  return eit->second.inddof[i];
472  }
473 
474  bgeot::pconvex_ref projected_fem::ref_convex(size_type cv) const
475  { return mim_target.int_method_of_element(cv)->approx_method()->ref_convex(); }
476 
478  {
479  GMM_ASSERT1(mim_target.linked_mesh().convex_index().is_in(cv),
480  "Wrong convex number: " << cv);
482  (dim(), nb_dof(cv),
483  mim_target.linked_mesh().structure_of_convex(cv)->nb_faces()));
484  }
485 
486  void projected_fem::base_value(const base_node &, base_tensor &) const
487  { GMM_ASSERT1(false, "No base values, real only element."); }
488  void projected_fem::grad_base_value(const base_node &,
489  base_tensor &) const
490  { GMM_ASSERT1(false, "No grad values, real only element."); }
491  void projected_fem::hess_base_value(const base_node &,
492  base_tensor &) const
493  { GMM_ASSERT1(false, "No hess values, real only element."); }
494 
495  inline void projected_fem::actualize_fictx(pfem pf, size_type cv,
496  const base_node &ptr) const {
497  if (fictx_cv != cv) {
498  bgeot::vectors_to_base_matrix
499  (G, mf_source.linked_mesh().points_of_convex(cv));
501  (mf_source.linked_mesh().trans_of_convex(cv), pf, base_node(), G, cv);
502  fictx_cv = cv;
503  }
504  fictx.set_xref(ptr);
505  }
506 
508  base_tensor &t, bool) const {
509  std::map<size_type,elt_projection_data>::iterator eit;
510  eit = elements.find(c.convex_num());
511  if (eit == elements.end()) {
512  mi2[1] = target_dim(); mi2[0] = short_type(0);
513  t.adjust_sizes(mi2);
514  std::fill(t.begin(), t.end(), scalar_type(0));
515  return;
516  }
517 // GMM_ASSERT1(eit != elements.end(), "Wrong convex number: " << c.convex_num());
518  elt_projection_data &e = eit->second;
519 
520  mi2[1] = target_dim(); mi2[0] = short_type(e.nb_dof);
521  t.adjust_sizes(mi2);
522  std::fill(t.begin(), t.end(), scalar_type(0));
523  if (e.nb_dof == 0) return;
524 
525  std::map<size_type,gausspt_projection_data>::iterator git;
526  git = e.gausspt.find(c.ii());
527  if (c.have_pgp() &&
528  (c.pgp()->get_ppoint_tab()
529  == e.pim->approx_method()->pintegration_points()) &&
530  git != e.gausspt.end()) {
531  gausspt_projection_data &gppd = git->second;
532  if (gppd.iflags & 1) {
533  if (gppd.iflags & 2) {
534  t = gppd.base_val;
535  return;
536  }
537  size_type cv = gppd.cv;
538  pfem pf = mf_source.fem_of_element(cv);
539  actualize_fictx(pf, cv, gppd.ptref);
540  pf->real_base_value(fictx, taux);
541  unsigned rdim = target_dim() / pf->target_dim();
542  std::map<size_type,size_type>::const_iterator ii;
543  if (rdim == 1) // mdim == 0
544  for (size_type i = 0; i < pf->nb_dof(cv); ++i) {
545  ii = gppd.local_dof.find(i);
546  if (ii != gppd.local_dof.end() && ii->second != size_type(-1))
547  for (size_type j = 0; j < target_dim(); ++j)
548  t(ii->second,j) = taux(i,j);
549  }
550  else // mdim == 1
551  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
552  for (size_type j = 0; j < target_dim(); ++j) {
553  ii = gppd.local_dof.find(i*rdim+j);
554  if (ii != gppd.local_dof.end() && ii->second != size_type(-1))
555  t(ii->second,j) = taux(i,0);
556  }
557 
558  if (store_values) {
559  gppd.base_val = t;
560  gppd.iflags |= 2;
561  }
562  }
563  }
564  else {
565  size_type cv;
566  short_type f;
567  if (find_a_projected_point(c.xreal(), ptref, cv, f)) {
568  pfem pf = mf_source.fem_of_element(cv);
569  actualize_fictx(pf, cv, ptref);
570  pf->real_base_value(fictx, taux);
571 
572  for (size_type i = 0; i < e.nb_dof; ++i)
573  ind_dof.at(e.inddof[i]) = i;
574 
575  unsigned rdim = target_dim() / pf->target_dim();
576  if (rdim == 1) // mdim == 0
577  for (size_type i = 0; i < pf->nb_dof(cv); ++i) {
578  size_type ii = ind_dof.at(mf_source.ind_basic_dof_of_element(cv)[i]);
579  if (ii != size_type(-1)) {
580  for (size_type j = 0; j < target_dim(); ++j)
581  t(ii,j) = taux(i,j);
582  }
583  }
584  else // mdim == 1
585  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
586  for (size_type j = 0; j < target_dim(); ++j) {
587  size_type ij = ind_dof.at(mf_source.ind_basic_dof_of_element(cv)[i*rdim+j]);
588  if (ij != size_type(-1))
589  t(ij,j) = taux(i,0);
590  }
591 
592  for (size_type i = 0; i < e.nb_dof; ++i)
593  ind_dof[e.inddof[i]] = size_type(-1);
594  }
595  }
596 
597  }
598 
600  base_tensor &t, bool) const {
601  std::map<size_type,elt_projection_data>::iterator eit;
602  eit = elements.find(c.convex_num());
603  if (eit == elements.end()) {
604  mi3[2] = mf_source.linked_mesh().dim(); mi3[1] = target_dim(); mi3[0] = short_type(0);
605  t.adjust_sizes(mi2);
606  std::fill(t.begin(), t.end(), scalar_type(0));
607  return;
608  }
609 // GMM_ASSERT1(eit != elements.end(), "Wrong convex number: " << c.convex_num());
610  elt_projection_data &e = eit->second;
611 
612  size_type N = mf_source.linked_mesh().dim();
613  mi3[2] = short_type(N); mi3[1] = target_dim(); mi3[0] = short_type(e.nb_dof);
614  t.adjust_sizes(mi3);
615  std::fill(t.begin(), t.end(), scalar_type(0));
616  if (e.nb_dof == 0) return;
617 
618  std::map<size_type,gausspt_projection_data>::iterator git;
619  git = e.gausspt.find(c.ii());
620  if (c.have_pgp() &&
621  (c.pgp()->get_ppoint_tab()
622  == e.pim->approx_method()->pintegration_points()) &&
623  git != e.gausspt.end()) {
624  gausspt_projection_data &gppd = git->second;
625  if (gppd.iflags & 1) {
626  if (gppd.iflags & 4) {
627  t = gppd.grad_val;
628  return;
629  }
630  size_type cv = gppd.cv;
631  pfem pf = mf_source.fem_of_element(cv);
632  actualize_fictx(pf, cv, gppd.ptref);
633  pf->real_grad_base_value(fictx, taux);
634 
635  unsigned rdim = target_dim() / pf->target_dim();
636  std::map<size_type,size_type>::const_iterator ii;
637  if (rdim == 1) // mdim == 0
638  for (size_type i = 0; i < pf->nb_dof(cv); ++i) {
639  ii = gppd.local_dof.find(i);
640  if (ii != gppd.local_dof.end() && ii->second != size_type(-1))
641  for (size_type j = 0; j < target_dim(); ++j)
642  for (size_type k = 0; k < N; ++k)
643  t(ii->second, j, k) = taux(i, j, k);
644  }
645  else // mdim == 1
646  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
647  for (size_type j = 0; j < target_dim(); ++j) {
648  ii = gppd.local_dof.find(i*rdim+j);
649  if (ii != gppd.local_dof.end() && ii->second != size_type(-1))
650  for (size_type k = 0; k < N; ++k)
651  t(ii->second, j, k) = taux(i, 0, k);
652  }
653  if (store_values) {
654  gppd.grad_val = t;
655  gppd.iflags |= 4;
656  }
657  }
658  }
659  else {
660  size_type cv;
661  short_type f;
662  if (find_a_projected_point(c.xreal(), ptref, cv, f)) {
663  pfem pf = mf_source.fem_of_element(cv);
664  actualize_fictx(pf, cv, ptref);
665  pf->real_grad_base_value(fictx, taux);
666  for (size_type i = 0; i < e.nb_dof; ++i)
667  ind_dof.at(e.inddof[i]) = i;
668 
669  unsigned rdim = target_dim() / pf->target_dim();
670  if (rdim == 1) // mdim == 0
671  for (size_type i = 0; i < pf->nb_dof(cv); ++i) {
672  size_type ii = ind_dof.at(mf_source.ind_basic_dof_of_element(cv)[i]);
673  if (ii != size_type(-1))
674  for (size_type j = 0; j < target_dim(); ++j)
675  for (size_type k = 0; k < N; ++k)
676  t(ii,j,k) = taux(i,j,k);
677  }
678  else // mdim == 1
679  for (size_type i = 0; i < pf->nb_dof(cv); ++i)
680  for (size_type j = 0; j < target_dim(); ++j) {
681  size_type ij = ind_dof.at(mf_source.ind_basic_dof_of_element(cv)[i*rdim+j]);
682  if (ij != size_type(-1))
683  for (size_type k = 0; k < N; ++k)
684  t(ij,j,k) = taux(i,0,k);
685  }
686 
687  for (size_type i = 0; i < e.nb_dof; ++i)
688  ind_dof[e.inddof[i]] = size_type(-1);
689  }
690  }
691  }
692 
694  (const fem_interpolation_context&, base_tensor &, bool) const
695  { GMM_ASSERT1(false, "Sorry, to be done."); }
696 
697  void projected_fem::projection_data(const fem_interpolation_context& c,
698  base_node &normal, scalar_type &gap) const {
699  std::map<size_type,elt_projection_data>::iterator eit;
700  eit = elements.find(c.convex_num());
701 
702  if (eit != elements.end()) {
703  elt_projection_data &e = eit->second;
704  if (e.nb_dof == 0) { // return undefined normal vector and huge gap
705  normal = base_node(c.N());
706  gap = 1e12;
707  return;
708  }
709  std::map<size_type,gausspt_projection_data>::iterator git;
710  git = e.gausspt.find(c.ii());
711  if (c.have_pgp() &&
712  (c.pgp()->get_ppoint_tab()
713  == e.pim->approx_method()->pintegration_points()) &&
714  git != e.gausspt.end()) {
715  gausspt_projection_data &gppd = git->second;
716  if (gppd.iflags & 1) {
717  normal = gppd.normal;
718  gap = gppd.gap;
719  }
720  else { // return undefined normal vector and huge gap
721  normal = base_node(c.N());
722  gap = 1e12;
723  }
724  return;
725  }
726  }
727 
728  // new projection
729  projection_data(c.xreal(), normal, gap);
730  }
731 
732  void projected_fem::projection_data(const base_node& pt,
733  base_node &normal, scalar_type &gap) const {
734  size_type cv;
735  short_type f;
736  if (find_a_projected_point(pt, ptref, cv, f)) {
737  const bgeot::pgeometric_trans pgt = mf_source.linked_mesh().trans_of_convex(cv);
738  bgeot::vectors_to_base_matrix(G, mf_source.linked_mesh().points_of_convex(cv));
739  if (f != short_type(-1))
740  normal_on_convex_face(pgt, G, f, ptref, normal);
741  else
742  normal_on_convex(pgt, G, ptref, normal);
743  base_node ppt = pgt->transform(ptref, G);
744  gap = gmm::vect_sp(pt-ppt, normal);
745  }
746  else { // return undefined normal vector and huge gap
747  normal = base_node(pt.size());
748  gap = 1e12;
749  }
750 
751  }
752 
753  dal::bit_vector projected_fem::projected_convexes() const {
754  dal::bit_vector bv;
755  std::map<size_type,elt_projection_data>::const_iterator eit;
756  for (eit = elements.begin(); eit != elements.end(); ++eit) {
757  std::map<size_type,gausspt_projection_data>::const_iterator git;
758  for (git = eit->second.gausspt.begin(); git != eit->second.gausspt.end(); ++git) {
759  if (git->second.iflags)
760  bv.add(git->second.cv);
761  }
762  }
763  return bv;
764  }
765 
766  void projected_fem::gauss_pts_stats(unsigned &ming, unsigned &maxg,
767  scalar_type &meang) const {
768  std::vector<unsigned> v(mf_source.linked_mesh().nb_allocated_convex());
769  std::map<size_type,elt_projection_data>::const_iterator eit;
770  for (eit = elements.begin(); eit != elements.end(); ++eit) {
771  std::map<size_type,gausspt_projection_data>::const_iterator git;
772  for (git = eit->second.gausspt.begin(); git != eit->second.gausspt.end(); ++git) {
773  if (git->second.iflags)
774  v[git->second.cv]++;
775  }
776  }
777 
778  ming = 100000; maxg = 0; meang = 0;
779  unsigned cntg = 0;
780  for (dal::bv_visitor cv(mf_source.linked_mesh().convex_index());
781  !cv.finished(); ++cv) {
782  ming = std::min(ming, v[cv]);
783  maxg = std::max(maxg, v[cv]);
784  meang += v[cv];
785  if (v[cv] > 0) ++cntg;
786  }
787  meang /= scalar_type(cntg);
788  }
789 
790  size_type projected_fem::memsize() const {
791  size_type sz = 0;
792  sz += blocked_dofs.memsize();
793  sz += sizeof(*this);
794  sz += elements.size() * sizeof(elt_projection_data); // Wrong for std::map
795  std::map<size_type,elt_projection_data>::const_iterator eit;
796  for (eit = elements.begin(); eit != elements.end(); ++eit) {
797  sz += eit->second.gausspt.size() * sizeof(gausspt_projection_data); // Wrong for std::map
798  sz += eit->second.inddof.capacity() * sizeof(size_type);
799  std::map<size_type,gausspt_projection_data>::const_iterator git;
800  for (git = eit->second.gausspt.begin(); git != eit->second.gausspt.end(); ++git) {
801  sz += git->second.local_dof.size() * sizeof(size_type); // Wrong for std::map
802  }
803  }
804  return sz;
805  }
806 
807  projected_fem::projected_fem(const mesh_fem &mf_source_,
808  const mesh_im &mim_target_,
809  size_type rg_source_,
810  size_type rg_target_,
811  dal::bit_vector blocked_dofs_, bool store_val)
812  : mf_source(mf_source_), mim_target(mim_target_),
813  rg_source(mf_source.linked_mesh().region(rg_source_)),
814  rg_target(mim_target.linked_mesh().region(rg_target_)),
815  store_values(store_val), blocked_dofs(blocked_dofs_), mi2(2), mi3(3) {
816  this->add_dependency(mf_source);
817  this->add_dependency(mim_target);
818  is_pol = is_lag = is_standard_fem = false; es_degree = 5;
819  is_equiv = real_element_defined = true;
820  ntarget_dim = mf_source.get_qdim();
821 
823  }
824 
825  DAL_SIMPLE_KEY(special_projfem_key, pfem);
826 
827  pfem new_projected_fem(const mesh_fem &mf_source_, const mesh_im &mim_target_,
828  size_type rg_source_, size_type rg_target_,
829  dal::bit_vector blocked_dofs_, bool store_val) {
830  pfem pf = std::make_shared<projected_fem>
831  (mf_source_, mim_target_, rg_source_, rg_target_,blocked_dofs_,store_val);
832  dal::pstatic_stored_object_key
833  pk = std::make_shared<special_projfem_key>(pf);
834  dal::add_stored_object(pk, pf);
835  return pf;
836  }
837 
838 
839 } /* end of namespace getfem. */
840 
virtual size_type nb_basic_dof_of_element(size_type cv) const
Return the number of degrees of freedom attached to a given convex.
pfem new_projected_fem(const mesh_fem &mf_source, const mesh_im &mim_target, size_type rg_source_=size_type(-1), size_type rg_target_=size_type(-1), dal::bit_vector blocked_dofs=dal::bit_vector(), bool store_val=true)
create a new projected FEM.
virtual pintegration_method int_method_of_element(size_type cv) const
return the integration method associated with an element (in no integration is associated, the function will crash! use the convex_index() of the mesh_im to check that a fem is associated to a given convex)
indexed array reference (given a container X, and a set of indexes I, this class provides a pseudo-co...
Definition: gmm_ref.h:289
static mesh_region all_convexes()
provide a default value for the mesh_region parameters of assembly procedures etc.
void real_grad_base_value(const fem_interpolation_context &c, base_tensor &t, bool=true) const
Give the gradient of all components of the base functions at the current point of the fem_interpolati...
size_type convex_num() const
get the current convex number
Definition: getfem_fem.cc:52
dim_type dim() const
dimension of the reference element.
Definition: getfem_fem.h:306
virtual const bgeot::convex< base_node > & node_convex(size_type cv) const
Gives the convex representing the nodes on the reference element.
virtual pfem fem_of_element(size_type cv) const
Return the basic fem associated with an element (if no fem is associated, the function will crash! us...
ref_convex convex(size_type ic) const
return a bgeot::convex object for the convex number ic.
Definition: getfem_mesh.h:189
pconvex_structure structure_of_convex(size_type ic) const
Return the pconvex_structure of the convex ic.
does the inversion of the geometric transformation for a given convex
Describe an integration method linked to a mesh.
const base_node & xreal() const
coordinates of the current point, in the real convex.
virtual const mesh::ind_cv_ct & convex_to_basic_dof(size_type d) const
Return the list of convexes attached to the specified dof.
FEM which projects a mesh_fem on a different mesh.
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
Definition: gmm_blas.h:557
virtual void update_from_context(void) const
this function has to be defined and should update the object when the context is modified.
void grad_base_value(const base_node &, base_tensor &) const
Give the value of all gradients (on ref.
virtual size_type nb_dof(size_type cv) const
Number of degrees of freedom.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
virtual size_type nb_basic_dof() const
Return the total number of basic degrees of freedom (before the optional reduction).
virtual dal::bit_vector basic_dof_on_region(const mesh_region &b) const
Get a list of basic dof lying on a given mesh_region.
void real_base_value(const fem_interpolation_context &c, base_tensor &t, bool=true) const
Give the value of all components of the base functions at the current point of the fem_interpolation_...
virtual size_type nb_basic_dof_of_face_of_element(size_type cv, short_type f) const
Return the number of dof lying on the given convex face.
virtual dim_type get_qdim() const
Return the Q dimension.
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 ...
structure passed as the argument of fem interpolation functions.
Definition: getfem_fem.h:741
virtual base_node point_of_basic_dof(size_type cv, size_type i) const
Return the geometrical location of a degree of freedom.
virtual bgeot::pconvex_ref ref_convex(size_type cv) const
Return the convex of the reference element.
dim_type target_dim() const
dimension of the target space.
Definition: getfem_fem.h:309
"iterator" class for regions.
GEneric Tool for Finite Element Methods.
void base_value(const base_node &, base_tensor &) const
Give the value of all components of the base functions at the point x of the reference element...
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:239
Describe a finite element method linked to a mesh.
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:79
void add_point_with_id(const base_node &n, size_type i)
insert a new point, with an associated number.
Definition: bgeot_kdtree.h:117
void clear()
reset the tree, remove all points
Definition: bgeot_kdtree.h:110
size_type nb_allocated_convex() const
The number of convex indexes from 0 to the index of the last convex.
dal::bit_vector projected_convexes() const
return the list of convexes of the projected mesh_fem which contain at least one gauss point (should ...
void hess_base_value(const base_node &, base_tensor &) const
Give the value of all hessians (on ref.
store a point and the associated index for the kdtree.
Definition: bgeot_kdtree.h:59
virtual ind_dof_face_ct ind_basic_dof_of_face_of_element(size_type cv, short_type f) const
Give an array of the dof numbers lying of a convex face (all degrees of freedom whose associated base...
void set_xref(const base_node &P)
change the current point (coordinates given in the reference convex)
void mult_add(const L1 &l1, const L2 &l2, L3 &l3)
*/
Definition: gmm_blas.h:1779
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
const mesh & linked_mesh() const
Give a reference to the linked mesh of type mesh.
pconvex_ref generic_dummy_convex_ref(dim_type nc, size_type n, short_type nf)
generic convex with n global nodes
bool context_check() const
return true if update_from_context was called
void gauss_pts_stats(unsigned &ming, unsigned &maxg, scalar_type &meang) const
return the min/max/mean number of gauss points in the convexes of the projected mesh_fem ...
short_type nb_faces_of_convex(size_type ic) const
Return the number of faces of convex ic.
const mesh_region region(size_type id) const
Return the region of index &#39;id&#39;.
Definition: getfem_mesh.h:414
pdof_description global_dof(dim_type d)
Description of a global dof, i.e.
Definition: getfem_fem.cc:521
virtual ind_dof_ct ind_basic_dof_of_element(size_type cv) const
Give an array of the dof numbers a of convex.
void resize(M &v, size_type m, size_type n)
*/
Definition: gmm_blas.h:231
void real_hess_base_value(const fem_interpolation_context &, base_tensor &, bool=true) const
Give the hessian of all components of the base functions at the current point of the fem_interpolatio...
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation