38 #ifndef GETFEM_CONTINUATION_H__
39 #define GETFEM_CONTINUATION_H__
50 template <
typename VECT,
typename MAT>
51 class virtual_cont_struct {
55 const double tau_bp_init = 1.e6;
56 const double diffeps = 1.e-8;
58 static constexpr
double tau_bp_init = 1.e6;
59 static constexpr
double diffeps = 1.e-8;
67 double scfac, h_init_, h_max_, h_min_, h_inc_, h_dec_;
69 double maxres_, maxdiff_, mincos_, delta_max_, delta_min_, thrvar_;
72 double tau_lp, tau_bp_1, tau_bp_2;
75 std::map<double, double> tau_bp_graph;
76 VECT alpha_hist, tau_bp_hist;
77 std::string sing_label;
79 double gamma_sing, gamma_next;
80 std::vector<VECT> tx_sing, tx_predict;
81 std::vector<double> tgamma_sing, tgamma_predict;
85 double bb_gamma, cc_gamma, dd;
90 void compute_tangent(
const VECT &x,
double gamma,
91 VECT &tx,
double &tgamma) {
94 solve_grad(x, gamma, y, g);
95 tgamma = 1. / (tgamma - w_sp(tx, y));
98 scale(tx, tgamma, 1./w_norm(tx, tgamma));
100 mult_grad(x, gamma, tx, y);
101 gmm::add(gmm::scaled(g, tgamma), y);
104 GMM_WARNING2(
"Tangent computed with the residual " << r);
112 bool test_tangent(
const VECT &x,
double gamma,
113 const VECT &tX,
double tGamma,
114 const VECT &tx,
double tgamma,
double h) {
116 double Gamma1, tGamma1(tgamma);
119 scaled_add(x, gamma, tX, tGamma, h, X1, Gamma1);
120 compute_tangent(X1, Gamma1, tX1, tGamma1);
122 double cang = cosang(tX1, tX, tGamma1, tGamma);
124 cout <<
"cos of the angle with the tested tangent " << cang << endl;
125 if (cang >= mincos())
128 cang = cosang(tX1, tx, tGamma1, tGamma);
130 cout <<
"cos of the angle with the initial tangent " << cang << endl;
136 bool switch_tangent(
const VECT &x,
double gamma,
137 VECT &tx,
double &tgamma,
double &h) {
138 double Gamma, tGamma(tgamma);
141 if (noisy() > 0) cout <<
"Trying a simple tangent switch" << endl;
142 if (noisy() > 1) cout <<
"Computing a new tangent" << endl;
144 scaled_add(x, gamma, tx, tgamma, h, X, Gamma);
145 compute_tangent(X, Gamma, tX, tGamma);
151 cout <<
"Starting testing the computed tangent" << endl;
152 double h_test = -0.9 * h_min();
153 bool accepted(
false);
154 while (!accepted && (h_test > -h_max())) {
156 + pow(10., floor(log10(-h_test / h_min()))) * h_min();
157 accepted = test_tangent(x, gamma, tX, tGamma, tx, tgamma, h_test);
160 accepted = test_tangent(x, gamma, tX, tGamma, tx, tgamma, h_test);
171 cout <<
"Tangent direction switched, "
172 <<
"starting computing a suitable step size" << endl;
174 bool h_adapted =
false;
175 while (!h_adapted && (h > h_test)) {
176 h_adapted = test_tangent(x, gamma, tX, tGamma, tx, tgamma, h);
179 h = h_adapted ? h / h_dec() : h_test;
180 copy(tX, tGamma, tx, tgamma);
182 if (noisy() > 0) cout <<
"Simple tangent switch has failed!" << endl;
188 bool test_limit_point(
double tgamma) {
189 double tau_lp_old = get_tau_lp();
191 return (tgamma * tau_lp_old < 0);
194 void init_test_functions(
const VECT &x,
double gamma,
195 const VECT &tx,
double tgamma) {
197 if (this->singularities > 1) {
198 if (noisy() > 1) cout <<
"Computing an initial value of the "
199 <<
"test function for bifurcations" << endl;
200 set_tau_bp_2(test_function_bp(x, gamma, tx, tgamma));
207 double test_function_bp(
const MAT &A,
const VECT &g,
208 const VECT &tx,
double tgamma,
209 VECT &v_x,
double &v_gamma) {
213 solve(A, y, z, g, bb_x(nn));
214 v_gamma = (bb_gamma - sp(tx, z)) / (tgamma - sp(tx, y));
215 scaled_add(z, y, -v_gamma, v_x);
216 double tau = 1. / (dd - sp(cc_x(nn), v_x) - cc_gamma * v_gamma);
217 scale(v_x, v_gamma, -tau);
221 gmm::add(gmm::scaled(g, v_gamma), y);
222 gmm::add(gmm::scaled(bb_x(nn), tau), y);
223 double r = sp(tx, v_x) + tgamma * v_gamma + bb_gamma * tau;
224 double q = sp(cc_x(nn), v_x) + cc_gamma * v_gamma + dd * tau - 1.;
225 r = sqrt(sp(y, y) + r * r + q * q);
227 GMM_WARNING2(
"Test function evaluated with the residual " << r);
232 double test_function_bp(
const MAT &A,
const VECT &g,
233 const VECT &tx,
double tgamma) {
236 return test_function_bp(A, g, tx, tgamma, v_x, v_gamma);
241 double test_function_bp(
const VECT &x,
double gamma,
242 const VECT &tx,
double tgamma,
243 VECT &v_x,
double &v_gamma) {
246 F_gamma(x, gamma, g);
247 return test_function_bp(A, g, tx, tgamma, v_x, v_gamma);
250 double test_function_bp(
const VECT &x,
double gamma,
251 const VECT &tx,
double tgamma) {
254 return test_function_bp(x, gamma, tx, tgamma, v_x, v_gamma);
259 bool test_smooth_bifurcation(
const VECT &x,
double gamma,
260 const VECT &tx,
double tgamma) {
261 double tau_bp_1_old = get_tau_bp_1();
262 set_tau_bp_1(get_tau_bp_2());
263 set_tau_bp_2(test_function_bp(x, gamma, tx, tgamma));
264 return (get_tau_bp_2() * get_tau_bp_1() < 0) &&
265 (gmm::abs(get_tau_bp_1()) < gmm::abs(tau_bp_1_old));
269 bool test_nonsmooth_bifurcation(
const VECT &x1,
double gamma1,
270 const VECT &tx1,
double tgamma1,
271 const VECT &x2,
double gamma2,
272 const VECT &tx2,
double tgamma2) {
273 VECT g1(x1), g2(x1), g(x1), tx(x1);
278 F_gamma(x2, gamma2, g2);
280 F_gamma(x1, gamma1, g1);
281 double tau1 = test_function_bp(A1, g1, tx1, tgamma1);
282 double tau2 = test_function_bp(A2, g2, tx2, tgamma2);
283 double tau_var_ref = std::max(gmm::abs(tau2 - tau1), 1.e-8);
291 double delta = delta_min(), tau0 = tau_bp_init, tgamma;
292 for (
double alpha=0.;
alpha < 1.; ) {
293 alpha = std::min(alpha + delta, 1.);
294 scaled_add(A1, 1.-alpha, A2, alpha, A);
295 scaled_add(g1, 1.-alpha, g2, alpha, g);
296 scaled_add(tx1, tgamma1, 1.-alpha, tx2, tgamma2, alpha, tx, tgamma);
299 tau2 = test_function_bp(A, g, tx, tgamma);
300 if ((tau2 * tau1 < 0) && (gmm::abs(tau1) < gmm::abs(tau0)))
302 insert_tau_bp_graph(alpha, tau2);
304 if (gmm::abs(tau2 - tau1) < 0.5 * thrvar() * tau_var_ref)
305 delta = std::min(2 * delta, delta_max());
306 else if (gmm::abs(tau2 - tau1) > thrvar() * tau_var_ref)
307 delta = std::max(0.1 * delta, delta_min());
312 set_tau_bp_1(tau_bp_init);
314 return nb_changes % 2;
321 bool newton_corr(VECT &X,
double &Gamma, VECT &tX,
322 double &tGamma,
const VECT &tx,
double tgamma,
324 bool converged =
false;
325 double Delta_Gamma, res(0), diff;
326 VECT f(X), g(X), Delta_X(X), y(X);
328 if (noisy() > 1) cout <<
"Starting correction" << endl;
333 for (it=0; it < maxit() && res < 1.e8; ++it) {
334 F_gamma(X, Gamma, f, g);
335 solve_grad(X, Gamma, Delta_X, y, f, g);
337 Delta_Gamma = sp(tX, Delta_X) / (sp(tX, y) - tGamma);
338 if (isnan(Delta_Gamma)) {
339 if (noisy() > 1) cout <<
"Newton correction failed with NaN" << endl;
342 gmm::add(gmm::scaled(y, -Delta_Gamma), Delta_X);
343 scaled_add(X, Gamma, Delta_X, Delta_Gamma, -1,
356 tGamma = 1. / (tGamma - w_sp(tX, y));
358 scale(tX, tGamma, 1./w_norm(tX, tGamma));
360 diff = w_norm(Delta_X, Delta_Gamma);
362 cout <<
" Correction " << std::setw(3) << it <<
":"
363 <<
" Gamma = " << std::fixed << std::setprecision(6) << Gamma
364 <<
" residual = " << std::scientific << std::setprecision(3) << res
365 <<
" difference = " << std::scientific << std::setprecision(3) << diff
366 <<
" cosang = " << std::fixed << std::setprecision(6)
367 << cosang(tX, tx, tGamma, tgamma) << endl;
369 if (res <= maxres() && diff <= maxdiff()) {
372 compute_tangent(X, Gamma, tX, tGamma);
376 if (noisy() > 1) cout <<
"Correction finished with Gamma = "
381 bool newton_corr(VECT &X,
double &Gamma, VECT &tX,
382 double &tGamma,
const VECT &tx,
double tgamma) {
384 return newton_corr(X, Gamma, tX, tGamma, tx, tgamma, it);
390 bool test_predict_dir(VECT &x,
double &gamma,
391 VECT &tx,
double &tgamma) {
392 bool converged =
false;
393 double h = h_init(), Gamma, tGamma;
397 scaled_add(x, gamma, tx, tgamma, h, X, Gamma);
399 cout <<
"(TPD) Prediction : Gamma = " << Gamma
400 <<
" (for h = " << h <<
", tgamma = " << tgamma <<
")" << endl;
401 copy(tx, tgamma, tX, tGamma);
403 converged = newton_corr(X, Gamma, tX, tGamma, tx, tgamma);
406 h = std::max(0.199 * h_dec() * h, h_min());
412 scaled_add(X, Gamma, x, gamma, -1., tx, tgamma);
413 if (sp(tX, tx, tGamma, tgamma) < 0)
414 scale(tX, tGamma, -1.);
415 copy(X, Gamma, x, gamma);
416 copy(tX, tGamma, tx, tgamma);
423 void treat_smooth_bif_point(
const VECT &x,
double gamma,
424 const VECT &tx,
double tgamma,
double h) {
425 double tau0(get_tau_bp_1()), tau1(get_tau_bp_2());
426 double gamma0(gamma), Gamma,
427 tgamma0(tgamma), tGamma(tgamma), v_gamma;
428 VECT x0(x), X(x), tx0(tx), tX(tx), v_x(tx);
431 cout <<
"Starting locating a bifurcation point" << endl;
434 h *= tau1 / (tau0 - tau1);
435 for (
size_type i=0; i < 10 && (gmm::abs(h) >= h_min()); ++i) {
436 scaled_add(x0, gamma0, tx0, tgamma0, h, X, Gamma);
438 cout <<
"(TSBP) Prediction : Gamma = " << Gamma
439 <<
" (for h = " << h <<
", tgamma = " << tgamma <<
")" << endl;
440 if (newton_corr(X, Gamma, tX, tGamma, tx0, tgamma0)) {
441 copy(X, Gamma, x0, gamma0);
442 if (cosang(tX, tx0, tGamma, tgamma0) >= mincos())
443 copy(tX, tGamma, tx0, tgamma0);
445 tau1 = test_function_bp(X, Gamma, tx0, tgamma0, v_x, v_gamma);
446 h *= tau1 / (tau0 - tau1);
448 scaled_add(x0, gamma0, tx0, tgamma0, h, x0, gamma0);
449 test_function_bp(x0, gamma0, tx0, tgamma0, v_x, v_gamma);
454 cout <<
"Bifurcation point located" << endl;
455 set_sing_point(x0, gamma0);
456 insert_tangent_sing(tx0, tgamma0);
459 cout <<
"Starting searching for the second branch" << endl;
460 double no = w_norm(v_x, v_gamma);
461 scale(v_x, v_gamma, 1./no);
462 if (test_predict_dir(x0, gamma0, v_x, v_gamma)
463 && insert_tangent_sing(v_x, v_gamma))
464 {
if (noisy() > 0) cout <<
"Second branch found" << endl; }
465 else if (noisy() > 0) cout <<
"Second branch not found!" << endl;
477 void treat_nonsmooth_point(
const VECT &x,
double gamma,
478 const VECT &tx,
double tgamma,
bool set_next) {
479 double gamma0(gamma), Gamma(gamma);
480 double tgamma0(tgamma), tGamma(tgamma);
481 double h = h_min(), mcos = mincos();
482 VECT x0(x), X(x), tx0(tx), tX(tx);
486 cout <<
"Starting locating a non-smooth point" << endl;
488 scaled_add(x0, gamma0, tx0, tgamma0, h, X, Gamma);
489 if (newton_corr(X, Gamma, tX, tGamma, tx0, tgamma0)) {
490 double cang = cosang(tX, tx0, tGamma, tgamma0);
491 if (cang >= mcos) mcos = (cang + 1.) / 2.;
494 copy(tx0, tgamma0, tX, tGamma);
497 scaled_add(x0, gamma0, tx0, tgamma0, h, X, Gamma);
499 cout <<
"(TNSBP) Prediction : Gamma = " << Gamma
500 <<
" (for h = " << h <<
", tgamma = " << tgamma <<
")" << endl;
501 if (newton_corr(X, Gamma, tX, tGamma, tx0, tgamma0)
502 && (cosang(tX, tx0, tGamma, tgamma0) >= mcos)) {
503 copy(X, Gamma, x0, gamma0);
504 copy(tX, tGamma, tx0, tgamma0);
506 copy(tx0, tgamma0, tX, tGamma);
511 cout <<
"Non-smooth point located" << endl;
512 set_sing_point(x0, gamma0);
517 cout <<
"Starting a thorough search for different branches" << endl;
518 double tgamma1 = tgamma0, tgamma2 = tgamma0;
519 VECT tx1(tx0), tx2(tx0);
520 scale(tx1, tgamma1, -1.);
521 insert_tangent_sing(tx1, tgamma1);
523 scaled_add(x0, gamma0, tx0, tgamma0, h, X, Gamma);
524 compute_tangent(X, Gamma, tx2, tgamma2);
530 double a, a1, a2, no;
533 for (
size_type i = 0; i < nbdir(); i++) {
534 a = (2 * M_PI * double(i)) /
double(nbdir());
537 scaled_add(tx1, tgamma1, a1, tx2, tgamma2, a2, tX, tGamma);
538 no = w_norm(tX, tGamma);
539 scaled_add(x0, gamma0, tX, tGamma, h/no, X, Gamma);
540 compute_tangent(X, Gamma, tX, tGamma);
542 if (gmm::abs(cosang(tX, tx0, tGamma, tgamma0)) < mincos()
543 || (i == 0 && nspan == 0)) {
544 copy(tX, tGamma, tx0, tgamma0);
545 if (insert_tangent_predict(tX, tGamma)) {
547 cout <<
"New potential tangent vector found, "
548 <<
"trying one predictor-corrector step" << endl;
549 copy(x0, gamma0, X, Gamma);
551 if (test_predict_dir(X, Gamma, tX, tGamma)) {
552 if (insert_tangent_sing(tX, tGamma)) {
553 if ((i == 0) && (nspan == 0)
555 && (gmm::abs(cosang(tX, tx0, tGamma, tgamma0))
556 >= mincos())) { i2 = 1; }
557 if (noisy() > 0) cout <<
"A new branch located (for nspan = "
558 << nspan <<
")" << endl;
559 if (set_next) set_next_point(X, Gamma);
562 copy(x0, gamma0, X, Gamma);
563 copy(tx0, tgamma0, tX, tGamma);
566 scale(tX, tGamma, -1.);
567 if (test_predict_dir(X, Gamma, tX, tGamma)
568 && insert_tangent_sing(tX, tGamma)) {
569 if (noisy() > 0) cout <<
"A new branch located (for nspan = "
570 << nspan <<
")" << endl;
571 if (set_next) set_next_point(X, Gamma);
579 if (i1 + 1 < i2) { ++i1; perturb =
false; }
580 else if(i2 + 1 < nb_tangent_sing())
581 { ++i2; i1 = 0; perturb =
false; }
583 copy(get_tx_sing(i1), get_tgamma_sing(i1), tx1, tgamma1);
584 copy(get_tx_sing(i2), get_tgamma_sing(i2), tx2, tgamma2);
587 tGamma = gmm::random(1.);
588 no = w_norm(tX, tGamma);
589 scaled_add(tx2, tgamma2, tX, tGamma, 0.1/no, tx2, tgamma2);
591 scaled_add(x0, gamma0, tx2, tgamma2, h, X, Gamma);
592 compute_tangent(X, Gamma, tx2, tgamma2);
594 }
while (++nspan < nbspan());
597 cout <<
"Number of branches emanating from the non-smooth point "
598 << nb_tangent_sing() << endl;
602 void init_Moore_Penrose_continuation(
const VECT &x,
603 double gamma, VECT &tx,
604 double &tgamma,
double &h) {
606 tgamma = (tgamma >= 0) ? 1. : -1.;
608 cout <<
"Computing an initial tangent" << endl;
609 compute_tangent(x, gamma, tx, tgamma);
611 if (this->singularities > 0)
612 init_test_functions(x, gamma, tx, tgamma);
618 void Moore_Penrose_continuation(VECT &x,
double &gamma,
619 VECT &tx,
double &tgamma,
620 double &h,
double &h0) {
621 bool converged, new_point =
false, tangent_switched =
false;
623 double tgamma0 = tgamma, Gamma, tGamma;
624 VECT tx0(tx), X(x), tX(x);
626 clear_tau_bp_currentstep();
632 scaled_add(x, gamma, tx, tgamma, h, X, Gamma);
634 cout <<
" Prediction : Gamma = " << Gamma
635 <<
" (for h = " << std::scientific << std::setprecision(3) << h
636 <<
", tgamma = " << tgamma <<
")" << endl;
637 copy(tx, tgamma, tX, tGamma);
640 converged = newton_corr(X, Gamma, tX, tGamma, tx, tgamma, it);
641 double cang(converged ? cosang(tX, tx, tGamma, tgamma) : 0);
643 if (converged && cang >= mincos()) {
645 if (this->singularities > 0) {
646 if (test_limit_point(tGamma)) {
647 set_sing_label(
"limit point");
648 if (noisy() > 0) cout <<
"Limit point detected!" << endl;
650 if (this->singularities > 1) {
652 cout <<
"New point found, computing a test function "
653 <<
"for bifurcations" << endl;
654 if (!tangent_switched) {
655 if (test_smooth_bifurcation(X, Gamma, tX, tGamma)) {
656 set_sing_label(
"smooth bifurcation point");
658 cout <<
"Smooth bifurcation point detected!" << endl;
659 treat_smooth_bif_point(X, Gamma, tX, tGamma, h);
661 }
else if (test_nonsmooth_bifurcation(x, gamma, tx0,
662 tgamma0, X, Gamma, tX,
664 set_sing_label(
"non-smooth bifurcation point");
666 cout <<
"Non-smooth bifurcation point detected!" << endl;
667 treat_nonsmooth_point(x, gamma, tx0, tgamma0,
false);
674 if (step_dec == 0 && it < thrit())
675 h = std::min(h_inc() * h, h_max());
676 }
else if (h > h_min()) {
677 h = std::max(h_dec() * h, h_min());
679 }
else if (this->non_smooth && !tangent_switched) {
681 cout <<
"Classical continuation has failed!" << endl;
682 if (switch_tangent(x, gamma, tx, tgamma, h)) {
683 tangent_switched =
true;
684 step_dec = (h >= h_init()) ? 0 : 1;
686 cout <<
"Restarting the classical continuation" << endl;
689 }
while (!new_point);
692 copy(X, Gamma, x, gamma);
693 copy(tX, tGamma, tx, tgamma);
694 }
else if (this->non_smooth && this->singularities > 1) {
696 treat_nonsmooth_point(x, gamma, tx0, tgamma0,
true);
697 if (gmm::vect_size(get_x_next()) > 0) {
698 if (test_limit_point(tGamma)) {
699 set_sing_label(
"limit point");
700 if (noisy() > 0) cout <<
"Limit point detected!" << endl;
703 cout <<
"Computing a test function for bifurcations"
705 bool bifurcation_detected = (nb_tangent_sing() > 2);
706 if (bifurcation_detected) {
708 set_tau_bp_1(tau_bp_init);
709 set_tau_bp_2(test_function_bp(get_x_next(),
712 get_tgamma_sing(1)));
715 = test_nonsmooth_bifurcation(x, gamma, tx, tgamma,
720 if (bifurcation_detected) {
721 set_sing_label(
"non-smooth bifurcation point");
723 cout <<
"Non-smooth bifurcation point detected!" << endl;
726 copy(get_x_next(), get_gamma_next(), x, gamma);
727 copy(get_tx_sing(1), get_tgamma_sing(1), tx, tgamma);
734 cout <<
"Continuation has failed!" << endl;
739 void Moore_Penrose_continuation(VECT &x,
double &gamma,
740 VECT &tx,
double &tgamma,
double &h) {
742 Moore_Penrose_continuation(x, gamma, tx, tgamma, h, h0);
747 void copy(
const VECT &v1,
const double &a1, VECT &v,
double &a)
const
749 void scale(VECT &v,
double &a,
double c)
const { gmm::scale(v, c); a *= c; }
750 void scaled_add(
const VECT &v1,
const VECT &v2,
double c2, VECT &v)
const
751 {
gmm::add(v1, gmm::scaled(v2, c2), v); }
752 void scaled_add(
const VECT &v1,
double c1,
753 const VECT &v2,
double c2, VECT &v)
const
754 {
gmm::add(gmm::scaled(v1, c1), gmm::scaled(v2, c2), v); }
755 void scaled_add(
const VECT &v1,
const double &a1,
756 const VECT &v2,
const double &a2,
double c2,
757 VECT &v,
double &a)
const
758 {
gmm::add(v1, gmm::scaled(v2, c2), v); a = a1 + c2*a2; }
759 void scaled_add(
const VECT &v1,
const double &a1,
double c1,
760 const VECT &v2,
const double &a2,
double c2,
761 VECT &v,
double &a)
const {
762 gmm::add(gmm::scaled(v1, c1), gmm::scaled(v2, c2), v);
765 void scaled_add(
const MAT &m1,
double c1,
766 const MAT &m2,
double c2, MAT &m)
const
767 {
gmm::add(gmm::scaled(m1, c1), gmm::scaled(m2, c2), m); }
768 void mult(
const MAT &A,
const VECT &v1, VECT &v)
const
771 double norm(
const VECT &v)
const
774 double sp(
const VECT &v1,
const VECT &v2)
const
776 double sp(
const VECT &v1,
const VECT &v2,
double w1,
double w2)
const
777 {
return sp(v1, v2) + w1 * w2; }
779 virtual double intrv_sp(
const VECT &v1,
const VECT &v2)
const = 0;
781 double w_sp(
const VECT &v1,
const VECT &v2)
const
782 {
return scfac * intrv_sp(v1, v2); }
783 double w_sp(
const VECT &v1,
const VECT &v2,
double w1,
double w2)
const
784 {
return w_sp(v1, v2) + w1 * w2; }
785 double w_norm(
const VECT &v,
double w)
const
786 {
return sqrt(w_sp(v, v) + w * w); }
788 double cosang(
const VECT &v1,
const VECT &v2)
const {
789 double no = sqrt(intrv_sp(v1, v1) * intrv_sp(v2, v2));
790 return (no == 0) ? 0: intrv_sp(v1, v2) / no;
792 double cosang(
const VECT &v1,
const VECT &v2,
double w1,
double w2)
const {
797 double no = sqrt((intrv_sp(v1, v1) + w1*w1)*
798 (intrv_sp(v2, v2) + w2*w2));
799 return (no == 0) ? 0 : (intrv_sp(v1, v2) + w1*w2) / no;
805 int noisy()
const {
return noisy_; }
806 double h_init()
const {
return h_init_; }
807 double h_min()
const {
return h_min_; }
808 double h_max()
const {
return h_max_; }
809 double h_dec()
const {
return h_dec_; }
810 double h_inc()
const {
return h_inc_; }
811 size_type maxit()
const {
return maxit_; }
812 size_type thrit()
const {
return thrit_; }
813 double maxres()
const {
return maxres_; }
814 double maxdiff()
const {
return maxdiff_; }
815 double mincos()
const {
return mincos_; }
816 double delta_max()
const {
return delta_max_; }
817 double delta_min()
const {
return delta_min_; }
818 double thrvar()
const {
return thrvar_; }
819 size_type nbdir()
const {
return nbdir_; }
820 size_type nbspan()
const {
return nbspan_; }
822 void set_tau_lp(
double tau) { tau_lp = tau; }
823 double get_tau_lp()
const {
return tau_lp; }
824 void set_tau_bp_1(
double tau) { tau_bp_1 = tau; }
825 double get_tau_bp_1()
const {
return tau_bp_1; }
826 void set_tau_bp_2(
double tau) { tau_bp_2 = tau; }
827 double get_tau_bp_2()
const {
return tau_bp_2; }
828 void clear_tau_bp_currentstep() {
829 tau_bp_graph.clear();
831 void init_tau_bp_graph() { tau_bp_graph[0.] = tau_bp_2; }
832 void insert_tau_bp_graph(
double alpha,
double tau) {
833 tau_bp_graph[
alpha] = tau;
837 const VECT &get_alpha_hist() {
840 for (std::map<double, double>::iterator it = tau_bp_graph.begin();
841 it != tau_bp_graph.end(); it++) {
842 alpha_hist[i] = (*it).first; i++;
846 const VECT &get_tau_bp_hist() {
849 for (std::map<double, double>::iterator it = tau_bp_graph.begin();
850 it != tau_bp_graph.end(); it++) {
851 tau_bp_hist[i] = (*it).second; i++;
856 void clear_sing_data() {
863 tgamma_predict.clear();
865 void set_sing_label(std::string label) { sing_label = label; }
866 const std::string get_sing_label()
const {
return sing_label; }
867 void set_sing_point(
const VECT &x,
double gamma) {
869 copy(x, gamma, x_sing, gamma_sing);
871 const VECT &get_x_sing()
const {
return x_sing; }
872 double get_gamma_sing()
const {
return gamma_sing; }
873 size_type nb_tangent_sing()
const {
return tx_sing.size(); }
874 bool insert_tangent_sing(
const VECT &tx,
double tgamma){
875 bool is_included =
false;
876 for (
size_type i = 0; (i < tx_sing.size()) && (!is_included); ++i) {
877 double cang = cosang(tx_sing[i], tx, tgamma_sing[i], tgamma);
878 is_included = (cang >= mincos_);
881 tx_sing.push_back(tx);
882 tgamma_sing.push_back(tgamma);
886 const VECT &get_tx_sing(
size_type i)
const {
return tx_sing[i]; }
887 double get_tgamma_sing(
size_type i)
const {
return tgamma_sing[i]; }
888 const std::vector<VECT> &get_tx_sing()
const {
return tx_sing; }
889 const std::vector<double> &get_tgamma_sing()
const {
return tgamma_sing; }
891 void set_next_point(
const VECT &x,
double gamma) {
892 if (gmm::vect_size(x_next) == 0) {
894 copy(x, gamma, x_next, gamma_next);
897 const VECT &get_x_next()
const {
return x_next; }
898 double get_gamma_next()
const {
return gamma_next; }
900 bool insert_tangent_predict(
const VECT &tx,
double tgamma) {
901 bool is_included =
false;
902 for (
size_type i = 0; (i < tx_predict.size()) && (!is_included); ++i) {
903 double cang = gmm::abs(cosang(tx_predict[i], tx, tgamma_predict[i], tgamma));
904 is_included = (cang >= mincos_);
907 tx_predict.push_back(tx);
908 tgamma_predict.push_back(tgamma);
914 srand(
unsigned(time(NULL)));
917 bb_gamma = gmm::random(1.)/scalar_type(nbdof);
918 cc_gamma = gmm::random(1.)/scalar_type(nbdof);
919 dd = gmm::random(1.)/scalar_type(nbdof);
920 gmm::scale(bb_x_, scalar_type(1)/scalar_type(nbdof));
921 gmm::scale(cc_x_, scalar_type(1)/scalar_type(nbdof));
927 {
if (gmm::vect_size(bb_x_) != nbdof) init_border(nbdof);
return bb_x_; }
929 {
if (gmm::vect_size(cc_x_) != nbdof) init_border(nbdof);
return cc_x_; }
933 return (this->singularities == 0) ? 0
934 : (2 * gmm::vect_size(bb_x_) * szd
935 + 4 * gmm::vect_size(get_tau_bp_hist()) * szd
936 + (1 + nb_tangent_sing()) * gmm::vect_size(get_x_sing()) * szd);
942 virtual void solve(
const MAT &A, VECT &g,
const VECT &L)
const = 0;
944 virtual void solve(
const MAT &A, VECT &g1, VECT &g2,
945 const VECT &L1,
const VECT &L2)
const = 0;
947 virtual void F(
const VECT &x,
double gamma, VECT &f)
const = 0;
949 virtual void F_gamma(
const VECT &x,
double gamma,
const VECT &f0,
952 virtual void F_gamma(
const VECT &x,
double gamma, VECT &g)
const = 0;
954 virtual void F_x(
const VECT &x,
double gamma, MAT &A)
const = 0;
956 virtual void solve_grad(
const VECT &x,
double gamma,
957 VECT &g,
const VECT &L)
const = 0;
959 virtual void solve_grad(
const VECT &x,
double gamma, VECT &g1,
960 VECT &g2,
const VECT &L1,
const VECT &L2)
const = 0;
962 virtual void mult_grad(
const VECT &x,
double gamma,
963 const VECT &w, VECT &y)
const = 0;
968 (
int sing = 0,
bool nonsm =
false,
double sfac=0.,
969 double hin = 1.e-2,
double hmax = 1.e-1,
double hmin = 1.e-5,
970 double hinc = 1.3,
double hdec = 0.5,
972 double mres = 1.e-6,
double mdiff = 1.e-6,
double mcos = 0.9,
973 double dmax = 0.005,
double dmin = 0.00012,
double tvar = 0.02,
975 : singularities(sing), non_smooth(nonsm), scfac(sfac),
976 h_init_(hin), h_max_(hmax), h_min_(hmin), h_inc_(hinc), h_dec_(hdec),
977 maxit_(mit), thrit_(tit), maxres_(mres), maxdiff_(mdiff), mincos_(mcos),
978 delta_max_(dmax), delta_min_(dmin), thrvar_(tvar),
979 nbdir_(ndir), nbspan_(nspan), noisy_(noi),
980 tau_lp(0.), tau_bp_1(tau_bp_init), tau_bp_2(tau_bp_init),
981 gamma_sing(0.), gamma_next(0.)
983 virtual ~virtual_cont_struct() {}
997 #ifdef GETFEM_MODELS_H__
999 class cont_struct_getfem_model
1000 :
public virtual_cont_struct<base_vector, model_real_sparse_matrix>,
1005 std::string parameter_name;
1006 std::string initdata_name, finaldata_name, currentdata_name;
1007 gmm::sub_interval I;
1008 rmodel_plsolver_type lsolver;
1009 double maxres_solve;
1011 void set_variables(
const base_vector &x,
double gamma)
const;
1012 void update_matrix(
const base_vector &x,
double gamma)
const;
1016 double intrv_sp(
const base_vector &v1,
const base_vector &v2)
const {
1017 return (I.size() > 0) ?
gmm::vect_sp(gmm::sub_vector(v1,I),
1018 gmm::sub_vector(v2,I))
1023 void solve(
const model_real_sparse_matrix &A, base_vector &g,
const base_vector &L)
const;
1025 void solve(
const model_real_sparse_matrix &A, base_vector &g1, base_vector &g2,
1026 const base_vector &L1,
const base_vector &L2)
const;
1028 void F(
const base_vector &x,
double gamma, base_vector &f)
const;
1030 void F_gamma(
const base_vector &x,
double gamma,
const base_vector &f0,
1031 base_vector &g)
const;
1033 void F_gamma(
const base_vector &x,
double gamma, base_vector &g)
const;
1036 void F_x(
const base_vector &x,
double gamma, model_real_sparse_matrix &A)
const;
1038 void solve_grad(
const base_vector &x,
double gamma,
1039 base_vector &g,
const base_vector &L)
const;
1041 void solve_grad(
const base_vector &x,
double gamma, base_vector &g1,
1043 const base_vector &L1,
const base_vector &L2)
const;
1045 void mult_grad(
const base_vector &x,
double gamma,
1046 const base_vector &w, base_vector &y)
const;
1050 const model &linked_model() {
return *md; }
1052 void set_parametrised_data_names
1053 (
const std::string &in,
const std::string &fn,
const std::string &cn) {
1055 finaldata_name = fn;
1056 currentdata_name = cn;
1059 void set_interval_from_variable_name(
const std::string &varname) {
1060 if (varname ==
"") I = gmm::sub_interval(0,0);
1061 else I = md->interval_of_variable(varname);
1064 cont_struct_getfem_model
1065 (model &md_,
const std::string &pn,
double sfac, rmodel_plsolver_type ls,
1066 double hin = 1.e-2,
double hmax = 1.e-1,
double hmin = 1.e-5,
1067 double hinc = 1.3,
double hdec = 0.5,
size_type mit = 10,
1068 size_type tit = 4,
double mres = 1.e-6,
double mdiff = 1.e-6,
1069 double mcos = 0.9,
double mress = 1.e-8,
int noi = 0,
int sing = 0,
1070 bool nonsm =
false,
double dmax = 0.005,
double dmin = 0.00012,
1072 : virtual_cont_struct(sing, nonsm, sfac, hin, hmax, hmin, hinc, hdec,
1073 mit, tit, mres, mdiff, mcos, dmax, dmin, tvar,
1075 md(&md_), parameter_name(pn),
1076 initdata_name(
""), finaldata_name(
""), currentdata_name(
""),
1077 I(0,0), lsolver(ls), maxres_solve(mress)
1079 GMM_ASSERT1(!md->is_complex(),
1080 "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.