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>
239 const VECTU &U, VECTV &V,
int extrapolation = 0,
256 template<
typename MAT>
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,
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;
288 "Attempt to interpolate a field of dimension " 289 << qdim <<
" on a mesh_fem whose Qdim is " <<
294 std::vector<size_type> dof_t_passes(mf_target.
nb_basic_dof());
297 gmm::row_matrix<gmm::rsvector<scalar_type> >
300 if (version == 0) mf_source.extend_vector(UU, U);
303 for (dal::bv_visitor cv(mf_source.
convex_index()); !cv.finished(); ++cv) {
311 mesh_fem::ind_dof_ct::const_iterator itdof;
314 bool discontinuous_source =
false;
315 for (
size_type dof=0; dof < nbd_s; ++dof)
317 discontinuous_source =
true;
324 coeff[qq].resize(cvnbdof);
326 for (
size_type k = 0; k < cvnbdof; ++k, ++itdof) {
327 coeff[qq][k] = U[(*itdof)*qqdim+qq];
332 bgeot::vectors_to_base_matrix
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));
342 const mesh_fem::ind_dof_ct &idct
344 dof_source.assign(idct.begin(), idct.end());
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];
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);
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);
389 gmm::row_matrix<gmm::rsvector<scalar_type> >
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;
420 dim_type qdim_s = mf_source.
get_qdim();
421 dim_type qqdim = dim_type(gmm::vect_size(UU)/mf_source.
nb_dof());
424 gmm::row_matrix<gmm::rsvector<scalar_type> >
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;
447 bgeot::vectors_to_base_matrix(G, msh.points_of_convex(cv));
454 mesh_fem::ind_dof_ct::const_iterator itdof;
456 coeff[qq].resize(cvnbdof);
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
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];
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);
529 template<
typename VECTU,
typename VECTV>
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>
549 const VECTU &U, VECTV &VV, MAT &MM,
550 int version,
int extrapolation,
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());
567 mf_target.extend_vector(VV,V);
568 gmm::row_matrix<gmm::rsvector<scalar_type> >
572 getfem::mesh_trans_inv mti(msh, EPS);
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) {
581 GMM_ASSERT1(pf_t->target_dim() == 1 && pf_t->is_lagrange(),
582 "Target fem not convenient for interpolation");
589 if (is_target_torus){
599 !dof.finished(); ++dof)
600 if (dof % qdim_t == 0){
601 if (is_target_torus){
604 mti.add_point_with_id(p, dof/qdim_t);
610 interpolation(mf_source, mti, U, V, M, version, extrapolation, 0,rg_source);
613 mf_target.reduce_vector(V, VV);
627 template<
typename VECTU,
typename VECTV,
typename MAT>
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());
639 mf_target.extend_vector(VV,V);
640 gmm::row_matrix<gmm::rsvector<scalar_type> >
644 getfem::mesh_trans_inv mti(msh, EPS);
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) {
654 GMM_ASSERT1(pf_t->target_dim() == 1 ||
656 "Target fem not convenient for interpolation");
663 base_node p(msh.dim());
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());
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);
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);
706 interpolation(mf_source, mf_target, U, V, M, 0, extrapolation, EPS,
707 rg_source, rg_target);
710 template<
typename MAT>
712 MAT &M,
int extrapolation,
double EPS,
714 GMM_ASSERT1(mf_source.
nb_dof() == gmm::mat_ncols(M)
715 && (gmm::mat_nrows(M) % mf_target.
nb_dof()) == 0
716 && gmm::mat_nrows(M) != 0,
"Dimensions mismatch");
717 std::vector<scalar_type> U, V;
721 interpolation_same_mesh(mf_source, mf_target, U, V, M, 1);
723 interpolation(mf_source, mf_target, U, V, M, 1, extrapolation, EPS,
724 rg_source, rg_target);
735 template <
typename VECT>
737 const VECT &nodal_data, VECT &int_pt_data,
738 bool use_im_data_filter =
true) {
741 dim_type qdim = mf_source.
get_qdim();
744 size_type nodal_data_size = gmm::vect_size(nodal_data);
745 dim_type data_qdim = nodal_data_size / nb_dof;
747 GMM_ASSERT1(data_qdim * mf_source.
nb_dof() == nodal_data_size,
748 "Incompatible size of mesh fem " << mf_source.
nb_dof() * data_qdim <<
749 " with the data " << nodal_data_size);
752 "Incompatible size of qdim for mesh_fem " << qdim
755 "mf_source and im_data do not share the same mesh.");
757 GMM_ASSERT1(nb_dof * data_qdim == nodal_data_size,
758 "Provided nodal data size is " << nodal_data_size
759 <<
" but expecting vector size of " << nb_dof);
763 GMM_ASSERT1(size_im_data == gmm::vect_size(int_pt_data),
764 "Provided im data size is " << gmm::vect_size(int_pt_data)
765 <<
" but expecting vector size of " << size_im_data);
767 VECT extended_nodal_data_((nb_dof != nb_basic_dof) ? nb_basic_dof * data_qdim : 0);
768 if (nb_dof != nb_basic_dof)
769 mf_source.extend_vector(nodal_data, extended_nodal_data_);
770 const VECT &extended_nodal_data = (nb_dof == nb_basic_dof) ? nodal_data : extended_nodal_data_;
772 dal::bit_vector im_data_convex_index(im_target.
convex_index(use_im_data_filter));
776 bgeot::base_tensor tensor_int_point(im_target.tensor_size());
778 for (dal::bv_visitor cv(im_data_convex_index); !cv.finished(); ++cv) {
782 if (pf_source == NULL)
785 mesh_fem::ind_dof_ct::const_iterator it_dof;
787 size_type nb_nodal_pt = cv_nb_dof / qdim;
788 coeff.resize(cv_nb_dof);
791 const getfem::papprox_integration pim(im_target.approx_int_method_of_element(cv));
792 if (pf_source->need_G())
793 bgeot::vectors_to_base_matrix(G, *(pim->pintegration_points()));
795 pfem_precomp pfp = fppool(pf_source, pim->pintegration_points());
804 for (
size_type i = 0; i < nb_int_pts; ++i, ++int_pt_id) {
806 ctx.
pf()->interpolation(ctx, coeff, tensor_int_point.as_vector(), qdim * data_qdim);
807 im_target.
set_tensor(int_pt_data, int_pt_id, tensor_int_point);
818 size_type i0 = pim->ind_first_point_on_face(f);
819 for (
size_type i = 0; i < nb_int_pts; ++i, ++int_pt_id) {
821 ctx.
pf()->interpolation(ctx, coeff, tensor_int_point.as_vector(), qdim * data_qdim);
822 im_target.
set_tensor(int_pt_data, int_pt_id, tensor_int_point);
virtual size_type nb_basic_dof_of_element(size_type cv) const
Return the number of degrees of freedom attached to a given convex.
virtual size_type nb_dof() const
Return the total number of degrees of freedom.
structure used to hold a set of convexes and/or convex faces.
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.
static mesh_region all_convexes()
provide a default value for the mesh_region parameters of assembly procedures etc.
Provides indexing of integration points for mesh_im.
void interpolation_function(mesh_fem &mf_target, const VECT &VV, F &f, mesh_region rg=mesh_region::all_convexes())
interpolation of a function f on mf_target.
short_type nb_faces_of_element(size_type cv) const
Number of (active) faces in element cv.
void set_tensor(VECT &V1, size_type cv, size_type i, const TENSOR &T, bool use_filter=true) const
set a tensor of an integration point from a raw vector data, described by the tensor size...
Define the getfem::mesh_fem class.
Provides mesh and mesh fem of torus.
void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target, const VECTU &U, VECTV &V, int extrapolation=0, double EPS=1E-10, mesh_region rg_source=mesh_region::all_convexes(), mesh_region rg_target=mesh_region::all_convexes())
interpolation/extrapolation of (mf_source, U) on mf_target.
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...
Describe a mesh (collection of convexes (elements) and points).
size_type add_point(base_node p)
Add point p to the list of points.
handles the geometric inversion for a given (supposedly quite large) set of points ...
const REDUCTION_MATRIX & reduction_matrix() const
Return the reduction matrix applied to the dofs.
const mesh & linked_mesh() const
linked mesh
const EXTENSION_MATRIX & extension_matrix() const
Return the extension matrix corresponding to reduction applied (RE=I).
size_type nb_index(bool use_filter=false) const
Total numbers of index (integration points)
size_t size_type
used as the common size type in the library
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.
Copy an original 2D mesh to become a torus mesh with radial dimension.
virtual dim_type get_qdim() const
Return the Q dimension.
structure passed as the argument of fem interpolation functions.
virtual base_node point_of_basic_dof(size_type cv, size_type i) const
Return the geometrical location of a degree of freedom.
a balanced tree stored in a dal::dynamic_array
bool is_reduced() const
Return true if a reduction matrix is applied to the dofs.
GEneric Tool for Finite Element Methods.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
bool dof_linkable(pdof_description)
Says if the dof is linkable.
Describe a finite element method linked to a mesh.
gmm::uint16_type short_type
used as the common short type integer in the library
void set_xref(const base_node &P)
change the current point (coordinates given in the reference convex)
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
const pfem pf() const
get the current FEM descriptor
const dal::bit_vector & convex_index() const
Get the set of convexes where a finite element has been assigned.
void interpolation_to_im_data(const mesh_fem &mf_source, const im_data &im_target, const VECT &nodal_data, VECT &int_pt_data, bool use_im_data_filter=true)
Interpolate mesh_fem data to im_data.
dal::bit_vector convex_index(bool use_filter=false) const
List of convexes.
Mesh fem object that adapts.
im_data provides indexing to the integration points of a mesh im object.
virtual ind_dof_ct ind_basic_dof_of_element(size_type cv) const
Give an array of the dof numbers a of convex.
void set_ii(size_type ii__)
change the current point (assuming a geotrans_precomp_ is used)
size_type nb_tensor_elem() const
sum of tensor elements, M(3,3) will have 3*3=9 elements
size_type index_of_first_point(size_type cv, short_type f=short_type(-1), bool use_filter=false) const
Returns the index of the first integration point with no filtering.
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
size_type nb_points_of_element(size_type cv, bool use_filter=false) const
Total number of points in element cv.