39 void projection_on_convex_face
42 base_node &proj_ref, base_node &proj) {
47 size_type nb_pts_cv = gmm::mat_ncols(G_cv);
48 size_type nb_pts_fc = pgt->structure()->nb_points_of_face(fc);
50 GMM_ASSERT1( N == pt.size(),
"Dimensions mismatch");
51 GMM_ASSERT1( nb_pts_cv == pgt->nb_points(),
"Dimensions mismatch");
53 bgeot::convex_ind_ct ind_pts_fc = pgt->structure()->ind_points_of_face(fc);
55 base_matrix G_fc(N, nb_pts_fc);
57 gmm::copy(gmm::mat_col(G_cv,ind_pts_fc[i]),gmm::mat_col(G_fc,i));
60 base_matrix base_ref_fc(P,P-1);
63 GMM_ASSERT1( dref_pts_fc.size() == P,
"Dimensions mismatch");
65 gmm::copy(dref_pts_fc[i+1] - dref_pts_fc[0], gmm::mat_col(base_ref_fc,i));
75 proj_ref = gmm::mean_value(pgt->convex_ref()->points_of_face(fc));
77 base_vector val(nb_pts_fc);
78 pgt->poly_vector_val(proj_ref, ind_pts_fc, val);
79 gmm::mult(G_fc, val, proj);
83 base_matrix grad_fc(nb_pts_fc, P);
84 base_matrix grad_fc1(nb_pts_fc, P-1);
85 base_matrix B(N,P-1), BB(N,P), CS(P-1,P-1);
87 scalar_type EPS = 10E-12;
89 while (res > EPS && --cnt) {
91 pgt->poly_vector_grad(proj_ref, ind_pts_fc, grad_fc);
92 gmm::mult(grad_fc, base_ref_fc, grad_fc1);
93 gmm::mult(G_fc, grad_fc1, K);
94 gmm::mult(gmm::transposed(K), K, CS);
97 gmm::mult(B, gmm::transposed(base_ref_fc), BB);
101 pgt->poly_vector_val(proj_ref, ind_pts_fc, val);
102 gmm::mult(G_fc, val, proj);
104 gmm::mult(gmm::transposed(BB), pt - proj, vres);
107 GMM_ASSERT1( res <= EPS,
108 "Iterative pojection on convex face did not converge");
109 pgt->project_into_reference_convex(proj_ref);
110 pgt->poly_vector_val(proj_ref, ind_pts_fc, val);
111 gmm::mult(G_fc, val, proj);
125 void normal_on_convex_face
127 const short_type fc,
const base_node &ref_pt, base_node &normal) {
132 size_type nb_pts_cv = gmm::mat_ncols(G_cv);
133 size_type nb_pts_fc = pgt->structure()->nb_points_of_face(fc);
135 GMM_ASSERT1( nb_pts_cv == pgt->nb_points(),
"Dimensions mismatch");
137 bgeot::convex_ind_ct ind_pts_fc = pgt->structure()->ind_points_of_face(fc);
139 base_matrix G_fc(N, nb_pts_fc);
141 gmm::copy(gmm::mat_col(G_cv,ind_pts_fc[i]),gmm::mat_col(G_fc,i));
144 base_matrix base_ref_fc(P,P-1);
147 GMM_ASSERT1( dref_pts_fc.size() == P,
"Dimensions mismatch");
149 gmm::copy(dref_pts_fc[i+1] - dref_pts_fc[0], gmm::mat_col(base_ref_fc,i));
154 base_matrix K(N,P-1);
156 base_matrix grad_fc(nb_pts_fc, P);
157 base_matrix grad_fc1(nb_pts_fc, P-1);
158 pgt->poly_vector_grad(ref_pt, ind_pts_fc, grad_fc);
159 gmm::mult(grad_fc, base_ref_fc, grad_fc1);
160 gmm::mult(G_fc, grad_fc1, K);
165 base_matrix grad_cv(nb_pts_cv, P);
166 pgt->poly_vector_grad(ref_pt, grad_cv);
167 gmm::mult(G_cv, grad_cv, KK);
170 base_matrix bases_product(P-1, P);
171 gmm::mult(gmm::transposed(K), KK, bases_product);
174 std::vector<size_type> ind(0);
176 if (j != i ) ind.push_back(j);
177 scalar_type det = gmm::lu_det(gmm::sub_matrix(bases_product,
178 gmm::sub_interval(0, P-1),
179 gmm::sub_index(ind) ) );
180 gmm::add(gmm::scaled(gmm::mat_col(KK, i), (i % 2) ? -det : +det ), normal);
184 gmm::scale(normal, 1/gmm::vect_norm2(normal));
187 base_node cv_center(N), fc_center(N);
189 gmm::add(gmm::mat_col(G_cv,i), cv_center);
191 gmm::add(gmm::mat_col(G_fc,i), fc_center);
192 gmm::scale(cv_center, scalar_type(1)/scalar_type(nb_pts_cv));
193 gmm::scale(fc_center, scalar_type(1)/scalar_type(nb_pts_fc));
194 if (gmm::vect_sp(normal, fc_center -cv_center) < 0)
195 gmm::scale(normal, scalar_type(-1));
210 void normal_on_convex
212 const base_node &ref_pt, base_node &normal) {
217 GMM_ASSERT1( N == 2 || N == 3,
"Normal on convexes calculation is supported "
218 "only for space dimension equal to 2 or 3.");
219 GMM_ASSERT1( P < N,
"Normal on convex is defined only in a space of"
220 "higher dimension.");
225 base_matrix grad_cv(nb_pts, P);
226 pgt->poly_vector_grad(ref_pt, grad_cv);
227 gmm::mult(G_cv, grad_cv, K);
231 if (P==1 && N == 2) {
235 else if (P==1 && N == 3) {
236 normal[0] = K(2,0)-K(1,0);
237 normal[1] = K(0,0)-K(2,0);
238 normal[2] = K(1,0)-K(0,0);
241 normal[0] = K(1,0)*K(2,1)-K(2,0)*K(1,1);
242 normal[1] = K(2,0)*K(0,1)-K(0,0)*K(2,1);
243 normal[2] = K(0,0)*K(1,1)-K(1,0)*K(0,1);
245 gmm::scale(normal, 1/gmm::vect_norm2(normal));
248 void projected_fem::build_kdtree(
void)
const {
251 dofs.setminus(blocked_dofs);
253 for (dal::bv_visitor dof(dofs); !dof.finished(); ++dof)
258 bool projected_fem::find_a_projected_point(
const base_node &pt, base_node &ptr_proj,
263 tree.nearest_neighbor(ipt, pt);
267 scalar_type dist_sel(1e10);
268 base_node proj_ref, proj_ref_sel, proj, proj_sel;
270 for (
size_type i=0; i < cvs.size(); ++i) {
273 if (rg_source.is_in(cv)) {
276 gic.
invert(pt, proj_ref, gt_invertible);
278 pgt->project_into_reference_convex(proj_ref);
279 proj = pgt->transform(proj_ref, mf_source.
linked_mesh().points_of_convex(cv));
281 if (dist < dist_sel) {
285 proj_ref_sel = proj_ref;
290 mesh_region::face_bitset faces = rg_source.faces_of_convex(cv);
291 if (faces.count() > 0) {
296 projection_on_convex_face(pgt, G, f, pt, proj_ref, proj);
298 if (dist < dist_sel) {
302 proj_ref_sel = proj_ref;
312 if (dist_sel < 0.05*elm_size) {
315 ptr_proj = proj_ref_sel;
328 "Dimensions mismatch between the source and the target meshes");
334 std::fill(ind_dof.begin(), ind_dof.end(),
size_type(-1));
337 rg_target.is_empty()) {
342 for (
mr_visitor i(rg_target); !i.finished(); ++i) {
347 if (dim_ == dim_type(-1)) {
349 if (i.is_face()) dim__ = dim_type(dim__ - 1);
350 GMM_ASSERT1(dim__ < N,
"The projection should take place in lower "
351 "dimensions than the mesh dimension. Otherwise "
352 "use the interpolated_fem object instead.");
355 GMM_ASSERT1(dim_ == dim__,
356 "Convexes/faces of different dimension in the target mesh");
359 GMM_ASSERT1(pim->type() == IM_APPROX,
360 "You have to use approximated integration to project a fem");
361 papprox_integration pai = pim->approx_method();
363 bgeot::pgeotrans_precomp pgp =
364 bgeot::geotrans_precomp(pgt, pai->pintegration_points(), 0);
367 size_type nb_pts = i.is_face() ? pai->nb_points_on_face(f)
368 : pai->nb_points_on_convex();
369 size_type start_pt = i.is_face() ? pai->ind_first_point_on_face(f) : 0;
370 elt_projection_data &e = elements[cv];
372 dal::bit_vector new_dofs;
374 pgp->transform(mim_target.
linked_mesh().points_of_convex(cv),
376 gausspt_projection_data &gppd = e.gausspt[start_pt + k];
377 gppd.iflags = find_a_projected_point(gpt, gppd.ptref, gppd.cv, gppd.f) ? 1 : 0;
381 mf_source.
linked_mesh().points_of_convex(gppd.cv, G);
383 normal_on_convex_face(pgt_source, G, gppd.f, gppd.ptref, gppd.normal);
385 normal_on_convex(pgt_source, G, gppd.ptref, gppd.normal);
387 base_node ppt = pgt_source->transform(gppd.ptref, G);
388 gppd.gap = gmm::vect_sp(gpt-ppt, gppd.normal);
391 if (gppd.iflags && (last_cv != gppd.cv || last_f != gppd.f)) {
394 for (
size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
396 if (!(blocked_dofs[dof]))
402 for (
size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
404 if (!(blocked_dofs[dof]))
414 dal::bit_vector old_dofs;
417 ind_dof[dof] = cnt++;
419 for (dal::bv_visitor dof(new_dofs); !dof.finished(); ++dof)
420 if (!(old_dofs[dof])) {
421 ind_dof[dof] = cnt++;
422 e.inddof.push_back(dof);
426 e.nb_dof = e.inddof.size();
427 max_dof = std::max(max_dof, e.nb_dof);
429 gausspt_projection_data &gppd = e.gausspt[start_pt + k];
433 for (
size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
435 gppd.local_dof[loc_dof] = new_dofs.is_in(dof) ? ind_dof[dof]
442 bgeot::convex_ind_ct ind_pts_fc = pf->structure(gppd.cv)->ind_points_of_face(gppd.f);
443 unsigned rdim =
target_dim() / pf->target_dim();
445 for (
size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
447 size_type loc_dof2 = ind_pts_fc[loc_dof];
448 gppd.local_dof[loc_dof2] = new_dofs.is_in(dof) ? ind_dof[dof]
452 for (
size_type ii = 0; ii < nbdof/rdim; ++ii)
453 for (
size_type jj = 0; jj < rdim; ++jj) {
456 size_type loc_dof2 = ind_pts_fc[ii]*rdim + jj;
457 gppd.local_dof[loc_dof2] = new_dofs.is_in(dof) ? ind_dof[dof]
469 base_node P(
dim()); gmm::fill(P,1./20);
470 std::vector<base_node> node_tab_(max_dof, P);
471 pspt_override = bgeot::store_point_tab(node_tab_);
473 dof_types_.resize(max_dof);
474 std::fill(dof_types_.begin(), dof_types_.end(),
480 std::fill(ind_dof.begin(), ind_dof.end(),
size_type(-1));
487 "Wrong convex number: " << cv);
488 std::map<size_type,elt_projection_data>::const_iterator eit;
489 eit = elements.find(cv);
490 return (eit != elements.end()) ? eit->second.nb_dof : 0;
495 std::map<size_type,elt_projection_data>::const_iterator eit;
496 eit = elements.find(cv);
497 GMM_ASSERT1(eit != elements.end(),
"Wrong convex number: " << cv);
498 return eit->second.inddof[i];
507 "Wrong convex number: " << cv);
514 { GMM_ASSERT1(
false,
"No base values, real only element."); }
517 { GMM_ASSERT1(
false,
"No grad values, real only element."); }
520 { GMM_ASSERT1(
false,
"No hess values, real only element."); }
522 inline void projected_fem::actualize_fictx(
pfem pf,
size_type cv,
523 const base_node &ptr)
const {
524 if (fictx_cv != cv) {
527 (mf_source.
linked_mesh().trans_of_convex(cv), pf, base_node(), G, cv);
534 base_tensor &t,
bool)
const {
535 std::map<size_type,elt_projection_data>::iterator eit;
537 if (eit == elements.end()) {
541 std::fill(t.begin(), t.end(), scalar_type(0));
545 elt_projection_data &e = eit->second;
550 std::fill(t.begin(), t.end(), scalar_type(0));
551 if (e.nb_dof == 0)
return;
553 std::map<size_type,gausspt_projection_data>::iterator git;
554 git = e.gausspt.find(c.ii());
556 (c.pgp()->get_ppoint_tab()
557 == e.pim->approx_method()->pintegration_points()) &&
558 git != e.gausspt.end()) {
559 gausspt_projection_data &gppd = git->second;
560 if (gppd.iflags & 1) {
561 if (gppd.iflags & 2) {
567 actualize_fictx(pf, cv, gppd.ptref);
568 pf->real_base_value(fictx, taux);
569 unsigned rdim =
target_dim() / pf->target_dim();
570 std::map<size_type,size_type>::const_iterator ii;
572 for (
size_type i = 0; i < pf->nb_dof(cv); ++i) {
573 ii = gppd.local_dof.find(i);
574 if (ii != gppd.local_dof.end() && ii->second !=
size_type(-1))
576 t(ii->second,j) = taux(i,j);
579 for (
size_type i = 0; i < pf->nb_dof(cv); ++i)
581 ii = gppd.local_dof.find(i*rdim+j);
582 if (ii != gppd.local_dof.end() && ii->second !=
size_type(-1))
583 t(ii->second,j) = taux(i,0);
595 if (find_a_projected_point(c.
xreal(), ptref, cv, f)) {
597 actualize_fictx(pf, cv, ptref);
598 pf->real_base_value(fictx, taux);
601 ind_dof.at(e.inddof[i]) = i;
603 unsigned rdim =
target_dim() / pf->target_dim();
605 for (
size_type i = 0; i < pf->nb_dof(cv); ++i) {
613 for (
size_type i = 0; i < pf->nb_dof(cv); ++i)
628 base_tensor &t,
bool)
const {
629 std::map<size_type,elt_projection_data>::iterator eit;
631 if (eit == elements.end()) {
636 std::fill(t.begin(), t.end(), scalar_type(0));
640 elt_projection_data &e = eit->second;
647 std::fill(t.begin(), t.end(), scalar_type(0));
648 if (e.nb_dof == 0)
return;
650 std::map<size_type,gausspt_projection_data>::iterator git;
651 git = e.gausspt.find(c.ii());
653 (c.pgp()->get_ppoint_tab()
654 == e.pim->approx_method()->pintegration_points()) &&
655 git != e.gausspt.end()) {
656 gausspt_projection_data &gppd = git->second;
657 if (gppd.iflags & 1) {
658 if (gppd.iflags & 4) {
664 actualize_fictx(pf, cv, gppd.ptref);
665 pf->real_grad_base_value(fictx, taux);
667 unsigned rdim =
target_dim() / pf->target_dim();
668 std::map<size_type,size_type>::const_iterator ii;
670 for (
size_type i = 0; i < pf->nb_dof(cv); ++i) {
671 ii = gppd.local_dof.find(i);
672 if (ii != gppd.local_dof.end() && ii->second !=
size_type(-1))
675 t(ii->second, j, k) = taux(i, j, k);
678 for (
size_type i = 0; i < pf->nb_dof(cv); ++i)
680 ii = gppd.local_dof.find(i*rdim+j);
681 if (ii != gppd.local_dof.end() && ii->second !=
size_type(-1))
683 t(ii->second, j, k) = taux(i, 0, k);
694 if (find_a_projected_point(c.
xreal(), ptref, cv, f)) {
696 actualize_fictx(pf, cv, ptref);
697 pf->real_grad_base_value(fictx, taux);
699 ind_dof.at(e.inddof[i]) = i;
701 unsigned rdim =
target_dim() / pf->target_dim();
703 for (
size_type i = 0; i < pf->nb_dof(cv); ++i) {
708 t(ii,j,k) = taux(i,j,k);
711 for (
size_type i = 0; i < pf->nb_dof(cv); ++i)
716 t(ij,j,k) = taux(i,0,k);
727 { GMM_ASSERT1(
false,
"Sorry, to be done."); }
730 base_node &normal, scalar_type &gap)
const {
731 std::map<size_type,elt_projection_data>::iterator eit;
734 if (eit != elements.end()) {
735 elt_projection_data &e = eit->second;
737 normal = base_node(c.N());
741 std::map<size_type,gausspt_projection_data>::iterator git;
742 git = e.gausspt.find(c.ii());
744 (c.pgp()->get_ppoint_tab()
745 == e.pim->approx_method()->pintegration_points()) &&
746 git != e.gausspt.end()) {
747 gausspt_projection_data &gppd = git->second;
748 if (gppd.iflags & 1) {
749 normal = gppd.normal;
753 normal = base_node(c.N());
761 projection_data(c.
xreal(), normal, gap);
764 void projected_fem::projection_data(
const base_node& pt,
765 base_node &normal, scalar_type &gap)
const {
768 if (find_a_projected_point(pt, ptref, cv, f)) {
772 normal_on_convex_face(pgt, G, f, ptref, normal);
774 normal_on_convex(pgt, G, ptref, normal);
775 base_node ppt = pgt->transform(ptref, G);
776 gap = gmm::vect_sp(pt-ppt, normal);
779 normal = base_node(pt.size());
787 std::map<size_type,elt_projection_data>::const_iterator eit;
788 for (eit = elements.begin(); eit != elements.end(); ++eit) {
789 std::map<size_type,gausspt_projection_data>::const_iterator git;
790 for (git = eit->second.gausspt.begin(); git != eit->second.gausspt.end(); ++git) {
791 if (git->second.iflags)
792 bv.add(git->second.cv);
801 for (
mr_visitor v(rg_target); !v.finished(); ++v) {
803 papprox_integration pai = pim->approx_method();
804 size_type start_pt = v.is_face() ? pai->ind_first_point_on_face(v.f()) : 0;
805 size_type nb_pts = v.is_face() ? pai->nb_points_on_face(v.f())
806 : pai->nb_points_on_convex();
807 bool isProjectedOn =
false;
808 for (
size_type ip = 0; ip != nb_pts; ++ip) {
809 auto &proj_data = elements.at(v.cv()).gausspt[start_pt + ip];
810 if (proj_data.iflags) {
811 isProjectedOn =
true;
815 if (isProjectedOn) projected_target.add(v.cv(), v.f());
817 return projected_target;
821 scalar_type &meang)
const {
823 std::map<size_type,elt_projection_data>::const_iterator eit;
824 for (eit = elements.begin(); eit != elements.end(); ++eit) {
825 std::map<size_type,gausspt_projection_data>::const_iterator git;
826 for (git = eit->second.gausspt.begin(); git != eit->second.gausspt.end(); ++git) {
827 if (git->second.iflags)
832 ming = 100000; maxg = 0; meang = 0;
835 !cv.finished(); ++cv) {
836 ming = std::min(ming, v[cv]);
837 maxg = std::max(maxg, v[cv]);
839 if (v[cv] > 0) ++cntg;
841 meang /= scalar_type(cntg);
844 size_type projected_fem::memsize()
const {
846 sz += blocked_dofs.memsize();
848 sz += elements.size() *
sizeof(elt_projection_data);
849 std::map<size_type,elt_projection_data>::const_iterator eit;
850 for (eit = elements.begin(); eit != elements.end(); ++eit) {
851 sz += eit->second.gausspt.size() *
sizeof(gausspt_projection_data);
852 sz += eit->second.inddof.capacity() *
sizeof(
size_type);
853 std::map<size_type,gausspt_projection_data>::const_iterator git;
854 for (git = eit->second.gausspt.begin(); git != eit->second.gausspt.end(); ++git) {
855 sz += git->second.local_dof.size() *
sizeof(
size_type);
861 projected_fem::projected_fem(
const mesh_fem &mf_source_,
862 const mesh_im &mim_target_,
865 dal::bit_vector blocked_dofs_,
bool store_val)
866 : mf_source(mf_source_), mim_target(mim_target_),
867 rg_source(mf_source.linked_mesh().region(rg_source_)),
868 rg_target(mim_target.linked_mesh().region(rg_target_)),
869 store_values(store_val), blocked_dofs(blocked_dofs_), mi2(2), mi3(3) {
870 this->add_dependency(mf_source);
871 this->add_dependency(mim_target);
872 is_pol = is_lag = is_standard_fem =
false; es_degree = 5;
873 is_equiv = real_element_defined =
true;
879 DAL_SIMPLE_KEY(special_projfem_key,
pfem);
883 dal::bit_vector blocked_dofs_,
bool store_val) {
884 pfem pf = std::make_shared<projected_fem>
885 (mf_source_, mim_target_, rg_source_, rg_target_,blocked_dofs_,store_val);
886 dal::pstatic_stored_object_key
887 pk = std::make_shared<special_projfem_key>(pf);