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) : pai->nb_points();
368 size_type start_pt = i.is_face() ? pai->ind_first_point_on_face(f) : 0;
369 elt_projection_data &e = elements[cv];
371 dal::bit_vector new_dofs;
373 pgp->transform(mim_target.
linked_mesh().points_of_convex(cv),
375 gausspt_projection_data &gppd = e.gausspt[start_pt + k];
376 gppd.iflags = find_a_projected_point(gpt, gppd.ptref, gppd.cv, gppd.f) ? 1 : 0;
380 mf_source.
linked_mesh().points_of_convex(gppd.cv, G);
382 normal_on_convex_face(pgt_source, G, gppd.f, gppd.ptref, gppd.normal);
384 normal_on_convex(pgt_source, G, gppd.ptref, gppd.normal);
386 base_node ppt = pgt_source->transform(gppd.ptref, G);
387 gppd.gap = gmm::vect_sp(gpt-ppt, gppd.normal);
390 if (gppd.iflags && (last_cv != gppd.cv || last_f != gppd.f)) {
393 for (
size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
395 if (!(blocked_dofs[dof]))
401 for (
size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
403 if (!(blocked_dofs[dof]))
413 dal::bit_vector old_dofs;
416 ind_dof[dof] = cnt++;
418 for (dal::bv_visitor dof(new_dofs); !dof.finished(); ++dof)
419 if (!(old_dofs[dof])) {
420 ind_dof[dof] = cnt++;
421 e.inddof.push_back(dof);
425 e.nb_dof = e.inddof.size();
426 max_dof = std::max(max_dof, e.nb_dof);
428 gausspt_projection_data &gppd = e.gausspt[start_pt + k];
432 for (
size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
434 gppd.local_dof[loc_dof] = new_dofs.is_in(dof) ? ind_dof[dof]
441 bgeot::convex_ind_ct ind_pts_fc = pf->structure(gppd.cv)->ind_points_of_face(gppd.f);
442 unsigned rdim =
target_dim() / pf->target_dim();
444 for (
size_type loc_dof = 0; loc_dof < nbdof; ++loc_dof) {
446 size_type loc_dof2 = ind_pts_fc[loc_dof];
447 gppd.local_dof[loc_dof2] = new_dofs.is_in(dof) ? ind_dof[dof]
451 for (
size_type ii = 0; ii < nbdof/rdim; ++ii)
452 for (
size_type jj = 0; jj < rdim; ++jj) {
455 size_type loc_dof2 = ind_pts_fc[ii]*rdim + jj;
456 gppd.local_dof[loc_dof2] = new_dofs.is_in(dof) ? ind_dof[dof]
468 base_node P(
dim()); gmm::fill(P,1./20);
469 std::vector<base_node> node_tab_(max_dof, P);
470 pspt_override = bgeot::store_point_tab(node_tab_);
472 dof_types_.resize(max_dof);
473 std::fill(dof_types_.begin(), dof_types_.end(),
479 std::fill(ind_dof.begin(), ind_dof.end(),
size_type(-1));
486 "Wrong convex number: " << cv);
487 std::map<size_type,elt_projection_data>::const_iterator eit;
488 eit = elements.find(cv);
489 return (eit != elements.end()) ? eit->second.nb_dof : 0;
494 std::map<size_type,elt_projection_data>::const_iterator eit;
495 eit = elements.find(cv);
496 GMM_ASSERT1(eit != elements.end(),
"Wrong convex number: " << cv);
497 return eit->second.inddof[i];
506 "Wrong convex number: " << cv);
513 { GMM_ASSERT1(
false,
"No base values, real only element."); }
516 { GMM_ASSERT1(
false,
"No grad values, real only element."); }
519 { GMM_ASSERT1(
false,
"No hess values, real only element."); }
521 inline void projected_fem::actualize_fictx(
pfem pf,
size_type cv,
522 const base_node &ptr)
const {
523 if (fictx_cv != cv) {
526 (mf_source.
linked_mesh().trans_of_convex(cv), pf, base_node(), G, cv);
533 base_tensor &t,
bool)
const {
534 std::map<size_type,elt_projection_data>::iterator eit;
536 if (eit == elements.end()) {
540 std::fill(t.begin(), t.end(), scalar_type(0));
544 elt_projection_data &e = eit->second;
549 std::fill(t.begin(), t.end(), scalar_type(0));
550 if (e.nb_dof == 0)
return;
552 std::map<size_type,gausspt_projection_data>::iterator git;
553 git = e.gausspt.find(c.ii());
555 (c.pgp()->get_ppoint_tab()
556 == e.pim->approx_method()->pintegration_points()) &&
557 git != e.gausspt.end()) {
558 gausspt_projection_data &gppd = git->second;
559 if (gppd.iflags & 1) {
560 if (gppd.iflags & 2) {
566 actualize_fictx(pf, cv, gppd.ptref);
567 pf->real_base_value(fictx, taux);
568 unsigned rdim =
target_dim() / pf->target_dim();
569 std::map<size_type,size_type>::const_iterator ii;
571 for (
size_type i = 0; i < pf->nb_dof(cv); ++i) {
572 ii = gppd.local_dof.find(i);
573 if (ii != gppd.local_dof.end() && ii->second !=
size_type(-1))
575 t(ii->second,j) = taux(i,j);
578 for (
size_type i = 0; i < pf->nb_dof(cv); ++i)
580 ii = gppd.local_dof.find(i*rdim+j);
581 if (ii != gppd.local_dof.end() && ii->second !=
size_type(-1))
582 t(ii->second,j) = taux(i,0);
594 if (find_a_projected_point(c.
xreal(), ptref, cv, f)) {
596 actualize_fictx(pf, cv, ptref);
597 pf->real_base_value(fictx, taux);
600 ind_dof.at(e.inddof[i]) = i;
602 unsigned rdim =
target_dim() / pf->target_dim();
604 for (
size_type i = 0; i < pf->nb_dof(cv); ++i) {
612 for (
size_type i = 0; i < pf->nb_dof(cv); ++i)
627 base_tensor &t,
bool)
const {
628 std::map<size_type,elt_projection_data>::iterator eit;
630 if (eit == elements.end()) {
635 std::fill(t.begin(), t.end(), scalar_type(0));
639 elt_projection_data &e = eit->second;
646 std::fill(t.begin(), t.end(), scalar_type(0));
647 if (e.nb_dof == 0)
return;
649 std::map<size_type,gausspt_projection_data>::iterator git;
650 git = e.gausspt.find(c.ii());
652 (c.pgp()->get_ppoint_tab()
653 == e.pim->approx_method()->pintegration_points()) &&
654 git != e.gausspt.end()) {
655 gausspt_projection_data &gppd = git->second;
656 if (gppd.iflags & 1) {
657 if (gppd.iflags & 4) {
663 actualize_fictx(pf, cv, gppd.ptref);
664 pf->real_grad_base_value(fictx, taux);
666 unsigned rdim =
target_dim() / pf->target_dim();
667 std::map<size_type,size_type>::const_iterator ii;
669 for (
size_type i = 0; i < pf->nb_dof(cv); ++i) {
670 ii = gppd.local_dof.find(i);
671 if (ii != gppd.local_dof.end() && ii->second !=
size_type(-1))
674 t(ii->second, j, k) = taux(i, j, k);
677 for (
size_type i = 0; i < pf->nb_dof(cv); ++i)
679 ii = gppd.local_dof.find(i*rdim+j);
680 if (ii != gppd.local_dof.end() && ii->second !=
size_type(-1))
682 t(ii->second, j, k) = taux(i, 0, k);
693 if (find_a_projected_point(c.
xreal(), ptref, cv, f)) {
695 actualize_fictx(pf, cv, ptref);
696 pf->real_grad_base_value(fictx, taux);
698 ind_dof.at(e.inddof[i]) = i;
700 unsigned rdim =
target_dim() / pf->target_dim();
702 for (
size_type i = 0; i < pf->nb_dof(cv); ++i) {
707 t(ii,j,k) = taux(i,j,k);
710 for (
size_type i = 0; i < pf->nb_dof(cv); ++i)
715 t(ij,j,k) = taux(i,0,k);
726 { GMM_ASSERT1(
false,
"Sorry, to be done."); }
729 base_node &normal, scalar_type &gap)
const {
730 std::map<size_type,elt_projection_data>::iterator eit;
733 if (eit != elements.end()) {
734 elt_projection_data &e = eit->second;
736 normal = base_node(c.N());
740 std::map<size_type,gausspt_projection_data>::iterator git;
741 git = e.gausspt.find(c.ii());
743 (c.pgp()->get_ppoint_tab()
744 == e.pim->approx_method()->pintegration_points()) &&
745 git != e.gausspt.end()) {
746 gausspt_projection_data &gppd = git->second;
747 if (gppd.iflags & 1) {
748 normal = gppd.normal;
752 normal = base_node(c.N());
760 projection_data(c.
xreal(), normal, gap);
763 void projected_fem::projection_data(
const base_node& pt,
764 base_node &normal, scalar_type &gap)
const {
767 if (find_a_projected_point(pt, ptref, cv, f)) {
771 normal_on_convex_face(pgt, G, f, ptref, normal);
773 normal_on_convex(pgt, G, ptref, normal);
774 base_node ppt = pgt->transform(ptref, G);
775 gap = gmm::vect_sp(pt-ppt, normal);
778 normal = base_node(pt.size());
786 std::map<size_type,elt_projection_data>::const_iterator eit;
787 for (eit = elements.begin(); eit != elements.end(); ++eit) {
788 std::map<size_type,gausspt_projection_data>::const_iterator git;
789 for (git = eit->second.gausspt.begin(); git != eit->second.gausspt.end(); ++git) {
790 if (git->second.iflags)
791 bv.add(git->second.cv);
798 scalar_type &meang)
const {
800 std::map<size_type,elt_projection_data>::const_iterator eit;
801 for (eit = elements.begin(); eit != elements.end(); ++eit) {
802 std::map<size_type,gausspt_projection_data>::const_iterator git;
803 for (git = eit->second.gausspt.begin(); git != eit->second.gausspt.end(); ++git) {
804 if (git->second.iflags)
809 ming = 100000; maxg = 0; meang = 0;
812 !cv.finished(); ++cv) {
813 ming = std::min(ming, v[cv]);
814 maxg = std::max(maxg, v[cv]);
816 if (v[cv] > 0) ++cntg;
818 meang /= scalar_type(cntg);
821 size_type projected_fem::memsize()
const {
823 sz += blocked_dofs.memsize();
825 sz += elements.size() *
sizeof(elt_projection_data);
826 std::map<size_type,elt_projection_data>::const_iterator eit;
827 for (eit = elements.begin(); eit != elements.end(); ++eit) {
828 sz += eit->second.gausspt.size() *
sizeof(gausspt_projection_data);
829 sz += eit->second.inddof.capacity() *
sizeof(
size_type);
830 std::map<size_type,gausspt_projection_data>::const_iterator git;
831 for (git = eit->second.gausspt.begin(); git != eit->second.gausspt.end(); ++git) {
832 sz += git->second.local_dof.size() *
sizeof(
size_type);
838 projected_fem::projected_fem(
const mesh_fem &mf_source_,
839 const mesh_im &mim_target_,
842 dal::bit_vector blocked_dofs_,
bool store_val)
843 : mf_source(mf_source_), mim_target(mim_target_),
844 rg_source(mf_source.linked_mesh().region(rg_source_)),
845 rg_target(mim_target.linked_mesh().region(rg_target_)),
846 store_values(store_val), blocked_dofs(blocked_dofs_), mi2(2), mi3(3) {
847 this->add_dependency(mf_source);
848 this->add_dependency(mim_target);
849 is_pol = is_lag = is_standard_fem =
false; es_degree = 5;
850 is_equiv = real_element_defined =
true;
856 DAL_SIMPLE_KEY(special_projfem_key,
pfem);
860 dal::bit_vector blocked_dofs_,
bool store_val) {
861 pfem pf = std::make_shared<projected_fem>
862 (mf_source_, mim_target_, rg_source_, rg_target_,blocked_dofs_,store_val);
863 dal::pstatic_stored_object_key
864 pk = std::make_shared<special_projfem_key>(pf);