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.