39 #ifndef GETFEM_CONTINUATION_H__
40 #define GETFEM_CONTINUATION_H__
51 template <
typename VECT,
typename MAT>
52 class virtual_cont_struct {
56 const double tau_bp_init = 1.e6;
57 const double diffeps = 1.e-8;
59 static constexpr
double tau_bp_init = 1.e6;
60 static constexpr
double diffeps = 1.e-8;
68 double scfac, h_init_, h_max_, h_min_, h_inc_, h_dec_;
70 double maxres_, maxdiff_, mincos_, delta_max_, delta_min_, thrvar_;
73 double tau_lp, tau_bp_1, tau_bp_2;
76 std::map<double, double> tau_bp_graph;
77 VECT alpha_hist, tau_bp_hist;
78 std::string sing_label;
80 double gamma_sing, gamma_next;
81 std::vector<VECT> tx_sing, tx_predict;
82 std::vector<double> tgamma_sing, tgamma_predict;
86 double bb_gamma, cc_gamma, dd;
91 void compute_tangent(
const VECT &x,
double gamma,
92 VECT &tx,
double &tgamma) {
95 solve_grad(x, gamma, y, g);
96 tgamma = 1. / (tgamma - w_sp(tx, y));
99 scale(tx, tgamma, 1./w_norm(tx, tgamma));
101 mult_grad(x, gamma, tx, y);
102 gmm::add(gmm::scaled(g, tgamma), y);
105 GMM_WARNING2(
"Tangent computed with the residual " << r);
113 bool test_tangent(
const VECT &x,
double gamma,
114 const VECT &tX,
double tGamma,
115 const VECT &tx,
double tgamma,
double h) {
117 double Gamma1, tGamma1(tgamma);
120 scaled_add(x, gamma, tX, tGamma, h, X1, Gamma1);
121 compute_tangent(X1, Gamma1, tX1, tGamma1);
123 double cang = cosang(tX1, tX, tGamma1, tGamma);
125 cout <<
"cos of the angle with the tested tangent " << cang << endl;
126 if (cang >= mincos())
129 cang = cosang(tX1, tx, tGamma1, tGamma);
131 cout <<
"cos of the angle with the initial tangent " << cang << endl;
137 bool switch_tangent(
const VECT &x,
double gamma,
138 VECT &tx,
double &tgamma,
double &h) {
139 double Gamma, tGamma(tgamma);
142 if (noisy() > 0) cout <<
"Trying a simple tangent switch" << endl;
143 if (noisy() > 1) cout <<
"Computing a new tangent" << endl;
145 scaled_add(x, gamma, tx, tgamma, h, X, Gamma);
146 compute_tangent(X, Gamma, tX, tGamma);
152 cout <<
"Starting testing the computed tangent" << endl;
153 double h_test = -0.9 * h_min();
154 bool accepted(
false);
155 while (!accepted && (h_test > -h_max())) {
157 + pow(10., floor(log10(-h_test / h_min()))) * h_min();
158 accepted = test_tangent(x, gamma, tX, tGamma, tx, tgamma, h_test);
161 accepted = test_tangent(x, gamma, tX, tGamma, tx, tgamma, h_test);
172 cout <<
"Tangent direction switched, "
173 <<
"starting computing a suitable step size" << endl;
175 bool h_adapted =
false;
176 while (!h_adapted && (h > h_test)) {
177 h_adapted = test_tangent(x, gamma, tX, tGamma, tx, tgamma, h);
180 h = h_adapted ? h / h_dec() : h_test;
181 copy(tX, tGamma, tx, tgamma);
183 if (noisy() > 0) cout <<
"Simple tangent switch has failed!" << endl;
189 bool test_limit_point(
double tgamma) {
190 double tau_lp_old = get_tau_lp();
192 return (tgamma * tau_lp_old < 0);
195 void init_test_functions(
const VECT &x,
double gamma,
196 const VECT &tx,
double tgamma) {
198 if (this->singularities > 1) {
199 if (noisy() > 1) cout <<
"Computing an initial value of the "
200 <<
"test function for bifurcations" << endl;
201 set_tau_bp_2(test_function_bp(x, gamma, tx, tgamma));
208 double test_function_bp(
const MAT &A,
const VECT &g,
209 const VECT &tx,
double tgamma,
210 VECT &v_x,
double &v_gamma) {
214 solve(A, y, z, g, bb_x(nn));
215 v_gamma = (bb_gamma - sp(tx, z)) / (tgamma - sp(tx, y));
216 scaled_add(z, y, -v_gamma, v_x);
217 double tau = 1. / (dd - sp(cc_x(nn), v_x) - cc_gamma * v_gamma);
218 scale(v_x, v_gamma, -tau);
222 gmm::add(gmm::scaled(g, v_gamma), y);
223 gmm::add(gmm::scaled(bb_x(nn), tau), y);
224 double r = sp(tx, v_x) + tgamma * v_gamma + bb_gamma * tau;
225 double q = sp(cc_x(nn), v_x) + cc_gamma * v_gamma + dd * tau - 1.;
226 r = sqrt(sp(y, y) + r * r + q * q);
228 GMM_WARNING2(
"Test function evaluated with the residual " << r);
233 double test_function_bp(
const MAT &A,
const VECT &g,
234 const VECT &tx,
double tgamma) {
237 return test_function_bp(A, g, tx, tgamma, v_x, v_gamma);
242 double test_function_bp(
const VECT &x,
double gamma,
243 const VECT &tx,
double tgamma,
244 VECT &v_x,
double &v_gamma) {
247 F_gamma(x, gamma, g);
248 return test_function_bp(A, g, tx, tgamma, v_x, v_gamma);
251 double test_function_bp(
const VECT &x,
double gamma,
252 const VECT &tx,
double tgamma) {
255 return test_function_bp(x, gamma, tx, tgamma, v_x, v_gamma);
260 bool test_smooth_bifurcation(
const VECT &x,
double gamma,
261 const VECT &tx,
double tgamma) {
262 double tau_bp_1_old = get_tau_bp_1();
263 set_tau_bp_1(get_tau_bp_2());
264 set_tau_bp_2(test_function_bp(x, gamma, tx, tgamma));
265 return (get_tau_bp_2() * get_tau_bp_1() < 0) &&
266 (gmm::abs(get_tau_bp_1()) < gmm::abs(tau_bp_1_old));
270 bool test_nonsmooth_bifurcation(
const VECT &x1,
double gamma1,
271 const VECT &tx1,
double tgamma1,
272 const VECT &x2,
double gamma2,
273 const VECT &tx2,
double tgamma2) {
274 VECT g1(x1), g2(x1), g(x1), tx(x1);
279 F_gamma(x2, gamma2, g2);
281 F_gamma(x1, gamma1, g1);
282 double tau1 = test_function_bp(A1, g1, tx1, tgamma1);
283 double tau2 = test_function_bp(A2, g2, tx2, tgamma2);
284 double tau_var_ref = std::max(gmm::abs(tau2 - tau1), 1.e-8);
292 double delta = delta_min(), tau0 = tau_bp_init, tgamma;
293 for (
double alpha=0.;
alpha < 1.; ) {
294 alpha = std::min(alpha + delta, 1.);
295 scaled_add(A1, 1.-alpha, A2, alpha, A);
296 scaled_add(g1, 1.-alpha, g2, alpha, g);
297 scaled_add(tx1, tgamma1, 1.-alpha, tx2, tgamma2, alpha, tx, tgamma);
300 tau2 = test_function_bp(A, g, tx, tgamma);
301 if ((tau2 * tau1 < 0) && (gmm::abs(tau1) < gmm::abs(tau0)))
303 insert_tau_bp_graph(alpha, tau2);
305 if (gmm::abs(tau2 - tau1) < 0.5 * thrvar() * tau_var_ref)
306 delta = std::min(2 * delta, delta_max());
307 else if (gmm::abs(tau2 - tau1) > thrvar() * tau_var_ref)
308 delta = std::max(0.1 * delta, delta_min());
313 set_tau_bp_1(tau_bp_init);
315 return nb_changes % 2;
322 bool newton_corr(VECT &X,
double &Gamma, VECT &tX,
323 double &tGamma,
const VECT &tx,
double tgamma,
325 bool converged =
false;
326 double Delta_Gamma, res(0), diff;
327 VECT f(X), g(X), Delta_X(X), y(X);
329 if (noisy() > 1) cout <<
"Starting correction" << endl;
334 for (it=0; it < maxit() && res < 1.e8; ++it) {
335 F_gamma(X, Gamma, f, g);
336 solve_grad(X, Gamma, Delta_X, y, f, g);
338 Delta_Gamma = sp(tX, Delta_X) / (sp(tX, y) - tGamma);
339 if (isnan(Delta_Gamma)) {
340 if (noisy() > 1) cout <<
"Newton correction failed with NaN" << endl;
343 gmm::add(gmm::scaled(y, -Delta_Gamma), Delta_X);
344 scaled_add(X, Gamma, Delta_X, Delta_Gamma, -1,
357 tGamma = 1. / (tGamma - w_sp(tX, y));
359 scale(tX, tGamma, 1./w_norm(tX, tGamma));
361 diff = w_norm(Delta_X, Delta_Gamma);
363 cout <<
" Correction " << std::setw(3) << it <<
":"
364 <<
" Gamma = " << std::fixed << std::setprecision(6) << Gamma
365 <<
" residual = " << std::scientific << std::setprecision(3) << res
366 <<
" difference = " << std::scientific << std::setprecision(3) << diff
367 <<
" cosang = " << std::fixed << std::setprecision(6)
368 << cosang(tX, tx, tGamma, tgamma) << endl;
370 if (res <= maxres() && diff <= maxdiff()) {
373 compute_tangent(X, Gamma, tX, tGamma);
377 if (noisy() > 1) cout <<
"Correction finished with Gamma = "
382 bool newton_corr(VECT &X,
double &Gamma, VECT &tX,
383 double &tGamma,
const VECT &tx,
double tgamma) {
385 return newton_corr(X, Gamma, tX, tGamma, tx, tgamma, it);
391 bool test_predict_dir(VECT &x,
double &gamma,
392 VECT &tx,
double &tgamma) {
393 bool converged =
false;
394 double h = h_init(), Gamma, tGamma;
398 scaled_add(x, gamma, tx, tgamma, h, X, Gamma);
400 cout <<
"(TPD) Prediction : Gamma = " << Gamma
401 <<
" (for h = " << h <<
", tgamma = " << tgamma <<
")" << endl;
402 copy(tx, tgamma, tX, tGamma);
404 converged = newton_corr(X, Gamma, tX, tGamma, tx, tgamma);
407 h = std::max(0.199 * h_dec() * h, h_min());
413 scaled_add(X, Gamma, x, gamma, -1., tx, tgamma);
414 if (sp(tX, tx, tGamma, tgamma) < 0)
415 scale(tX, tGamma, -1.);
416 copy(X, Gamma, x, gamma);
417 copy(tX, tGamma, tx, tgamma);
424 void treat_smooth_bif_point(
const VECT &x,
double gamma,
425 const VECT &tx,
double tgamma,
double h) {
426 double tau0(get_tau_bp_1()), tau1(get_tau_bp_2());
427 double gamma0(gamma), Gamma,
428 tgamma0(tgamma), tGamma(tgamma), v_gamma;
429 VECT x0(x), X(x), tx0(tx), tX(tx), v_x(tx);
432 cout <<
"Starting locating a bifurcation point" << endl;
435 h *= tau1 / (tau0 - tau1);
436 for (
size_type i=0; i < 10 && (gmm::abs(h) >= h_min()); ++i) {
437 scaled_add(x0, gamma0, tx0, tgamma0, h, X, Gamma);
439 cout <<
"(TSBP) Prediction : Gamma = " << Gamma
440 <<
" (for h = " << h <<
", tgamma = " << tgamma <<
")" << endl;
441 if (newton_corr(X, Gamma, tX, tGamma, tx0, tgamma0)) {
442 copy(X, Gamma, x0, gamma0);
443 if (cosang(tX, tx0, tGamma, tgamma0) >= mincos())
444 copy(tX, tGamma, tx0, tgamma0);
446 tau1 = test_function_bp(X, Gamma, tx0, tgamma0, v_x, v_gamma);
447 h *= tau1 / (tau0 - tau1);
449 scaled_add(x0, gamma0, tx0, tgamma0, h, x0, gamma0);
450 test_function_bp(x0, gamma0, tx0, tgamma0, v_x, v_gamma);
455 cout <<
"Bifurcation point located" << endl;
456 set_sing_point(x0, gamma0);
457 insert_tangent_sing(tx0, tgamma0);
460 cout <<
"Starting searching for the second branch" << endl;
461 double no = w_norm(v_x, v_gamma);
462 scale(v_x, v_gamma, 1./no);
463 if (test_predict_dir(x0, gamma0, v_x, v_gamma)
464 && insert_tangent_sing(v_x, v_gamma))
465 {
if (noisy() > 0) cout <<
"Second branch found" << endl; }
466 else if (noisy() > 0) cout <<
"Second branch not found!" << endl;
478 void treat_nonsmooth_point(
const VECT &x,
double gamma,
479 const VECT &tx,
double tgamma,
bool set_next) {
480 double gamma0(gamma), Gamma(gamma);
481 double tgamma0(tgamma), tGamma(tgamma);
482 double h = h_min(), mcos = mincos();
483 VECT x0(x), X(x), tx0(tx), tX(tx);
487 cout <<
"Starting locating a non-smooth point" << endl;
489 scaled_add(x0, gamma0, tx0, tgamma0, h, X, Gamma);
490 if (newton_corr(X, Gamma, tX, tGamma, tx0, tgamma0)) {
491 double cang = cosang(tX, tx0, tGamma, tgamma0);
492 if (cang >= mcos) mcos = (cang + 1.) / 2.;
495 copy(tx0, tgamma0, tX, tGamma);
498 scaled_add(x0, gamma0, tx0, tgamma0, h, X, Gamma);
500 cout <<
"(TNSBP) Prediction : Gamma = " << Gamma
501 <<
" (for h = " << h <<
", tgamma = " << tgamma <<
")" << endl;
502 if (newton_corr(X, Gamma, tX, tGamma, tx0, tgamma0)
503 && (cosang(tX, tx0, tGamma, tgamma0) >= mcos)) {
504 copy(X, Gamma, x0, gamma0);
505 copy(tX, tGamma, tx0, tgamma0);
507 copy(tx0, tgamma0, tX, tGamma);
512 cout <<
"Non-smooth point located" << endl;
513 set_sing_point(x0, gamma0);
518 cout <<
"Starting a thorough search for different branches" << endl;
519 double tgamma1 = tgamma0, tgamma2 = tgamma0;
520 VECT tx1(tx0), tx2(tx0);
521 scale(tx1, tgamma1, -1.);
522 insert_tangent_sing(tx1, tgamma1);
524 scaled_add(x0, gamma0, tx0, tgamma0, h, X, Gamma);
525 compute_tangent(X, Gamma, tx2, tgamma2);
531 double a, a1, a2, no;
534 for (
size_type i = 0; i < nbdir(); i++) {
535 a = (2 * M_PI * double(i)) /
double(nbdir());
538 scaled_add(tx1, tgamma1, a1, tx2, tgamma2, a2, tX, tGamma);
539 no = w_norm(tX, tGamma);
540 scaled_add(x0, gamma0, tX, tGamma, h/no, X, Gamma);
541 compute_tangent(X, Gamma, tX, tGamma);
543 if (gmm::abs(cosang(tX, tx0, tGamma, tgamma0)) < mincos()
544 || (i == 0 && nspan == 0)) {
545 copy(tX, tGamma, tx0, tgamma0);
546 if (insert_tangent_predict(tX, tGamma)) {
548 cout <<
"New potential tangent vector found, "
549 <<
"trying one predictor-corrector step" << endl;
550 copy(x0, gamma0, X, Gamma);
552 if (test_predict_dir(X, Gamma, tX, tGamma)) {
553 if (insert_tangent_sing(tX, tGamma)) {
554 if ((i == 0) && (nspan == 0)
556 && (gmm::abs(cosang(tX, tx0, tGamma, tgamma0))
557 >= mincos())) { i2 = 1; }
558 if (noisy() > 0) cout <<
"A new branch located (for nspan = "
559 << nspan <<
")" << endl;
560 if (set_next) set_next_point(X, Gamma);
563 copy(x0, gamma0, X, Gamma);
564 copy(tx0, tgamma0, tX, tGamma);
567 scale(tX, tGamma, -1.);
568 if (test_predict_dir(X, Gamma, tX, tGamma)
569 && insert_tangent_sing(tX, tGamma)) {
570 if (noisy() > 0) cout <<
"A new branch located (for nspan = "
571 << nspan <<
")" << endl;
572 if (set_next) set_next_point(X, Gamma);
580 if (i1 + 1 < i2) { ++i1; perturb =
false; }
581 else if(i2 + 1 < nb_tangent_sing())
582 { ++i2; i1 = 0; perturb =
false; }
584 copy(get_tx_sing(i1), get_tgamma_sing(i1), tx1, tgamma1);
585 copy(get_tx_sing(i2), get_tgamma_sing(i2), tx2, tgamma2);
588 tGamma = gmm::random(1.);
589 no = w_norm(tX, tGamma);
590 scaled_add(tx2, tgamma2, tX, tGamma, 0.1/no, tx2, tgamma2);
592 scaled_add(x0, gamma0, tx2, tgamma2, h, X, Gamma);
593 compute_tangent(X, Gamma, tx2, tgamma2);
595 }
while (++nspan < nbspan());
598 cout <<
"Number of branches emanating from the non-smooth point "
599 << nb_tangent_sing() << endl;
603 void init_Moore_Penrose_continuation(
const VECT &x,
604 double gamma, VECT &tx,
605 double &tgamma,
double &h) {
607 tgamma = (tgamma >= 0) ? 1. : -1.;
609 cout <<
"Computing an initial tangent" << endl;
610 compute_tangent(x, gamma, tx, tgamma);
612 if (this->singularities > 0)
613 init_test_functions(x, gamma, tx, tgamma);
619 void Moore_Penrose_continuation(VECT &x,
double &gamma,
620 VECT &tx,
double &tgamma,
621 double &h,
double &h0) {
622 bool converged, new_point =
false, tangent_switched =
false;
624 double tgamma0 = tgamma, Gamma, tGamma;
625 VECT tx0(tx), X(x), tX(x);
627 clear_tau_bp_currentstep();
633 scaled_add(x, gamma, tx, tgamma, h, X, Gamma);
635 cout <<
" Prediction : Gamma = " << Gamma
636 <<
" (for h = " << std::scientific << std::setprecision(3) << h
637 <<
", tgamma = " << tgamma <<
")" << endl;
638 copy(tx, tgamma, tX, tGamma);
641 converged = newton_corr(X, Gamma, tX, tGamma, tx, tgamma, it);
642 double cang(converged ? cosang(tX, tx, tGamma, tgamma) : 0);
644 if (converged && cang >= mincos()) {
646 if (this->singularities > 0) {
647 if (test_limit_point(tGamma)) {
648 set_sing_label(
"limit point");
649 if (noisy() > 0) cout <<
"Limit point detected!" << endl;
651 if (this->singularities > 1) {
653 cout <<
"New point found, computing a test function "
654 <<
"for bifurcations" << endl;
655 if (!tangent_switched) {
656 if (test_smooth_bifurcation(X, Gamma, tX, tGamma)) {
657 set_sing_label(
"smooth bifurcation point");
659 cout <<
"Smooth bifurcation point detected!" << endl;
660 treat_smooth_bif_point(X, Gamma, tX, tGamma, h);
662 }
else if (test_nonsmooth_bifurcation(x, gamma, tx0,
663 tgamma0, X, Gamma, tX,
665 set_sing_label(
"non-smooth bifurcation point");
667 cout <<
"Non-smooth bifurcation point detected!" << endl;
668 treat_nonsmooth_point(x, gamma, tx0, tgamma0,
false);
675 if (step_dec == 0 && it < thrit())
676 h = std::min(h_inc() * h, h_max());
677 }
else if (h > h_min()) {
678 h = std::max(h_dec() * h, h_min());
680 }
else if (this->non_smooth && !tangent_switched) {
682 cout <<
"Classical continuation has failed!" << endl;
683 if (switch_tangent(x, gamma, tx, tgamma, h)) {
684 tangent_switched =
true;
685 step_dec = (h >= h_init()) ? 0 : 1;
687 cout <<
"Restarting the classical continuation" << endl;
690 }
while (!new_point);
693 copy(X, Gamma, x, gamma);
694 copy(tX, tGamma, tx, tgamma);
695 }
else if (this->non_smooth && this->singularities > 1) {
697 treat_nonsmooth_point(x, gamma, tx0, tgamma0,
true);
698 if (gmm::vect_size(get_x_next()) > 0) {
699 if (test_limit_point(tGamma)) {
700 set_sing_label(
"limit point");
701 if (noisy() > 0) cout <<
"Limit point detected!" << endl;
704 cout <<
"Computing a test function for bifurcations"
706 bool bifurcation_detected = (nb_tangent_sing() > 2);
707 if (bifurcation_detected) {
709 set_tau_bp_1(tau_bp_init);
710 set_tau_bp_2(test_function_bp(get_x_next(),
713 get_tgamma_sing(1)));
716 = test_nonsmooth_bifurcation(x, gamma, tx, tgamma,
721 if (bifurcation_detected) {
722 set_sing_label(
"non-smooth bifurcation point");
724 cout <<
"Non-smooth bifurcation point detected!" << endl;
727 copy(get_x_next(), get_gamma_next(), x, gamma);
728 copy(get_tx_sing(1), get_tgamma_sing(1), tx, tgamma);
735 cout <<
"Continuation has failed!" << endl;
740 void Moore_Penrose_continuation(VECT &x,
double &gamma,
741 VECT &tx,
double &tgamma,
double &h) {
743 Moore_Penrose_continuation(x, gamma, tx, tgamma, h, h0);
748 void copy(
const VECT &v1,
const double &a1, VECT &v,
double &a)
const
750 void scale(VECT &v,
double &a,
double c)
const { gmm::scale(v, c); a *= c; }
751 void scaled_add(
const VECT &v1,
const VECT &v2,
double c2, VECT &v)
const
752 {
gmm::add(v1, gmm::scaled(v2, c2), v); }
753 void scaled_add(
const VECT &v1,
double c1,
754 const VECT &v2,
double c2, VECT &v)
const
755 {
gmm::add(gmm::scaled(v1, c1), gmm::scaled(v2, c2), v); }
756 void scaled_add(
const VECT &v1,
const double &a1,
757 const VECT &v2,
const double &a2,
double c2,
758 VECT &v,
double &a)
const
759 {
gmm::add(v1, gmm::scaled(v2, c2), v); a = a1 + c2*a2; }
760 void scaled_add(
const VECT &v1,
const double &a1,
double c1,
761 const VECT &v2,
const double &a2,
double c2,
762 VECT &v,
double &a)
const {
763 gmm::add(gmm::scaled(v1, c1), gmm::scaled(v2, c2), v);
766 void scaled_add(
const MAT &m1,
double c1,
767 const MAT &m2,
double c2, MAT &m)
const
768 {
gmm::add(gmm::scaled(m1, c1), gmm::scaled(m2, c2), m); }
769 void mult(
const MAT &A,
const VECT &v1, VECT &v)
const
772 double norm(
const VECT &v)
const
775 double sp(
const VECT &v1,
const VECT &v2)
const
777 double sp(
const VECT &v1,
const VECT &v2,
double w1,
double w2)
const
778 {
return sp(v1, v2) + w1 * w2; }
780 virtual double intrv_sp(
const VECT &v1,
const VECT &v2)
const = 0;
782 double w_sp(
const VECT &v1,
const VECT &v2)
const
783 {
return scfac * intrv_sp(v1, v2); }
784 double w_sp(
const VECT &v1,
const VECT &v2,
double w1,
double w2)
const
785 {
return w_sp(v1, v2) + w1 * w2; }
786 double w_norm(
const VECT &v,
double w)
const
787 {
return sqrt(w_sp(v, v) + w * w); }
789 double cosang(
const VECT &v1,
const VECT &v2)
const {
790 double no = sqrt(intrv_sp(v1, v1) * intrv_sp(v2, v2));
791 return (no == 0) ? 0: intrv_sp(v1, v2) / no;
793 double cosang(
const VECT &v1,
const VECT &v2,
double w1,
double w2)
const {
798 double no = sqrt((intrv_sp(v1, v1) + w1*w1)*
799 (intrv_sp(v2, v2) + w2*w2));
800 return (no == 0) ? 0 : (intrv_sp(v1, v2) + w1*w2) / no;
806 int noisy()
const {
return noisy_; }
807 double h_init()
const {
return h_init_; }
808 double h_min()
const {
return h_min_; }
809 double h_max()
const {
return h_max_; }
810 double h_dec()
const {
return h_dec_; }
811 double h_inc()
const {
return h_inc_; }
812 size_type maxit()
const {
return maxit_; }
813 size_type thrit()
const {
return thrit_; }
814 double maxres()
const {
return maxres_; }
815 double maxdiff()
const {
return maxdiff_; }
816 double mincos()
const {
return mincos_; }
817 double delta_max()
const {
return delta_max_; }
818 double delta_min()
const {
return delta_min_; }
819 double thrvar()
const {
return thrvar_; }
820 size_type nbdir()
const {
return nbdir_; }
821 size_type nbspan()
const {
return nbspan_; }
823 void set_tau_lp(
double tau) { tau_lp = tau; }
824 double get_tau_lp()
const {
return tau_lp; }
825 void set_tau_bp_1(
double tau) { tau_bp_1 = tau; }
826 double get_tau_bp_1()
const {
return tau_bp_1; }
827 void set_tau_bp_2(
double tau) { tau_bp_2 = tau; }
828 double get_tau_bp_2()
const {
return tau_bp_2; }
829 void clear_tau_bp_currentstep() {
830 tau_bp_graph.clear();
832 void init_tau_bp_graph() { tau_bp_graph[0.] = tau_bp_2; }
833 void insert_tau_bp_graph(
double alpha,
double tau) {
834 tau_bp_graph[
alpha] = tau;
838 const VECT &get_alpha_hist() {
841 for (std::map<double, double>::iterator it = tau_bp_graph.begin();
842 it != tau_bp_graph.end(); it++) {
843 alpha_hist[i] = (*it).first; i++;
847 const VECT &get_tau_bp_hist() {
850 for (std::map<double, double>::iterator it = tau_bp_graph.begin();
851 it != tau_bp_graph.end(); it++) {
852 tau_bp_hist[i] = (*it).second; i++;
857 void clear_sing_data() {
864 tgamma_predict.clear();
866 void set_sing_label(std::string label) { sing_label = label; }
867 const std::string get_sing_label()
const {
return sing_label; }
868 void set_sing_point(
const VECT &x,
double gamma) {
870 copy(x, gamma, x_sing, gamma_sing);
872 const VECT &get_x_sing()
const {
return x_sing; }
873 double get_gamma_sing()
const {
return gamma_sing; }
874 size_type nb_tangent_sing()
const {
return tx_sing.size(); }
875 bool insert_tangent_sing(
const VECT &tx,
double tgamma){
876 bool is_included =
false;
877 for (
size_type i = 0; (i < tx_sing.size()) && (!is_included); ++i) {
878 double cang = cosang(tx_sing[i], tx, tgamma_sing[i], tgamma);
879 is_included = (cang >= mincos_);
882 tx_sing.push_back(tx);
883 tgamma_sing.push_back(tgamma);
887 const VECT &get_tx_sing(
size_type i)
const {
return tx_sing[i]; }
888 double get_tgamma_sing(
size_type i)
const {
return tgamma_sing[i]; }
889 const std::vector<VECT> &get_tx_sing()
const {
return tx_sing; }
890 const std::vector<double> &get_tgamma_sing()
const {
return tgamma_sing; }
892 void set_next_point(
const VECT &x,
double gamma) {
893 if (gmm::vect_size(x_next) == 0) {
895 copy(x, gamma, x_next, gamma_next);
898 const VECT &get_x_next()
const {
return x_next; }
899 double get_gamma_next()
const {
return gamma_next; }
901 bool insert_tangent_predict(
const VECT &tx,
double tgamma) {
902 bool is_included =
false;
903 for (
size_type i = 0; (i < tx_predict.size()) && (!is_included); ++i) {
904 double cang = gmm::abs(cosang(tx_predict[i], tx, tgamma_predict[i], tgamma));
905 is_included = (cang >= mincos_);
908 tx_predict.push_back(tx);
909 tgamma_predict.push_back(tgamma);
915 srand(
unsigned(time(NULL)));
918 bb_gamma = gmm::random(1.)/scalar_type(nbdof);
919 cc_gamma = gmm::random(1.)/scalar_type(nbdof);
920 dd = gmm::random(1.)/scalar_type(nbdof);
921 gmm::scale(bb_x_, scalar_type(1)/scalar_type(nbdof));
922 gmm::scale(cc_x_, scalar_type(1)/scalar_type(nbdof));
928 {
if (gmm::vect_size(bb_x_) != nbdof) init_border(nbdof);
return bb_x_; }
930 {
if (gmm::vect_size(cc_x_) != nbdof) init_border(nbdof);
return cc_x_; }
934 return (this->singularities == 0) ? 0
935 : (2 * gmm::vect_size(bb_x_) * szd
936 + 4 * gmm::vect_size(get_tau_bp_hist()) * szd
937 + (1 + nb_tangent_sing()) * gmm::vect_size(get_x_sing()) * szd);
943 virtual void solve(
const MAT &A, VECT &g,
const VECT &L)
const = 0;
945 virtual void solve(
const MAT &A, VECT &g1, VECT &g2,
946 const VECT &L1,
const VECT &L2)
const = 0;
948 virtual void F(
const VECT &x,
double gamma, VECT &f)
const = 0;
950 virtual void F_gamma(
const VECT &x,
double gamma,
const VECT &f0,
953 virtual void F_gamma(
const VECT &x,
double gamma, VECT &g)
const = 0;
955 virtual void F_x(
const VECT &x,
double gamma, MAT &A)
const = 0;
957 virtual void solve_grad(
const VECT &x,
double gamma,
958 VECT &g,
const VECT &L)
const = 0;
960 virtual void solve_grad(
const VECT &x,
double gamma, VECT &g1,
961 VECT &g2,
const VECT &L1,
const VECT &L2)
const = 0;
963 virtual void mult_grad(
const VECT &x,
double gamma,
964 const VECT &w, VECT &y)
const = 0;
969 (
int sing = 0,
bool nonsm =
false,
double sfac=0.,
970 double hin = 1.e-2,
double hmax = 1.e-1,
double hmin = 1.e-5,
971 double hinc = 1.3,
double hdec = 0.5,
973 double mres = 1.e-6,
double mdiff = 1.e-6,
double mcos = 0.9,
974 double dmax = 0.005,
double dmin = 0.00012,
double tvar = 0.02,
976 : singularities(sing), non_smooth(nonsm), scfac(sfac),
977 h_init_(hin), h_max_(hmax), h_min_(hmin), h_inc_(hinc), h_dec_(hdec),
978 maxit_(mit), thrit_(tit), maxres_(mres), maxdiff_(mdiff), mincos_(mcos),
979 delta_max_(dmax), delta_min_(dmin), thrvar_(tvar),
980 nbdir_(ndir), nbspan_(nspan), noisy_(noi),
981 tau_lp(0.), tau_bp_1(tau_bp_init), tau_bp_2(tau_bp_init),
982 gamma_sing(0.), gamma_next(0.)
984 virtual ~virtual_cont_struct() {}
998 #ifdef GETFEM_MODELS_H__
1000 class cont_struct_getfem_model
1001 :
public virtual_cont_struct<base_vector, model_real_sparse_matrix>,
1006 std::string parameter_name;
1007 std::string initdata_name, finaldata_name, currentdata_name;
1008 gmm::sub_interval I;
1009 rmodel_plsolver_type lsolver;
1010 double maxres_solve;
1012 void set_variables(
const base_vector &x,
double gamma)
const;
1013 void update_matrix(
const base_vector &x,
double gamma)
const;
1017 double intrv_sp(
const base_vector &v1,
const base_vector &v2)
const {
1018 return (I.size() > 0) ?
gmm::vect_sp(gmm::sub_vector(v1,I),
1019 gmm::sub_vector(v2,I))
1024 void solve(
const model_real_sparse_matrix &A, base_vector &g,
const base_vector &L)
const;
1026 void solve(
const model_real_sparse_matrix &A, base_vector &g1, base_vector &g2,
1027 const base_vector &L1,
const base_vector &L2)
const;
1029 void F(
const base_vector &x,
double gamma, base_vector &f)
const;
1031 void F_gamma(
const base_vector &x,
double gamma,
const base_vector &f0,
1032 base_vector &g)
const;
1034 void F_gamma(
const base_vector &x,
double gamma, base_vector &g)
const;
1037 void F_x(
const base_vector &x,
double gamma, model_real_sparse_matrix &A)
const;
1039 void solve_grad(
const base_vector &x,
double gamma,
1040 base_vector &g,
const base_vector &L)
const;
1042 void solve_grad(
const base_vector &x,
double gamma, base_vector &g1,
1044 const base_vector &L1,
const base_vector &L2)
const;
1046 void mult_grad(
const base_vector &x,
double gamma,
1047 const base_vector &w, base_vector &y)
const;
1051 const model &linked_model() {
return *md; }
1053 void set_parametrised_data_names
1054 (
const std::string &in,
const std::string &fn,
const std::string &cn) {
1056 finaldata_name = fn;
1057 currentdata_name = cn;
1060 void set_interval_from_variable_name(
const std::string &varname) {
1061 if (varname ==
"") I = gmm::sub_interval(0,0);
1062 else I = md->interval_of_variable(varname);
1065 cont_struct_getfem_model
1066 (model &md_,
const std::string &pn,
double sfac, rmodel_plsolver_type ls,
1067 double hin = 1.e-2,
double hmax = 1.e-1,
double hmin = 1.e-5,
1068 double hinc = 1.3,
double hdec = 0.5,
size_type mit = 10,
1069 size_type tit = 4,
double mres = 1.e-6,
double mdiff = 1.e-6,
1070 double mcos = 0.9,
double mress = 1.e-8,
int noi = 0,
int sing = 0,
1071 bool nonsm =
false,
double dmax = 0.005,
double dmin = 0.00012,
1073 : virtual_cont_struct(sing, nonsm, sfac, hin, hmax, hmin, hinc, hdec,
1074 mit, tit, mres, mdiff, mcos, dmax, dmin, tvar,
1076 md(&md_), parameter_name(pn),
1077 initdata_name(
""), finaldata_name(
""), currentdata_name(
""),
1078 I(0,0), lsolver(ls), maxres_solve(mress)
1080 GMM_ASSERT1(!md->is_complex(),
1081 "Continuation has only a real version, sorry.");
base class for static stored objects
Standard solvers for model bricks.
void copy(const L1 &l1, L2 &l2)
*/
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.
void resize(V &v, size_type n)
*/
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
strongest_value_type< V1, V2 >::value_type vect_sp(const V1 &v1, const V2 &v2)
*/
void add(const L1 &l1, L2 &l2)
*/
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.