39 #ifndef GETFEM_INTERPOLATION_H__
40 #define GETFEM_INTERPOLATION_H__
59 typedef std::set<size_type>::const_iterator set_iterator;
60 typedef std::map<size_type,size_type>::const_iterator map_iterator;
63 std::vector<std::set<size_type> > pts_cvx;
64 std::vector<base_node> ref_coords;
65 std::map<size_type,size_type> ids;
70 {
return pts_cvx[i].size(); }
71 void points_on_convex(
size_type i, std::vector<size_type> &itab)
const;
73 const std::vector<base_node> &reference_coords(
void)
const {
return ref_coords; }
75 void add_point_with_id(base_node n,
size_type id)
78 const mesh &linked_mesh(
void)
const {
return msh; }
90 void distribute(
int extrapolation = 0,
92 mesh_trans_inv(
const mesh &m,
double EPS_ = 1E-12)
93 :
bgeot::geotrans_inv(EPS_), msh(m) {}
104 template <
typename VECT,
typename F,
typename M>
105 inline void interpolation_function__(
const mesh_fem &mf, VECT &V,
106 F &f,
const dal::bit_vector &dofs,
107 const M &, gmm::abstract_null_type) {
109 GMM_ASSERT1(gmm::vect_size(V) == mf.nb_basic_dof() && Q == 1,
110 "Dof vector has not the right size");
111 for (dal::bv_visitor i(dofs); !i.finished(); ++i)
112 V[i] = f(mf.point_of_basic_dof(i));
115 template <
typename VECT,
typename F,
typename M>
116 inline void interpolation_function__(
const mesh_fem &mf, VECT &V,
117 F &f,
const dal::bit_vector &dofs,
118 const M &v, gmm::abstract_vector) {
119 size_type N = gmm::vect_size(v), Q = mf.get_qdim();
120 GMM_ASSERT1(gmm::vect_size(V) == mf.nb_basic_dof()*N/Q,
121 "Dof vector has not the right size");
122 for (dal::bv_visitor i(dofs); !i.finished(); ++i)
124 gmm::copy(f(mf.point_of_basic_dof(i)),
125 gmm::sub_vector(V, gmm::sub_interval(i*N/Q, N)));
128 template <
typename VECT,
typename F,
typename M>
129 inline void interpolation_function__(
const mesh_fem &mf, VECT &V,
130 F &f,
const dal::bit_vector &dofs,
131 const M &mm, gmm::abstract_matrix) {
133 size_type Nr = gmm::mat_nrows(mm), Nc = gmm::mat_ncols(mm), N = Nr*Nc;
135 base_matrix m(Nr, Nc);
136 GMM_ASSERT1(gmm::vect_size(V) == mf.nb_basic_dof()*N/Q,
137 "Dof vector has not the right size");
138 for (dal::bv_visitor i(dofs); !i.finished(); ++i)
140 gmm::copy(f(mf.point_of_basic_dof(i)), m);
142 gmm::copy(gmm::mat_col(m, j),
143 gmm::sub_vector(V, gmm::sub_interval(i*N/Q+j*Nr, Nr)));
148 template <
typename VECT,
typename F,
typename M>
149 inline void interpolation_function_(
const mesh_fem &mf, VECT &V,
150 F &f,
const dal::bit_vector &dofs,
152 interpolation_function__(mf, V, f, dofs, m,
153 typename gmm::linalg_traits<M>::linalg_type());
156 #if GETFEM_PARA_LEVEL > 0
157 template <
typename T>
158 void take_one_op(
void *a,
void *b,
int *len, MPI_Datatype *) {
160 return aa ? aa : *((T*)b);
163 template <
typename T>
164 inline MPI_Op mpi_take_one_op(T) {
165 static bool isinit =
false;
168 MPI_Op_create(take_one_op<T>,
true, &op);
185 template <
typename VECT,
typename F>
188 typedef typename gmm::linalg_traits<VECT>::value_type T;
191 mf_target.
linked_mesh().intersect_with_mpi_region(rg);
194 interpolation_function_(mf_target, V, f, dofs,
203 gmm::sub_vector(
const_cast<VECT &
>(VV),
204 gmm::sub_slice(k, mf_target.
nb_dof(),
208 gmm::copy(V,
const_cast<VECT &
>(VV));
237 template<
typename VECTU,
typename VECTV>
238 void interpolation(
const mesh_fem &mf_source,
const mesh_fem &mf_target,
239 const VECTU &U, VECTV &V,
int extrapolation = 0,
256 template<
typename MAT>
257 void interpolation(
const mesh_fem &mf_source,
const mesh_fem &mf_target,
258 MAT &M,
int extrapolation = 0,
double EPS = 1E-10,
274 template<
typename VECTU,
typename VECTV,
typename MAT>
275 void interpolation_same_mesh(
const mesh_fem &mf_source,
276 const mesh_fem &mf_target,
277 const VECTU &UU, VECTV &VV,
278 MAT &MM,
int version) {
280 typedef typename gmm::linalg_traits<VECTU>::value_type T;
282 dim_type qdim = mf_source.get_qdim();
283 dim_type qqdim = dim_type(gmm::vect_size(UU)/mf_source.nb_dof());
284 std::vector<T> val(qdim);
285 std::vector<std::vector<T> > coeff;
286 std::vector<size_type> dof_source;
287 GMM_ASSERT1(qdim == mf_target.get_qdim() || mf_target.get_qdim() == 1,
288 "Attempt to interpolate a field of dimension "
289 << qdim <<
" on a mesh_fem whose Qdim is " <<
290 int(mf_target.get_qdim()));
291 size_type qmult = mf_source.get_qdim()/mf_target.get_qdim();
292 size_type qqdimt = qqdim * mf_source.get_qdim()/mf_target.get_qdim();
293 fem_precomp_pool fppool;
294 std::vector<size_type> dof_t_passes(mf_target.nb_basic_dof());
295 std::vector<T> U(mf_source.nb_basic_dof()*qqdim);
296 std::vector<T> V(mf_target.nb_basic_dof()*qqdimt);
297 gmm::row_matrix<gmm::rsvector<scalar_type> >
298 M(mf_target.nb_basic_dof(), mf_source.nb_basic_dof());
300 if (version == 0) mf_source.extend_vector(UU, U);
303 for (dal::bv_visitor cv(mf_source.convex_index()); !cv.finished(); ++cv) {
305 pfem pf_s = mf_source.fem_of_element(cv);
306 if (!mf_target.convex_index().is_in(cv))
308 pfem pf_t = mf_target.fem_of_element(cv);
311 mesh_fem::ind_dof_ct::const_iterator itdof;
312 size_type cvnbdof = mf_source.nb_basic_dof_of_element(cv);
314 bool discontinuous_source =
false;
315 for (
size_type dof=0; dof < nbd_s; ++dof)
317 discontinuous_source =
true;
324 coeff[qq].resize(cvnbdof);
325 itdof = mf_source.ind_basic_dof_of_element(cv).begin();
326 for (
size_type k = 0; k < cvnbdof; ++k, ++itdof) {
327 coeff[qq][k] = U[(*itdof)*qqdim+qq];
332 bgeot::vectors_to_base_matrix
333 (G, mf_source.linked_mesh().points_of_convex(cv));
335 GMM_ASSERT1(pf_t->target_dim() == 1,
336 "won't interpolate on a vector FEM... ");
337 pfem_precomp pfp = fppool(pf_s, pf_t->node_tab(cv));
338 fem_interpolation_context ctx(pgt,pfp,
size_type(-1), G, cv,
340 itdof = mf_target.ind_basic_dof_of_element(cv).begin();
342 const mesh_fem::ind_dof_ct &idct
343 = mf_source.ind_basic_dof_of_element(cv);
344 dof_source.assign(idct.begin(), idct.end());
346 for (
size_type i = 0; i < nbd_t; ++i, itdof+=mf_target.get_qdim()) {
348 if (!discontinuous_source && dof_t_passes[*itdof] > 0)
continue;
349 dof_t_passes[*itdof] += 1;
353 pf_s->interpolation(ctx, coeff[qq], val, qdim);
355 V[(dof_t + k)*qqdim+qq] += val[k];
359 base_matrix Mloc(qdim, mf_source.nb_basic_dof_of_element(cv));
360 pf_s->interpolation(ctx, Mloc, qdim);
362 for (
size_type j=0; j < dof_source.size(); ++j) {
363 M(dof_t + k, dof_source[j]) += Mloc(k, j);
371 for (
size_type i = 0; i < mf_target.nb_basic_dof(); ++i) {
373 scalar_type passes = scalar_type(dof_t_passes[i]);
374 if (version == 0 && passes > scalar_type(0))
377 V[(dof_t + k)*qqdim+qq] /= passes;
378 else if (passes > scalar_type(0))
380 for (
size_type j=0; j < dof_source.size(); ++j)
381 gmm::scale(gmm::mat_row(M, dof_t + k), scalar_type(1)/passes);
385 mf_target.reduce_vector(V, VV);
387 if (mf_target.is_reduced())
388 if (mf_source.is_reduced()) {
389 gmm::row_matrix<gmm::rsvector<scalar_type> >
390 MMM(mf_target.nb_dof(), mf_source.nb_basic_dof());
391 gmm::mult(mf_target.reduction_matrix(), M, MMM);
392 gmm::mult(MMM, mf_source.extension_matrix(), MM);
395 gmm::mult(mf_target.reduction_matrix(), M, MM);
397 if (mf_source.is_reduced())
398 gmm::mult(M, mf_source.extension_matrix(), MM);
410 template<
typename VECTU,
typename VECTV,
typename MAT>
413 const VECTU &UU, VECTV &V, MAT &MM,
414 int version,
int extrapolation = 0,
415 dal::bit_vector *dof_untouched = 0,
418 typedef typename gmm::linalg_traits<VECTU>::value_type T;
419 const mesh &msh(mf_source.linked_mesh());
420 dim_type qdim_s = mf_source.get_qdim();
421 dim_type qqdim = dim_type(gmm::vect_size(UU)/mf_source.nb_dof());
423 std::vector<T> U(mf_source.nb_basic_dof()*qqdim);
424 gmm::row_matrix<gmm::rsvector<scalar_type> > M;
425 if (version != 0) M.resize(gmm::mat_nrows(MM), mf_source.nb_basic_dof());
427 if (version == 0) mf_source.extend_vector(UU, U);
429 mti.distribute(extrapolation, rg_source);
430 std::vector<size_type> itab;
434 dal::bit_vector points_to_do; points_to_do.add(0, mti.nb_points());
435 std::vector<T> val(qdim_s);
436 std::vector<std::vector<T> > coeff;
438 std::vector<size_type> dof_source;
440 for (dal::bv_visitor cv(mf_source.convex_index()); !cv.finished(); ++cv) {
442 mti.points_on_convex(cv, itab);
443 if (itab.size() == 0)
continue;
445 pfem pf_s = mf_source.fem_of_element(cv);
447 bgeot::vectors_to_base_matrix(G, msh.points_of_convex(cv));
449 fem_interpolation_context ctx(pgt, pf_s, base_node(), G, cv,
453 size_type cvnbdof = mf_source.nb_basic_dof_of_element(cv);
454 mesh_fem::ind_dof_ct::const_iterator itdof;
456 coeff[qq].resize(cvnbdof);
457 itdof = mf_source.ind_basic_dof_of_element(cv).begin();
458 for (
size_type k = 0; k < cvnbdof; ++k, ++itdof) {
459 coeff[qq][k] = U[(*itdof)*qqdim+qq];
464 const mesh_fem::ind_dof_ct &idct
465 = mf_source.ind_basic_dof_of_element(cv);
466 dof_source.assign(idct.begin(), idct.end());
468 for (
size_type i = 0; i < itab.size(); ++i) {
470 if (points_to_do.is_in(ipt)) {
471 points_to_do.sup(ipt);
472 ctx.set_xref(mti.reference_coords()[ipt]);
477 pf_s->interpolation(ctx, coeff[qq], val, qdim_s);
479 V[(pos + k)*qqdim+qq] = val[k];
489 base_matrix Mloc(qdim_s, mf_source.nb_basic_dof_of_element(cv));
490 pf_s->interpolation(ctx, Mloc, qdim_s);
492 for (
size_type j=0; j < gmm::mat_ncols(Mloc); ++j)
493 M(pos+k, dof_source[j]) = Mloc(k,j);
504 if (points_to_do.card() != 0) {
506 dof_untouched->clear();
507 for (dal::bv_visitor ipt(points_to_do); !ipt.finished(); ++ipt)
508 dof_untouched->add(mti.id_of_point(ipt));
511 dal::bit_vector dofs_to_do;
512 for (dal::bv_visitor ipt(points_to_do); !ipt.finished(); ++ipt)
513 dofs_to_do.add(mti.id_of_point(ipt));
514 GMM_WARNING2(
"in interpolation (different meshes),"
515 << dofs_to_do.card() <<
" dof of target mesh_fem have "
516 <<
" been missed\nmissing dofs : " << dofs_to_do);
521 if (mf_source.is_reduced())
522 gmm::mult(M, mf_source.extension_matrix(), MM);
529 template<
typename VECTU,
typename VECTV>
530 void interpolation(
const mesh_fem &mf_source, mesh_trans_inv &mti,
531 const VECTU &U, VECTV &V,
int extrapolation = 0,
532 dal::bit_vector *dof_untouched = 0,
535 GMM_ASSERT1((gmm::vect_size(U) % mf_source.nb_dof()) == 0 &&
536 gmm::vect_size(V)!=0,
"Dimension of vector mismatch");
537 interpolation(mf_source, mti, U, V, M, 0, extrapolation, dof_untouched, rg_source);
547 template<
typename VECTU,
typename VECTV,
typename MAT>
548 void interpolation(
const mesh_fem &mf_source,
const mesh_fem &mf_target,
549 const VECTU &U, VECTV &VV, MAT &MM,
550 int version,
int extrapolation,
556 const torus_mesh_fem * pmf_torus =
dynamic_cast<const torus_mesh_fem *
>(&mf_target);
558 interpolation_to_torus_mesh_fem(mf_source, *pmf_torus,
559 U, VV, MM, version, extrapolation, EPS, rg_source, rg_target);
563 typedef typename gmm::linalg_traits<VECTU>::value_type T;
564 dim_type qqdim = dim_type(gmm::vect_size(U)/mf_source.nb_dof());
565 size_type qqdimt = qqdim * mf_source.get_qdim()/mf_target.get_qdim();
566 std::vector<T> V(mf_target.nb_basic_dof()*qqdimt);
567 mf_target.extend_vector(VV,V);
568 gmm::row_matrix<gmm::rsvector<scalar_type> > M;
569 if (version != 0) M.resize(mf_target.nb_basic_dof(), mf_source.nb_dof());
571 const mesh &msh(mf_source.linked_mesh());
572 getfem::mesh_trans_inv mti(msh, EPS);
573 size_type qdim_s = mf_source.get_qdim(), qdim_t = mf_target.get_qdim();
574 GMM_ASSERT1(qdim_s == qdim_t || qdim_t == 1,
575 "Attempt to interpolate a field of dimension "
576 << qdim_s <<
" on a mesh_fem whose Qdim is " << qdim_t);
579 for (dal::bv_visitor cv(mf_target.convex_index()); !cv.finished();++cv) {
580 pfem pf_t = mf_target.fem_of_element(cv);
581 GMM_ASSERT1(pf_t->target_dim() == 1 && pf_t->is_lagrange(),
582 "Target fem not convenient for interpolation");
585 bool is_target_torus =
dynamic_cast<const torus_mesh *
>(&mf_target.linked_mesh());
587 size_type nbpts = mf_target.nb_basic_dof() / qdim_t;
589 if (is_target_torus){
590 auto p = mf_target.point_of_basic_dof(i * qdim_t);
594 else mti.add_point(mf_target.point_of_basic_dof(i * qdim_t));
598 for (dal::bv_visitor_c dof(mf_target.basic_dof_on_region(rg_target));
599 !dof.finished(); ++dof)
600 if (dof % qdim_t == 0){
601 if (is_target_torus){
602 auto p = mf_target.point_of_basic_dof(dof);
604 mti.add_point_with_id(p, dof/qdim_t);
607 mti.add_point_with_id(mf_target.point_of_basic_dof(dof),dof/qdim_t);
610 interpolation(mf_source, mti, U, V, M, version, extrapolation, 0,rg_source);
613 mf_target.reduce_vector(V, VV);
615 if (mf_target.is_reduced())
616 gmm::mult(mf_target.reduction_matrix(), M, MM);
627 template<
typename VECTU,
typename VECTV,
typename MAT>
628 void interpolation_to_torus_mesh_fem(
const mesh_fem &mf_source,
const torus_mesh_fem &mf_target,
629 const VECTU &U, VECTV &VV, MAT &MM,
630 int version,
int extrapolation,
635 typedef typename gmm::linalg_traits<VECTU>::value_type T;
636 dim_type qqdim = dim_type(gmm::vect_size(U)/mf_source.nb_dof());
637 size_type qqdimt = qqdim * mf_source.get_qdim()/mf_target.get_qdim();
638 std::vector<T> V(mf_target.nb_basic_dof()*qqdimt);
639 mf_target.extend_vector(VV,V);
640 gmm::row_matrix<gmm::rsvector<scalar_type> >
641 M(mf_target.nb_basic_dof(), mf_source.nb_dof());
643 const mesh &msh(mf_source.linked_mesh());
644 getfem::mesh_trans_inv mti(msh, EPS);
645 size_type qdim_s = mf_source.get_qdim(), qdim_t = mf_target.get_qdim();
646 GMM_ASSERT1(qdim_s == qdim_t || qdim_t == 1,
647 "Attempt to interpolate a field of dimension "
648 << qdim_s <<
" on a mesh_fem whose Qdim is " << qdim_t);
651 for (dal::bv_visitor cv(mf_target.convex_index()); !cv.finished();++cv) {
652 pfem pf_t = mf_target.fem_of_element(cv);
654 GMM_ASSERT1(pf_t->target_dim() == 1 ||
655 (mf_target.get_qdim() == mf_target.linked_mesh().dim()),
656 "Target fem not convenient for interpolation");
660 size_type nbpts = mf_target.nb_basic_dof() / qdim_t;
663 base_node p(msh.dim());
664 for (
size_type k=0; k < msh.dim(); ++k) p[k] = mf_target.point_of_basic_dof(i * qdim_t)[k];
667 interpolation(mf_source, mti, U, V, M, version, extrapolation);
670 for (dal::bv_visitor_c dof(mf_target.basic_dof_on_region(rg_target)); !dof.finished(); ++dof)
671 if (dof % qdim_t == 0)
673 base_node p(msh.dim());
674 for (
size_type k=0; k < msh.dim(); ++k) p[k] = mf_target.point_of_basic_dof(dof)[k];
675 mti.add_point_with_id(p, dof/qdim_t);
677 interpolation(mf_source, mti, U, V, M, version, extrapolation, 0, rg_source);
681 mf_target.reduce_vector(V, VV);
683 if (mf_target.is_reduced())
684 gmm::mult(mf_target.reduction_matrix(), M, MM);
692 template<
typename VECTU,
typename VECTV>
694 const VECTU &U, VECTV &V,
int extrapolation,
698 GMM_ASSERT1((gmm::vect_size(U) % mf_source.
nb_dof()) == 0
699 && (gmm::vect_size(V) % mf_target.
nb_dof()) == 0
700 && gmm::vect_size(V) != 0,
"Dimensions mismatch");
704 interpolation_same_mesh(mf_source, mf_target, U, V, M, 0);
707 auto partitioning_allowed = rg_source.is_partitioning_allowed();
710 auto &V_thrd = V_distributed.thrd_cast();
711 gmm::resize(V_thrd, V.size());
713 mf_source, mf_target, U, V_thrd, M, 0, extrapolation, EPS,
714 rg_source, rg_target);
716 for (
size_type thread=0; thread != V_distributed.num_threads(); ++thread){
717 auto &V_thrd2 = V_distributed(thread);
718 for (
size_type i = 0; i < V_thrd2.size(); ++i) {
719 if (gmm::abs(V_thrd2[i]) > EPS) V[i] = V_thrd2[i];
726 template<
typename MAT>
728 MAT &M,
int extrapolation,
double EPS,
730 GMM_ASSERT1(mf_source.
nb_dof() == gmm::mat_ncols(M)
731 && (gmm::mat_nrows(M) % mf_target.
nb_dof()) == 0
732 && gmm::mat_nrows(M) != 0,
"Dimensions mismatch");
733 std::vector<scalar_type> U, V;
737 interpolation_same_mesh(mf_source, mf_target, U, V, M, 1);
739 interpolation(mf_source, mf_target, U, V, M, 1, extrapolation, EPS,
740 rg_source, rg_target);
751 template <
typename VECT>
753 const VECT &nodal_data, VECT &int_pt_data,
754 bool use_im_data_filter =
true) {
757 dim_type qdim = mf_source.
get_qdim();
760 size_type nodal_data_size = gmm::vect_size(nodal_data);
761 dim_type data_qdim = nodal_data_size / nb_dof;
763 GMM_ASSERT1(data_qdim * mf_source.
nb_dof() == nodal_data_size,
764 "Incompatible size of mesh fem " << mf_source.
nb_dof() * data_qdim <<
765 " with the data " << nodal_data_size);
768 "Incompatible size of qdim for mesh_fem " << qdim
771 "mf_source and im_data do not share the same mesh.");
773 GMM_ASSERT1(nb_dof * data_qdim == nodal_data_size,
774 "Provided nodal data size is " << nodal_data_size
775 <<
" but expecting vector size of " << nb_dof);
779 GMM_ASSERT1(size_im_data == gmm::vect_size(int_pt_data),
780 "Provided im data size is " << gmm::vect_size(int_pt_data)
781 <<
" but expecting vector size of " << size_im_data);
783 VECT extended_nodal_data_((nb_dof != nb_basic_dof) ? nb_basic_dof * data_qdim : 0);
784 if (nb_dof != nb_basic_dof)
785 mf_source.extend_vector(nodal_data, extended_nodal_data_);
786 const VECT &extended_nodal_data = (nb_dof == nb_basic_dof) ? nodal_data : extended_nodal_data_;
788 dal::bit_vector im_data_convex_index(im_target.
convex_index(use_im_data_filter));
792 bgeot::base_tensor tensor_int_point(im_target.tensor_size());
794 for (dal::bv_visitor cv(im_data_convex_index); !cv.finished(); ++cv) {
798 if (pf_source == NULL)
801 mesh_fem::ind_dof_ct::const_iterator it_dof;
803 size_type nb_nodal_pt = cv_nb_dof / qdim;
804 coeff.resize(cv_nb_dof);
807 const getfem::papprox_integration pim(im_target.approx_int_method_of_element(cv));
808 if (pf_source->need_G())
809 bgeot::vectors_to_base_matrix(G, *(pim->pintegration_points()));
811 pfem_precomp pfp = fppool(pf_source, pim->pintegration_points());
820 for (
size_type i = 0; i < nb_int_pts; ++i, ++int_pt_id) {
822 ctx.
pf()->interpolation(ctx, coeff, tensor_int_point.as_vector(), qdim * data_qdim);
823 im_target.
set_tensor(int_pt_data, int_pt_id, tensor_int_point);
834 size_type i0 = pim->ind_first_point_on_face(f);
835 for (
size_type i = 0; i < nb_int_pts; ++i, ++int_pt_id) {
837 ctx.
pf()->interpolation(ctx, coeff, tensor_int_point.as_vector(), qdim * data_qdim);
838 im_target.
set_tensor(int_pt_data, int_pt_id, tensor_int_point);