37 #ifndef GETFEM_MESHER_H__
38 #define GETFEM_MESHER_H__
53 virtual scalar_type operator()(
const base_node &P)
const = 0;
54 virtual ~mesher_virtual_function() {}
57 class mvf_constant :
public mesher_virtual_function {
60 mvf_constant(scalar_type c_) : c(c_) {}
61 scalar_type operator()(
const base_node &)
const {
return c; }
70 class mesher_signed_distance :
public mesher_virtual_function {
74 mesher_signed_distance() : id(
size_type(-1)) {}
75 virtual ~mesher_signed_distance() {}
76 virtual bool bounding_box(base_node &bmin, base_node &bmax)
const = 0;
77 virtual scalar_type operator()(
const base_node &P,
78 dal::bit_vector &bv)
const = 0;
79 virtual scalar_type grad(
const base_node &P,
80 base_small_vector &G)
const = 0;
81 virtual void hess(
const base_node &P, base_matrix &H)
const = 0;
82 virtual void register_constraints(std::vector<
const
83 mesher_signed_distance*>& list)
const=0;
84 virtual scalar_type operator()(
const base_node &P)
const = 0;
87 typedef std::shared_ptr<const mesher_signed_distance> pmesher_signed_distance;
89 class mesher_half_space :
public mesher_signed_distance {
90 base_node x0; base_small_vector n; scalar_type xon;
92 mesher_half_space() =
default;
93 mesher_half_space(
const base_node &x0_,
const base_small_vector &n_)
96 bool bounding_box(base_node &, base_node &)
const
98 virtual scalar_type operator()(
const base_node &P)
const
100 virtual scalar_type operator()(
const base_node &P,
101 dal::bit_vector &bv)
const {
103 bv[id] = (gmm::abs(d) < SEPS);
106 virtual void register_constraints(std::vector<
const
107 mesher_signed_distance*>& list)
const {
108 id = list.size(); list.push_back(
this);
110 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
111 G = n; G *= scalar_type(-1);
114 void hess(
const base_node &P, base_matrix &H)
const {
120 inline pmesher_signed_distance new_mesher_half_space
121 (
const base_node &x0,
const base_small_vector &n)
122 {
return std::make_shared<mesher_half_space>(x0, n); }
124 class mesher_level_set :
public mesher_signed_distance {
126 mutable std::vector<base_poly> gradient;
127 mutable std::vector<base_poly> hessian;
128 const fem<base_poly> *pf;
129 mutable int initialized;
130 scalar_type shift_ls;
132 bool is_initialized(
void)
const {
return initialized; }
133 mesher_level_set() : initialized(0) {}
134 template <
typename VECT>
135 mesher_level_set(
pfem pf_,
const VECT &coeff_,
136 scalar_type shift_ls_ = scalar_type(0)) {
137 init_base(pf_, coeff_);
138 set_shift(shift_ls_);
140 void set_shift(scalar_type shift_ls_) {
141 shift_ls = shift_ls_;
142 if (shift_ls != scalar_type(0)) {
143 base_node P(pf->dim()); base_small_vector G(pf->dim());
148 template <
typename VECT>
void init_base(
pfem pf_,
const VECT &coeff_);
149 void init_grad(
void)
const;
150 void init_hess(
void)
const;
152 bool bounding_box(base_node &, base_node &)
const
154 virtual scalar_type operator()(
const base_node &P)
const
155 {
return bgeot::to_scalar(base.
eval(P.begin())) + shift_ls; }
156 virtual scalar_type operator()(
const base_node &P,
157 dal::bit_vector &bv)
const
158 { scalar_type d = (*this)(P); bv[id] = (gmm::abs(d) < SEPS);
return d; }
159 virtual void register_constraints(std::vector<
const
160 mesher_signed_distance*>& list)
const {
161 id = list.size(); list.push_back(
this);
163 scalar_type grad(
const base_node &P, base_small_vector &G)
const;
164 void hess(
const base_node &P, base_matrix &H)
const;
167 template <
typename VECT>
168 void mesher_level_set::init_base(
pfem pf_,
const VECT &coeff_) {
169 std::vector<scalar_type> coeff(coeff_.begin(), coeff_.end());
170 GMM_ASSERT1(gmm::vect_norm2(coeff) != 0,
"level is zero!");
171 pf =
dynamic_cast<const fem<base_poly>*
> (pf_.get());
172 GMM_ASSERT1(pf,
"A polynomial fem is required for level set (got "
173 <<
typeid(pf_).name() <<
")");
174 base = base_poly(pf->base()[0].dim(), pf->base()[0].degree());
175 for (
unsigned i=0; i < pf->nb_base(0); ++i) {
176 base += pf->base()[i] * coeff[i];
181 template <
typename VECT>
182 inline pmesher_signed_distance new_mesher_level_set
183 (
pfem pf,
const VECT &coeff, scalar_type shift_ls = scalar_type(0))
184 {
return std::make_shared<mesher_level_set>(pf, coeff, shift_ls); }
187 class mesher_ball :
public mesher_signed_distance {
188 base_node x0; scalar_type R;
190 mesher_ball(base_node x0_, scalar_type R_) : x0(x0_), R(R_) {}
191 bool bounding_box(base_node &bmin, base_node &bmax)
const {
193 for (
size_type i=0; i < x0.size(); ++i) { bmin[i] -= R; bmax[i] += R; }
196 virtual scalar_type operator()(
const base_node &P,
197 dal::bit_vector &bv)
const {
199 bv[id] = (gmm::abs(d) < SEPS);
202 virtual scalar_type operator()(
const base_node &P)
const
204 virtual void register_constraints(std::vector<
const
205 mesher_signed_distance*>& list)
const {
206 id = list.size(); list.push_back(
this);
208 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
211 while (e == scalar_type(0))
216 void hess(
const base_node &, base_matrix &)
const {
217 GMM_ASSERT1(
false,
"Sorry, to be done");
221 inline pmesher_signed_distance new_mesher_ball(base_node x0, scalar_type R)
222 {
return std::make_shared<mesher_ball>(x0, R); }
224 class mesher_rectangle :
public mesher_signed_distance {
226 base_node rmin, rmax;
227 std::vector<mesher_half_space> hfs;
229 mesher_rectangle(base_node rmin_, base_node rmax_)
230 : rmin(rmin_), rmax(rmax_), hfs(rmin.size()*2) {
231 base_node n(rmin_.size());
232 for (
unsigned k = 0; k < rmin.size(); ++k) {
234 hfs[k*2] = mesher_half_space(rmin, n);
236 hfs[k*2+1] = mesher_half_space(rmax, n);
240 bool bounding_box(base_node &bmin, base_node &bmax)
const {
241 bmin = rmin; bmax = rmax;
244 virtual scalar_type operator()(
const base_node &P)
const {
246 scalar_type d = rmin[0] - P[0];
248 d = std::max(d, rmin[i] - P[i]);
249 d = std::max(d, P[i] - rmax[i]);
254 virtual scalar_type operator()(
const base_node &P, dal::bit_vector &bv)
256 scalar_type d = this->operator()(P);
257 if (gmm::abs(d) < SEPS)
258 for (
int k = 0; k < 2*rmin.size(); ++k) hfs[k](P, bv);
261 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
262 unsigned i = 0; scalar_type di = hfs[i](P);
263 for (
int k = 1; k < 2*rmin.size(); ++k) {
264 scalar_type dk = hfs[k](P);
265 if (dk > di) { i = k; di = dk; }
267 return hfs[i].grad(P, G);
269 void hess(
const base_node &P, base_matrix &H)
const {
272 virtual void register_constraints(std::vector<
const
273 mesher_signed_distance*>& list)
const {
274 for (
int k = 0; k < 2*rmin.size(); ++k)
275 hfs[k].register_constraints(list);
279 inline pmesher_signed_distance new_mesher_rectangle(base_node rmin,
281 {
return std::make_shared<mesher_rectangle>(rmin, rmax); }
283 class mesher_simplex_ref :
public mesher_signed_distance {
285 std::vector<mesher_half_space> hfs;
289 mesher_simplex_ref(
unsigned N_) : hfs(N_+1), N(N_), org(N_) {
291 for (
unsigned k = 0; k < N; ++k) {
293 hfs[k] = mesher_half_space(org, no);
296 std::fill(org.begin(), org.end(), 1.0/N);
298 hfs[N] = mesher_half_space(org, no);
300 bool bounding_box(base_node &bmin, base_node &bmax)
const {
301 bmin.resize(N); bmax.resize(N);
302 std::fill(bmin.begin(), bmin.end(), scalar_type(0));
303 std::fill(bmax.begin(), bmax.end(), scalar_type(1));
306 virtual scalar_type operator()(
const base_node &P)
const {
307 scalar_type d = - P[0];
308 for (
size_type i=1; i < N; ++i) d = std::max(d, - P[i]);
309 d = std::max(d, gmm::vect_sp(P - org, org) / gmm::vect_norm2(org));
313 virtual scalar_type operator()(
const base_node &P, dal::bit_vector &bv)
315 scalar_type d = this->operator()(P);
316 if (gmm::abs(d) < SEPS)
for (
unsigned k = 0; k < N+1; ++k) hfs[k](P, bv);
319 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
320 unsigned i = 0; scalar_type di = hfs[i](P);
321 for (
unsigned k = 1; k < N+1; ++k) {
322 scalar_type dk = hfs[k](P);
323 if (dk > di) { i = k; di = dk; }
325 return hfs[i].grad(P, G);
327 void hess(
const base_node &P, base_matrix &H)
const {
330 virtual void register_constraints(std::vector<
const
331 mesher_signed_distance*>& list)
const
332 {
for (
unsigned k = 0; k < N+1; ++k) hfs[k].register_constraints(list); }
335 inline pmesher_signed_distance new_mesher_simplex_ref(
unsigned N)
336 {
return std::make_shared<mesher_simplex_ref>(N); }
339 class mesher_prism_ref :
public mesher_signed_distance {
341 std::vector<mesher_half_space> hfs;
345 mesher_prism_ref(
unsigned N_) : hfs(N_+2), N(N_) {
348 for (
unsigned k = 0; k < N; ++k) {
350 hfs[k] = mesher_half_space(org, no);
355 hfs[N] = mesher_half_space(org, no);
356 std::fill(org.begin(), org.end(), 1.0/N);
359 hfs[N+1] = mesher_half_space(org, no);
361 bool bounding_box(base_node &bmin, base_node &bmax)
const {
362 bmin.resize(N); bmax.resize(N);
363 std::fill(bmin.begin(), bmin.end(), scalar_type(0));
364 std::fill(bmax.begin(), bmax.end(), scalar_type(1));
367 virtual scalar_type operator()(
const base_node &P)
const {
368 scalar_type d = - P[0];
369 for (
size_type i=1; i < N; ++i) d = std::max(d, - P[i]);
370 d = std::max(d, P[N-1] - scalar_type(1));
371 d = std::max(d, gmm::vect_sp(P - org, org) / gmm::vect_norm2(org));
375 virtual scalar_type operator()(
const base_node &P, dal::bit_vector &bv)
377 scalar_type d = this->operator()(P);
378 if (gmm::abs(d) < SEPS)
for (
unsigned k = 0; k < N+2; ++k) hfs[k](P, bv);
381 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
382 unsigned i = 0; scalar_type di = hfs[i](P);
383 for (
unsigned k = 1; k < N+2; ++k) {
384 scalar_type dk = hfs[k](P);
385 if (dk > di) { i = k; di = dk; }
387 return hfs[i].grad(P, G);
389 void hess(
const base_node &P, base_matrix &H)
const {
392 virtual void register_constraints(std::vector<
const
393 mesher_signed_distance*>& list)
const
394 {
for (
unsigned k = 0; k < N+2; ++k) hfs[k].register_constraints(list); }
397 inline pmesher_signed_distance new_mesher_prism_ref(
unsigned N)
398 {
return std::make_shared<mesher_prism_ref>(N); }
407 class mesher_union :
public mesher_signed_distance {
408 std::vector<pmesher_signed_distance> dists;
409 mutable std::vector<scalar_type> vd;
413 mesher_union(
const std::vector<pmesher_signed_distance>
414 &dists_) : dists(dists_)
415 { vd.resize(dists.size()); with_min =
true; }
418 (
const pmesher_signed_distance &a,
419 const pmesher_signed_distance &b,
420 const pmesher_signed_distance &c = pmesher_signed_distance(),
421 const pmesher_signed_distance &d = pmesher_signed_distance(),
422 const pmesher_signed_distance &e = pmesher_signed_distance(),
423 const pmesher_signed_distance &f = pmesher_signed_distance(),
424 const pmesher_signed_distance &g = pmesher_signed_distance(),
425 const pmesher_signed_distance &h = pmesher_signed_distance(),
426 const pmesher_signed_distance &i = pmesher_signed_distance(),
427 const pmesher_signed_distance &j = pmesher_signed_distance(),
428 const pmesher_signed_distance &k = pmesher_signed_distance(),
429 const pmesher_signed_distance &l = pmesher_signed_distance(),
430 const pmesher_signed_distance &m = pmesher_signed_distance(),
431 const pmesher_signed_distance &n = pmesher_signed_distance(),
432 const pmesher_signed_distance &o = pmesher_signed_distance(),
433 const pmesher_signed_distance &p = pmesher_signed_distance(),
434 const pmesher_signed_distance &q = pmesher_signed_distance(),
435 const pmesher_signed_distance &r = pmesher_signed_distance(),
436 const pmesher_signed_distance &s = pmesher_signed_distance(),
437 const pmesher_signed_distance &t = pmesher_signed_distance()) {
438 dists.push_back(a); dists.push_back(b);
440 if (c) dists.push_back(c);
441 if (d) dists.push_back(d);
442 if (e) dists.push_back(e);
443 if (f) dists.push_back(f);
444 if (g) dists.push_back(g);
445 if (h) dists.push_back(h);
446 if (i) dists.push_back(i);
447 if (j) dists.push_back(j);
448 if (k) dists.push_back(k);
449 if (l) dists.push_back(l);
450 if (m) dists.push_back(m);
451 if (n) dists.push_back(n);
452 if (o) dists.push_back(o);
453 if (p) dists.push_back(p);
454 if (q) dists.push_back(q);
455 if (r) dists.push_back(r);
456 if (s) dists.push_back(s);
457 if (t) dists.push_back(t);
458 vd.resize(dists.size());
461 bool bounding_box(base_node &bmin, base_node &bmax)
const {
462 base_node bmin2, bmax2;
463 bool b = dists[0]->bounding_box(bmin, bmax);
464 if (!b)
return false;
465 for (
size_type k = 1; k < dists.size(); ++k) {
466 b = dists[k]->bounding_box(bmin2, bmax2);
467 if (!b)
return false;
468 for (
unsigned i=0; i < bmin.size(); ++i) {
469 bmin[i] = std::min(bmin[i],bmin2[i]);
470 bmax[i] = std::max(bmax[i],bmax2[i]);
475 virtual scalar_type operator()(
const base_node &P)
const {
476 scalar_type d, f(0), g(1);
478 d = (*(dists[0]))(P);
479 for (
size_type k = 1; k < dists.size(); ++k)
480 d = std::min(d, (*(dists[k]))(P));
484 for (
size_type k = 0; k < dists.size(); ++k) {
485 vd[k] = (*(dists[k]))(P);
486 if (vd[k] <= scalar_type(0)) isin =
true;
487 f += gmm::sqr(gmm::neg(vd[k]));
488 g *= gmm::pos(vd[k]);
490 d = isin ? -gmm::sqrt(f)
491 : pow(g, scalar_type(1) / scalar_type(dists.size()));
495 scalar_type operator()(
const base_node &P, dal::bit_vector &bv)
const {
497 scalar_type d = vd[0] = (*(dists[0]))(P);
498 bool ok = (d > -SEPS);
499 for (
size_type k = 1; k < dists.size(); ++k) {
500 vd[k] = (*(dists[k]))(P);
if (vd[k] <= -SEPS) ok =
false;
501 d = std::min(d,vd[k]);
503 for (
size_type k = 0; ok && k < dists.size(); ++k) {
504 if (vd[k] < SEPS) (*(dists[k]))(P, bv);
509 vd[0] = (*(dists[0]))(P);
510 bool ok = (vd[0] > -SEPS);
511 for (
size_type k = 1; k < dists.size(); ++k) {
512 vd[k] = (*(dists[k]))(P);
if (vd[k] <= -SEPS) ok =
false;
514 for (
size_type k = 0; ok && k < dists.size(); ++k) {
515 if (vd[k] < SEPS) (*(dists[k]))(P, bv);
517 return operator()(P);
520 virtual void register_constraints(std::vector<
const
521 mesher_signed_distance*>& list)
const {
522 for (
size_type k = 0; k < dists.size(); ++k)
523 dists[k]->register_constraints(list);
525 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
528 d = (*(dists[0]))(P);
530 for (
size_type k = 1; k < dists.size(); ++k) {
531 scalar_type d2 = (*(dists[k]))(P);
532 if (d2 < d) { d = d2; i = k; }
534 return dists[i]->grad(P, G);
538 base_small_vector Gloc;
539 for (
size_type k = 0; k < dists.size(); ++k) {
540 dists[k]->grad(P, Gloc);
542 Gloc *= -gmm::neg(vd[k]);
544 Gloc *= pow(d, scalar_type(dists.size())) / vd[k];
545 if (!k) G = Gloc;
else G += Gloc;
548 G *= scalar_type(1) / d;
550 G /= pow(d, scalar_type(dists.size()-1)) * scalar_type(dists.size());
554 void hess(
const base_node &P, base_matrix &H)
const {
555 scalar_type d = (*(dists[0]))(P);
556 if (with_min || gmm::abs(d) < SEPS) {
558 for (
size_type k = 1; k < dists.size(); ++k) {
559 scalar_type d2 = (*(dists[k]))(P);
560 if (d2 < d) { d = d2; i = k; }
562 dists[i]->hess(P, H);
565 GMM_ASSERT1(
false,
"Sorry, to be done");
570 inline pmesher_signed_distance new_mesher_union
571 (
const std::vector<pmesher_signed_distance> &dists)
572 {
return std::make_shared<mesher_union>(dists); }
574 inline pmesher_signed_distance new_mesher_union
575 (
const pmesher_signed_distance &a,
576 const pmesher_signed_distance &b,
577 const pmesher_signed_distance &c = pmesher_signed_distance(),
578 const pmesher_signed_distance &d = pmesher_signed_distance(),
579 const pmesher_signed_distance &e = pmesher_signed_distance(),
580 const pmesher_signed_distance &f = pmesher_signed_distance(),
581 const pmesher_signed_distance &g = pmesher_signed_distance(),
582 const pmesher_signed_distance &h = pmesher_signed_distance(),
583 const pmesher_signed_distance &i = pmesher_signed_distance(),
584 const pmesher_signed_distance &j = pmesher_signed_distance(),
585 const pmesher_signed_distance &k = pmesher_signed_distance(),
586 const pmesher_signed_distance &l = pmesher_signed_distance(),
587 const pmesher_signed_distance &m = pmesher_signed_distance(),
588 const pmesher_signed_distance &n = pmesher_signed_distance(),
589 const pmesher_signed_distance &o = pmesher_signed_distance(),
590 const pmesher_signed_distance &p = pmesher_signed_distance(),
591 const pmesher_signed_distance &q = pmesher_signed_distance(),
592 const pmesher_signed_distance &r = pmesher_signed_distance(),
593 const pmesher_signed_distance &s = pmesher_signed_distance(),
594 const pmesher_signed_distance &t = pmesher_signed_distance()) {
595 return std::make_shared<mesher_union>
596 (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t);
601 class mesher_intersection :
public mesher_signed_distance {
602 std::vector<pmesher_signed_distance> dists;
603 mutable std::vector<scalar_type> vd;
608 mesher_intersection(
const std::vector<pmesher_signed_distance>
609 &dists_) : dists(dists_)
610 { vd.resize(dists.size()); }
613 (
const pmesher_signed_distance &a,
614 const pmesher_signed_distance &b,
615 const pmesher_signed_distance &c = pmesher_signed_distance(),
616 const pmesher_signed_distance &d = pmesher_signed_distance(),
617 const pmesher_signed_distance &e = pmesher_signed_distance(),
618 const pmesher_signed_distance &f = pmesher_signed_distance(),
619 const pmesher_signed_distance &g = pmesher_signed_distance(),
620 const pmesher_signed_distance &h = pmesher_signed_distance(),
621 const pmesher_signed_distance &i = pmesher_signed_distance(),
622 const pmesher_signed_distance &j = pmesher_signed_distance(),
623 const pmesher_signed_distance &k = pmesher_signed_distance(),
624 const pmesher_signed_distance &l = pmesher_signed_distance(),
625 const pmesher_signed_distance &m = pmesher_signed_distance(),
626 const pmesher_signed_distance &n = pmesher_signed_distance(),
627 const pmesher_signed_distance &o = pmesher_signed_distance(),
628 const pmesher_signed_distance &p = pmesher_signed_distance(),
629 const pmesher_signed_distance &q = pmesher_signed_distance(),
630 const pmesher_signed_distance &r = pmesher_signed_distance(),
631 const pmesher_signed_distance &s = pmesher_signed_distance(),
632 const pmesher_signed_distance &t = pmesher_signed_distance()) {
633 dists.push_back(a); dists.push_back(b);
634 if (c) dists.push_back(c);
635 if (d) dists.push_back(d);
636 if (e) dists.push_back(e);
637 if (f) dists.push_back(f);
638 if (g) dists.push_back(g);
639 if (h) dists.push_back(h);
640 if (i) dists.push_back(i);
641 if (j) dists.push_back(j);
642 if (k) dists.push_back(k);
643 if (l) dists.push_back(l);
644 if (m) dists.push_back(m);
645 if (n) dists.push_back(n);
646 if (o) dists.push_back(o);
647 if (p) dists.push_back(p);
648 if (q) dists.push_back(q);
649 if (r) dists.push_back(r);
650 if (s) dists.push_back(s);
651 if (t) dists.push_back(t);
652 vd.resize(dists.size());
654 bool bounding_box(base_node &bmin, base_node &bmax)
const {
655 base_node bmin2, bmax2;
657 bool b = dists[0]->bounding_box(bmin, bmax); first = !b;
658 for (
size_type k = 1; k < dists.size(); ++k) {
659 bool bb = dists[k]->bounding_box(bmin2, bmax2);
660 for (
unsigned i=0; i < bmin.size() && bb && !first; ++i) {
661 bmin[i] = std::max(bmin[i],bmin2[i]);
662 bmax[i] = std::max(std::min(bmax[i],bmax2[i]), bmin[i]);
664 if (first && bb) { bmin = bmin2; bmax = bmax2; first =
false; }
669 virtual scalar_type operator()(
const base_node &P)
const {
670 scalar_type d = (*(dists[0]))(P);
671 for (
size_type k = 1; k < dists.size(); ++k)
672 d = std::max(d, (*(dists[k]))(P));
676 scalar_type operator()(
const base_node &P, dal::bit_vector &bv)
const {
677 scalar_type d = vd[0] = (*(dists[0]))(P);
678 bool ok = (d < SEPS);
679 for (
size_type k = 1; k < dists.size(); ++k) {
680 vd[k] = (*(dists[k]))(P);
if (vd[k] >= SEPS) ok =
false;
681 d = std::min(d,vd[k]);
683 for (
size_type k = 0; ok && k < dists.size(); ++k) {
684 if (vd[k] > -SEPS) (*(dists[k]))(P, bv);
688 virtual void register_constraints(std::vector<
const
689 mesher_signed_distance*>& list)
const {
690 for (
size_type k = 0; k < dists.size(); ++k) {
691 dists[k]->register_constraints(list);
694 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
695 scalar_type d = (*(dists[0]))(P);
697 for (
size_type k = 1; k < dists.size(); ++k) {
698 scalar_type d2 = (*(dists[k]))(P);
699 if (d2 > d) { d = d2; i = k; }
701 return dists[i]->grad(P, G);
703 void hess(
const base_node &P, base_matrix &H)
const {
704 scalar_type d = (*(dists[0]))(P);
706 for (
size_type k = 1; k < dists.size(); ++k) {
707 scalar_type d2 = (*(dists[k]))(P);
708 if (d2 > d) { d = d2; i = k; }
710 dists[i]->hess(P, H);
714 inline pmesher_signed_distance new_mesher_intersection
715 (
const std::vector<pmesher_signed_distance> &dists)
716 {
return std::make_shared<mesher_intersection>(dists); }
718 inline pmesher_signed_distance new_mesher_intersection
719 (
const pmesher_signed_distance &a,
720 const pmesher_signed_distance &b,
721 const pmesher_signed_distance &c = pmesher_signed_distance(),
722 const pmesher_signed_distance &d = pmesher_signed_distance(),
723 const pmesher_signed_distance &e = pmesher_signed_distance(),
724 const pmesher_signed_distance &f = pmesher_signed_distance(),
725 const pmesher_signed_distance &g = pmesher_signed_distance(),
726 const pmesher_signed_distance &h = pmesher_signed_distance(),
727 const pmesher_signed_distance &i = pmesher_signed_distance(),
728 const pmesher_signed_distance &j = pmesher_signed_distance(),
729 const pmesher_signed_distance &k = pmesher_signed_distance(),
730 const pmesher_signed_distance &l = pmesher_signed_distance(),
731 const pmesher_signed_distance &m = pmesher_signed_distance(),
732 const pmesher_signed_distance &n = pmesher_signed_distance(),
733 const pmesher_signed_distance &o = pmesher_signed_distance(),
734 const pmesher_signed_distance &p = pmesher_signed_distance(),
735 const pmesher_signed_distance &q = pmesher_signed_distance(),
736 const pmesher_signed_distance &r = pmesher_signed_distance(),
737 const pmesher_signed_distance &s = pmesher_signed_distance(),
738 const pmesher_signed_distance &t = pmesher_signed_distance()) {
739 return std::make_shared<mesher_intersection>
740 (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t);
745 class mesher_setminus :
public mesher_signed_distance {
746 pmesher_signed_distance a, b;
748 mesher_setminus(
const pmesher_signed_distance& a_,
749 const pmesher_signed_distance &b_) : a(a_), b(b_) {}
750 bool bounding_box(base_node &bmin, base_node &bmax)
const
751 {
return a->bounding_box(bmin,bmax); }
752 scalar_type operator()(
const base_node &P, dal::bit_vector &bv)
const {
753 scalar_type da = (*a)(P), db = -(*b)(P);
754 if (da < SEPS && db < SEPS) {
755 if (da > -SEPS) (*a)(P, bv);
756 if (db > -SEPS) (*b)(P, bv);
758 return std::max(da, db);
760 scalar_type operator()(
const base_node &P)
const
761 {
return std::max((*a)(P),-(*b)(P)); }
762 virtual void register_constraints(std::vector<
const
763 mesher_signed_distance*>& list)
const {
764 a->register_constraints(list); b->register_constraints(list);
766 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
767 scalar_type da = (*a)(P), db = -(*b)(P);
768 if (da > db)
return a->grad(P, G);
769 else { b->grad(P, G); G *= scalar_type(-1);
return db; }
771 void hess(
const base_node &P, base_matrix &H)
const {
772 scalar_type da = (*a)(P), db = -(*b)(P);
773 if (da > db) a->hess(P, H);
774 else { b->hess(P, H); gmm::scale(H, scalar_type(-1)); }
779 inline pmesher_signed_distance new_mesher_setminus
780 (
const pmesher_signed_distance &a,
const pmesher_signed_distance &b)
781 {
return std::make_shared<mesher_setminus>(a, b); }
784 class mesher_tube :
public mesher_signed_distance {
785 base_node x0; base_node n; scalar_type R;
787 mesher_tube(base_node x0_, base_node n_, scalar_type R_)
788 : x0(x0_), n(n_), R(R_)
790 bool bounding_box(base_node &, base_node &)
const
792 virtual scalar_type operator()(
const base_node &P)
const {
793 base_node v(P); v -= x0;
794 gmm::add(gmm::scaled(n, -gmm::vect_sp(v, n)), v);
797 virtual scalar_type operator()(
const base_node &P,
798 dal::bit_vector &bv)
const {
799 scalar_type d = (*this)(P);
800 bv[id] = (gmm::abs(d) < SEPS);
803 virtual void register_constraints(std::vector<
const
804 mesher_signed_distance*>& list)
const {
805 id = list.size(); list.push_back(
this);
807 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
809 gmm::add(gmm::scaled(n, -gmm::vect_sp(G, n)), G);
811 while (e == scalar_type(0)) {
813 gmm::add(gmm::scaled(n, -gmm::vect_sp(G, n)), G);
819 void hess(
const base_node &, base_matrix &)
const {
820 GMM_ASSERT1(
false,
"Sorry, to be done");
824 inline pmesher_signed_distance new_mesher_tube(base_node x0, base_node n,
826 {
return std::make_shared<mesher_tube>(x0,n,R); }
829 class mesher_cylinder :
public mesher_signed_distance {
830 base_node x0; base_small_vector n;
832 pmesher_signed_distance t, p1, p2, i1;
834 mesher_cylinder(
const base_node &c,
const base_small_vector &no,
835 scalar_type L_, scalar_type R_)
836 : x0(c), n(no/gmm::
vect_norm2(no)), L(L_), R(R_),
837 t(new_mesher_tube(x0, n, R)),
838 p1(new_mesher_half_space(x0, n)),
839 p2(new_mesher_half_space(x0+n*L, -1.0 * n)),
840 i1(new_mesher_intersection(p1, p2, t)) {}
841 bool bounding_box(base_node &bmin, base_node &bmax)
const {
842 base_node x1(x0+n*L);
844 for (
unsigned i = 0; i < gmm::vect_size(x0); ++i) {
845 bmin[i] = std::min(x0[i], x1[i]) - R;
846 bmax[i] = std::max(x0[i], x1[i]) + R;
850 virtual scalar_type operator()(
const base_node &P)
const {
return (*i1)(P); }
851 virtual scalar_type operator()(
const base_node &P,
852 dal::bit_vector& bv)
const
853 {
return (*i1)(P, bv); }
854 scalar_type grad(
const base_node &P, base_small_vector &G)
const
855 {
return i1->grad(P, G); }
856 void hess(
const base_node &, base_matrix &)
const {
857 GMM_ASSERT1(
false,
"Sorry, to be done");
859 virtual void register_constraints(std::vector<
const
860 mesher_signed_distance*>& list)
const
861 { i1->register_constraints(list); }
864 inline pmesher_signed_distance new_mesher_cylinder
865 (
const base_node &c,
const base_small_vector &no,
866 scalar_type L, scalar_type R)
867 {
return std::make_shared<mesher_cylinder>(c,no,L,R); }
870 class mesher_infinite_cone :
public mesher_signed_distance {
872 base_node x0; base_node n; scalar_type
alpha;
874 mesher_infinite_cone(base_node x0_, base_node n_, scalar_type alpha_)
875 : x0(x0_), n(n_),
alpha(alpha_)
877 bool bounding_box(base_node &, base_node &)
const
879 virtual scalar_type operator()(
const base_node &P)
const {
880 base_node v(P); v -= x0;
885 virtual scalar_type operator()(
const base_node &P,
886 dal::bit_vector &bv)
const {
887 scalar_type d = (*this)(P);
888 bv[id] = (gmm::abs(d) < SEPS);
891 virtual void register_constraints(std::vector<
const
892 mesher_signed_distance*>& list)
const {
893 id = list.size(); list.push_back(
this);
895 scalar_type grad(
const base_node &P, base_small_vector &v)
const {
900 scalar_type d = no * cos(alpha) - gmm::abs(v_n) * sin(alpha);
901 while (no == scalar_type(0)) {
903 gmm::add(gmm::scaled(n, -gmm::vect_sp(v, n)), v);
906 v *= cos(alpha) / no;
907 v -= (sin(alpha) * gmm::sgn(v_n)) * n;
910 void hess(
const base_node &, base_matrix &)
const {
911 GMM_ASSERT1(
false,
"Sorry, to be done");
915 inline pmesher_signed_distance new_mesher_infinite_cone
916 (base_node x0, base_node n, scalar_type alpha)
917 {
return std::make_shared<mesher_infinite_cone>(x0,n,alpha); }
920 class mesher_cone :
public mesher_signed_distance {
921 base_node x0; base_small_vector n;
922 scalar_type L,
alpha;
923 pmesher_signed_distance t, p1, p2, i1;
925 mesher_cone(
const base_node &c,
const base_small_vector &no,
926 scalar_type L_, scalar_type alpha_)
928 t(new_mesher_infinite_cone(x0, n,
alpha)),
929 p1(new_mesher_half_space(x0, n)),
930 p2(new_mesher_half_space(x0+n*L, -1.0 * n)),
931 i1(new_mesher_intersection(p1, p2, t)) {}
932 bool bounding_box(base_node &bmin, base_node &bmax)
const {
933 base_node x1(x0+n*L);
934 scalar_type R = L * sin(alpha);
936 for (
unsigned i = 0; i < gmm::vect_size(x0); ++i) {
937 bmin[i] = std::min(x0[i], x1[i]) - R;
938 bmax[i] = std::max(x0[i], x1[i]) + R;
942 virtual scalar_type operator()(
const base_node &P)
const {
return (*i1)(P); }
943 virtual scalar_type operator()(
const base_node &P,
944 dal::bit_vector& bv)
const
945 {
return (*i1)(P, bv); }
946 scalar_type grad(
const base_node &P, base_small_vector &G)
const
947 {
return i1->grad(P, G); }
948 void hess(
const base_node &, base_matrix &)
const {
949 GMM_ASSERT1(
false,
"Sorry, to be done");
951 virtual void register_constraints(std::vector<
const
952 mesher_signed_distance*>& list)
const
953 { i1->register_constraints(list); }
956 inline pmesher_signed_distance new_mesher_cone
957 (
const base_node &c,
const base_small_vector &no,
958 scalar_type L, scalar_type alpha)
959 {
return std::make_shared<mesher_cone>(c,no,L,alpha); }
962 class mesher_ellipse :
public mesher_signed_distance {
963 base_node x0; base_small_vector n, t;
966 mesher_ellipse(
const base_node ¢er,
const base_small_vector &no,
967 scalar_type r_, scalar_type R_)
968 : x0(center), n(no/gmm::
vect_norm2(no)), r(r_), R(R_) {
969 t[0] = -n[1]; t[1] = n[0];
970 if (R < r) { std::swap(r, R); std::swap(n, t); }
973 bool bounding_box(base_node &bmin, base_node &bmax)
const {
975 for (
unsigned i = 0; i < 2; ++i) { bmin[i] -= R; bmax[i] += R; }
978 virtual scalar_type operator()(
const base_node &P)
const {
979 base_small_vector v(P); v -= x0;
981 vt = std::max(-a, std::min(a, vt));
982 base_node x1 = x0 + t*vt;
983 base_small_vector v1(P); v1 -= x1;
986 scalar_type ea = v1n*v1n / (r*r) + v1t * v1t / (R*R);
987 scalar_type eb = 2. * (x1n*v1n / (r*r) + x1t*v1t / (R*R));
988 scalar_type ec = x1n*x1n / (r*r) + x1t * x1t / (R*R);
990 scalar_type delta = eb*eb - 4 * ea * ec;
992 scalar_type lambda = (-eb + sqrt(delta)) / (2. * ea);
995 virtual scalar_type operator()(
const base_node &P,
996 dal::bit_vector& bv)
const {
997 scalar_type d = this->operator()(P);
998 bv[id] = (gmm::abs(d) < SEPS);
1001 scalar_type grad(
const base_node &, base_small_vector &)
const
1002 { GMM_ASSERT1(
false,
"Sorry, to be done");
return 0.; }
1003 void hess(
const base_node &, base_matrix &)
const {
1004 GMM_ASSERT1(
false,
"Sorry, to be done");
1006 virtual void register_constraints(std::vector<
const
1007 mesher_signed_distance*>& list)
const
1008 {
id = list.size(); list.push_back(
this); }
1011 inline pmesher_signed_distance new_mesher_ellipse
1012 (
const base_node ¢er,
const base_small_vector &no,
1013 scalar_type r, scalar_type R)
1014 {
return std::make_shared<mesher_ellipse>(center,no,r,R); }
1018 class mesher_torus :
public mesher_signed_distance {
1022 mesher_torus(scalar_type RR, scalar_type rr) : R(RR), r(rr) {}
1023 bool bounding_box(base_node &bmin, base_node &bmax)
const {
1024 bmin = base_node(3); bmax = base_node(3);
1025 bmin[0] = bmin[1] = -R-r; bmin[2] = -r;
1026 bmax[0] = bmax[1] = +R+r; bmax[2] = +r;
1029 virtual scalar_type operator()(
const base_node &P)
const {
1030 scalar_type x = P[0], y = P[1], z = P[2], c = sqrt(x*x + y*y);
1031 return (c == 0.) ? R - r : sqrt(gmm::sqr(c-R) + z*z) - r;
1033 virtual scalar_type operator()(
const base_node &P, dal::bit_vector&bv)
1035 scalar_type d = this->operator()(P);
1036 bv[id] = (gmm::abs(d) < SEPS);
1039 scalar_type grad(
const base_node &P, base_small_vector &G)
const {
1041 scalar_type x = P[0], y = P[1], z = P[2], c = sqrt(x*x + y*y), d(0);
1047 scalar_type w = 1. - R / c, e = sqrt(gmm::sqr(c-R) + z*z);
1053 G[0] = x * w / e; G[1] = y * w / e; G[2] = z / e;
1058 void hess(
const base_node &, base_matrix &)
const {
1059 GMM_ASSERT1(
false,
"Sorry, to be done");
1061 virtual void register_constraints(std::vector<
const
1062 mesher_signed_distance*>&list)
const
1063 {
id = list.size(); list.push_back(
this); }
1067 inline pmesher_signed_distance new_mesher_torus(scalar_type R, scalar_type r)
1068 {
return std::make_shared<mesher_torus>(R,r); }
1071 void build_mesh(mesh &m,
const pmesher_signed_distance& dist_,
1072 scalar_type h0,
const std::vector<base_node> &fixed_points
1073 = std::vector<base_node>(),
size_type K = 1,
int noise = -1,
1074 size_type iter_max = 500,
int prefind = 1,
1075 scalar_type dist_point_hull = 4,
1076 scalar_type boundary_threshold_flatness = 0.11);
1079 bool try_projection(
const mesher_signed_distance& dist, base_node &X,
1080 bool on_surface =
false);
1081 bool pure_multi_constraint_projection
1082 (
const std::vector<const mesher_signed_distance*> &list_constraints,
1083 base_node &X,
const dal::bit_vector &cts);
1084 scalar_type curvature_radius_estimate(
const mesher_signed_distance &dist,
1085 base_node X,
bool proj =
false);
1086 scalar_type min_curvature_radius_estimate
1087 (
const std::vector<const mesher_signed_distance*> &list_constraints,
1088 const base_node &X,
const dal::bit_vector &cts,
size_type hide_first = 0);
convenient initialization of vectors via overload of "operator,".
Simple implementation of a KD-tree.
T eval(const ITER &it) const
Evaluate the polynomial.
base class for static stored objects
Export solutions to various formats.
Define a getfem::getfem_mesh object.
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
void fill_random(L &l)
fill a vector or matrix with random value (uniform [-1,1]).
void clear(L &l)
clear (fill with zeros) a vector or matrix.
number_traits< typename linalg_traits< V1 >::value_type >::magnitude_type vect_dist2(const V1 &v1, const V2 &v2)
Euclidean distance between two vectors.
void resize(V &v, size_type n)
*/
strongest_value_type< V1, V2 >::value_type vect_sp(const V1 &v1, const V2 &v2)
*/
void add(const L1 &l1, L2 &l2)
*/
computation of the condition number of dense matrices.
Implements BFGS (Broyden, Fletcher, Goldfarb, Shanno) algorithm.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
size_t size_type
used as the common size type in the library
size_type alpha(short_type n, short_type d)
Return the value of which is the number of monomials of a polynomial of variables and degree .
GEneric Tool for Finite Element Methods.