34   template <
typename PLSOLVER>
 
   37     typedef typename PLSOLVER::element_type::MATRIX MATRIX;
 
   38     typedef typename PLSOLVER::element_type::VECTOR VECTOR;
 
   39     typedef typename gmm::linalg_traits<VECTOR>::value_type T;
 
   40     typedef typename gmm::number_traits<T>::magnitude_type R;
 
   43     PLSOLVER linear_solver;
 
   49     virtual const VECTOR &residual()
 const { 
return rhs; }
 
   52     virtual const VECTOR &state_vector()
 const { 
return state; }
 
   53     virtual VECTOR &state_vector() { 
return state; }
 
   54     virtual R state_norm()
 const { 
return gmm::vect_norm1(state_vector()); }
 
   56     virtual void perturbation() {
 
   57       R res = 
gmm::vect_norm2(state), ampl = std::max(res*R(1E-20), R(1E-50));
 
   58       std::vector<R> V(gmm::vect_size(state));
 
   60       gmm::add(gmm::scaled(V, ampl), state);
 
   63     virtual void add_to_residual(VECTOR &extra_rhs, R mult=1.) {
 
   64       if (mult == R(1))       
gmm::add(extra_rhs, rhs);
 
   65       else if (mult != R(0))  
gmm::add(gmm::scaled(extra_rhs, mult), rhs);
 
   69       (*linear_solver)(K, dr, rhs, iter);
 
   72     pb_base(PLSOLVER linsolv, 
const MATRIX &K_, VECTOR &rhs_)
 
   73       : linear_solver(linsolv), K(K_), rhs(rhs_), state(gmm::vect_size(rhs_)) {}
 
   80   template <
typename PLSOLVER>
 
   81   class lin_model_pb : pb_base<PLSOLVER> {
 
   84     using typename pb_base<PLSOLVER>::VECTOR;
 
   85     using typename pb_base<PLSOLVER>::R;
 
   86     using pb_base<PLSOLVER>::state_vector;
 
   87     using pb_base<PLSOLVER>::linear_solve;
 
   88     void compute_all() { md.assembly(model::BUILD_ALL); }
 
   89     lin_model_pb(model &, PLSOLVER) = 
delete;
 
   93   lin_model_pb<rmodel_plsolver_type>::lin_model_pb
 
   94     (model &md_, rmodel_plsolver_type linsolv)
 
   95     : pb_base<rmodel_plsolver_type>
 
   96       (linsolv, md_.real_tangent_matrix(), md_.set_real_rhs()),
 
   98   { md.from_variables(state_vector()); }
 
  100   lin_model_pb<cmodel_plsolver_type>::lin_model_pb
 
  101     (model &md_, cmodel_plsolver_type linsolv)
 
  102     : pb_base<cmodel_plsolver_type>
 
  103       (linsolv, md_.complex_tangent_matrix(), md_.set_complex_rhs()),
 
  105   { md.from_variables(state_vector()); }
 
  111   template <
typename PLSOLVER>
 
  112   class nonlin_model_pb : 
protected pb_base<PLSOLVER> {
 
  114     using typename pb_base<PLSOLVER>::VECTOR;
 
  115     using typename pb_base<PLSOLVER>::R;
 
  118     abstract_newton_line_search &ls;
 
  122     using pb_base<PLSOLVER>::residual;
 
  123     using pb_base<PLSOLVER>::residual_norm;
 
  124     using pb_base<PLSOLVER>::state_vector;
 
  125     using pb_base<PLSOLVER>::state_norm;
 
  126     using pb_base<PLSOLVER>::add_to_residual;
 
  127     using pb_base<PLSOLVER>::perturbation;
 
  128     using pb_base<PLSOLVER>::linear_solve;
 
  130     virtual R approx_external_load_norm() { 
return md.approx_external_load(); }
 
  132     virtual void compute_tangent_matrix() {
 
  133       md.to_variables(state_vector());
 
  134       md.assembly(model::BUILD_MATRIX);
 
  137     virtual void compute_residual() {
 
  138       md.to_variables(state_vector());
 
  139       md.assembly(model::BUILD_RHS);
 
  144       gmm::resize(stateinit, gmm::vect_size(state_vector()));
 
  148        res = residual_norm();
 
  150       R0 = gmm::real(gmm::vect_sp(dr, residual()));
 
  151       ls.init_search(res, iter.get_iteration(), R0);
 
  153         alpha = ls.next_try();
 
  154         gmm::add(stateinit, gmm::scaled(dr, alpha), state_vector());
 
  157         res = residual_norm();
 
  159         R0 = gmm::real(gmm::vect_sp(dr, residual()));
 
  161       } 
while (!ls.is_converged(res, R0));
 
  163       if (alpha != ls.converged_value()) {
 
  164         alpha = ls.converged_value();
 
  165         gmm::add(stateinit, gmm::scaled(dr, alpha), state_vector());
 
  166         res = ls.converged_residual();
 
  173     nonlin_model_pb(model &md_, abstract_newton_line_search &ls_,
 
  174                     PLSOLVER linear_solver_) = 
delete;
 
  178   nonlin_model_pb<rmodel_plsolver_type>::nonlin_model_pb
 
  179     (model &md_, abstract_newton_line_search &ls_, rmodel_plsolver_type linsolv)
 
  180     : pb_base<rmodel_plsolver_type>
 
  181       (linsolv, md_.real_tangent_matrix(), md_.set_real_rhs()),
 
  183   { md.from_variables(state_vector()); }
 
  185   nonlin_model_pb<cmodel_plsolver_type>::nonlin_model_pb
 
  186     (model &md_, abstract_newton_line_search &ls_, cmodel_plsolver_type linsolv)
 
  187     : pb_base<cmodel_plsolver_type>
 
  188       (linsolv, md_.complex_tangent_matrix(), md_.set_complex_rhs()),
 
  190   { md.from_variables(state_vector()); }
 
  197   template <
typename PLSOLVER>
 
  198   class nonlin_condensed_model_pb : 
public nonlin_model_pb<PLSOLVER> {
 
  200     using typename pb_base<PLSOLVER>::MATRIX;
 
  201     using typename pb_base<PLSOLVER>::VECTOR;
 
  202     using typename pb_base<PLSOLVER>::R;
 
  205     using nonlin_model_pb<PLSOLVER>::md;
 
  207     const MATRIX &internal_K;
 
  211     virtual const VECTOR &residual()
 const { 
return full_rhs; }
 
  215     using pb_base<PLSOLVER>::state_vector;
 
  216     using pb_base<PLSOLVER>::state_norm;
 
  218     virtual void add_to_residual(VECTOR &extra_rhs, R mult=1.) {
 
  219       if (mult == R(1))      
gmm::add(extra_rhs, full_rhs);
 
  220       else if (mult != R(0)) 
gmm::add(gmm::scaled(extra_rhs, mult), full_rhs);
 
  223     using pb_base<PLSOLVER>::perturbation;
 
  226       VECTOR dr0(md.nb_primary_dof(), R(0));
 
  227       pb_base<PLSOLVER>::linear_solve(dr0, iter);
 
  228       gmm::sub_interval I_prim(0, md.nb_primary_dof()),
 
  229                         I_intern(md.nb_primary_dof(), md.nb_internal_dof());
 
  230       gmm::copy(dr0, gmm::sub_vector(dr, I_prim));
 
  233                 gmm::scaled(gmm::sub_vector(dr, I_prim), scalar_type(-1)),
 
  234                 md.internal_solution(),
 
  235                 gmm::sub_vector(dr, I_intern));
 
  238     virtual void compute_tangent_matrix() {
 
  239       md.to_variables(state_vector(), condensed_vars);
 
  240       md.assembly(condensed_vars ? model::BUILD_MATRIX_CONDENSED
 
  241                                  : model::BUILD_MATRIX);
 
  244     virtual void compute_residual() {
 
  245       md.to_variables(state_vector(), condensed_vars);
 
  246       md.assembly(condensed_vars ? model::BUILD_RHS_WITH_INTERNAL 
 
  250     nonlin_condensed_model_pb(model &md_, abstract_newton_line_search &ls_,
 
  251                               PLSOLVER linear_solver_) = 
delete;
 
  255   nonlin_condensed_model_pb<rmodel_plsolver_type>::nonlin_condensed_model_pb
 
  256     (model &md_, abstract_newton_line_search &ls_, rmodel_plsolver_type linsolv)
 
  257     : nonlin_model_pb<rmodel_plsolver_type>(md_, ls_, linsolv),
 
  258       condensed_vars(md_.has_internal_variables()),
 
  259       internal_K(md_.real_tangent_matrix(condensed_vars)),
 
  260       full_rhs(md_.set_real_rhs(condensed_vars))
 
  262     gmm::resize(state_vector(), md.nb_dof(condensed_vars));
 
  263     md.from_variables(state_vector(), condensed_vars);
 
  267   nonlin_condensed_model_pb<cmodel_plsolver_type>::nonlin_condensed_model_pb
 
  268     (model &md_, abstract_newton_line_search &ls_, cmodel_plsolver_type linsolv)
 
  269     : nonlin_model_pb<cmodel_plsolver_type>(md_, ls_, linsolv),
 
  270       condensed_vars(false), internal_K(md_.complex_tangent_matrix()),
 
  271       full_rhs(md_.set_complex_rhs())
 
  273     GMM_ASSERT1(
false, 
"No support for internal variable condensation in " 
  274                        "complex valued models.");
 
  282   static rmodel_plsolver_type rdefault_linear_solver(
const model &md) {
 
  283     return default_linear_solver<model_real_sparse_matrix,
 
  284                                  model_real_plain_vector>(md);
 
  287   static cmodel_plsolver_type cdefault_linear_solver(
const model &md) {
 
  288     return default_linear_solver<model_complex_sparse_matrix,
 
  289                                  model_complex_plain_vector>(md);
 
  292   void default_newton_line_search::init_search(
double r, 
size_t git, 
double) {
 
  293     alpha_min_ratio = 0.9;
 
  295     alpha_max_ratio = 10.0;
 
  298     glob_it = git; 
if (git <= 1) count_pat = 0;
 
  299     conv_alpha = 
alpha = alpha_old = 1.;
 
  300     conv_r = first_res = r; it = 0;
 
  302     max_ratio_reached = 
false;
 
  305   double default_newton_line_search::next_try() {
 
  306     alpha_old = 
alpha; ++it;
 
  308     if (alpha >= 0.4) 
alpha *= 0.5; 
else alpha *= alpha_mult;
 
  312   bool default_newton_line_search::is_converged(
double r, 
double) {
 
  314     if (!max_ratio_reached && r < first_res * alpha_max_ratio) {
 
  315       alpha_max_ratio_reached = alpha_old; r_max_ratio_reached = r;
 
  316       it_max_ratio_reached = it; max_ratio_reached = 
true;
 
  318     if (max_ratio_reached &&
 
  319         r < r_max_ratio_reached * 0.5 &&
 
  320         r > first_res * 1.1 && it <= it_max_ratio_reached+1) {
 
  321       alpha_max_ratio_reached = alpha_old; r_max_ratio_reached = r;
 
  322       it_max_ratio_reached = it;
 
  324     if (count == 0 || r < conv_r)
 
  325       { conv_r = r; conv_alpha = alpha_old; count = 1; }
 
  326     if (conv_r < first_res) ++count;
 
  328     if (r < first_res *  alpha_min_ratio)
 
  329       { count_pat = 0; 
return true; }
 
  330     if (count>=5 || (alpha < alpha_min && max_ratio_reached) || alpha<1e-15) {
 
  331       if (conv_r < first_res * 0.99) count_pat = 0;
 
  333         { conv_r=r_max_ratio_reached; conv_alpha=alpha_max_ratio_reached; }
 
  334       if (conv_r >= first_res * 0.999) count_pat++;
 
  346   template <
typename PLSOLVER>
 
  349                            abstract_newton_line_search &ls) {
 
  351     typename PLSOLVER::element_type::VECTOR state(md.nb_dof());
 
  352     md.from_variables(state);
 
  353     md.cancel_init_step();
 
  354     md.set_time_integration(2);
 
  355     scalar_type dt = md.get_time_step();
 
  356     scalar_type ddt = md.get_init_time_step();
 
  357     scalar_type t = md.get_time();
 
  360     md.set_time_step(ddt);
 
  363     md.copy_init_time_derivative();
 
  366     md.set_time_step(dt);
 
  368     md.to_variables(state);
 
  369     md.set_time_integration(1);
 
  376   template <
typename PLSOLVER>
 
  379                       abstract_newton_line_search &ls) {
 
  381     int time_integration = md.is_time_integration();
 
  382     if (time_integration) {
 
  383       if (time_integration == 1 && md.is_init_step()) {
 
  384         compute_init_values(md, iter, lsolver, ls);
 
  387       md.set_time(md.get_time() + md.get_time_step());
 
  388       md.call_init_affine_dependent_variables(time_integration);
 
  391     if (md.is_linear()) {
 
  392       lin_model_pb<PLSOLVER> mdpb(md, lsolver);
 
  394       mdpb.linear_solve(mdpb.state_vector(), iter);
 
  395       md.to_variables(mdpb.state_vector()); 
 
  397       std::unique_ptr<nonlin_model_pb<PLSOLVER>> mdpb;
 
  398       if (md.has_internal_variables())
 
  399         mdpb = std::make_unique<nonlin_condensed_model_pb<PLSOLVER>>(md, ls, lsolver);
 
  401         mdpb = std::make_unique<nonlin_model_pb<PLSOLVER>>(md, ls, lsolver);
 
  402       if (
dynamic_cast<newton_search_with_step_control *
>(&ls))
 
  403         Newton_with_step_control(*mdpb, iter);
 
  405         classical_Newton(*mdpb, iter);
 
  406       md.to_variables(mdpb->state_vector()); 
 
  411                       rmodel_plsolver_type lsolver,
 
  412                       abstract_newton_line_search &ls) {
 
  413     standard_solve<rmodel_plsolver_type>(md, iter, lsolver, ls);
 
  417                       cmodel_plsolver_type lsolver,
 
  418                       abstract_newton_line_search &ls) {
 
  419     standard_solve<cmodel_plsolver_type>(md, iter, lsolver, ls);
 
  424                       rmodel_plsolver_type lsolver) {
 
  425     default_newton_line_search ls;
 
  430                       cmodel_plsolver_type lsolver) {
 
  431     newton_search_with_step_control ls;
 
  437     newton_search_with_step_control ls;
 
`‘Model’' variables store the variables, the data and the description of a model.
The Iteration object calculates whether the solution has reached the desired accuracy,...
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 resize(V &v, size_type n)
*/
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm1(const V &v)
1-norm of a vector
void add(const L1 &l1, L2 &l2)
*/
Input/output on sparse matrices.
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.
void standard_solve(model &md, gmm::iteration &iter, rmodel_plsolver_type lsolver, abstract_newton_line_search &ls)
A default solver for the model brick system.