33 template <
typename PLSOLVER>
36 typedef typename PLSOLVER::element_type::MATRIX MATRIX;
37 typedef typename PLSOLVER::element_type::VECTOR VECTOR;
38 typedef typename gmm::linalg_traits<VECTOR>::value_type T;
39 typedef typename gmm::number_traits<T>::magnitude_type R;
42 PLSOLVER linear_solver;
48 virtual const VECTOR &residual()
const {
return rhs; }
51 virtual const VECTOR &state_vector()
const {
return state; }
52 virtual VECTOR &state_vector() {
return state; }
53 virtual R state_norm()
const {
return gmm::vect_norm1(state_vector()); }
55 virtual void perturbation() {
56 R res =
gmm::vect_norm2(state), ampl = std::max(res*R(1E-20), R(1E-50));
57 std::vector<R> V(gmm::vect_size(state));
59 gmm::add(gmm::scaled(V, ampl), state);
62 virtual void add_to_residual(VECTOR &extra_rhs, R mult=1.) {
63 if (mult == R(1))
gmm::add(extra_rhs, rhs);
64 else if (mult != R(0))
gmm::add(gmm::scaled(extra_rhs, mult), rhs);
68 (*linear_solver)(K, dr, rhs, iter);
71 pb_base(PLSOLVER linsolv,
const MATRIX &K_, VECTOR &rhs_)
72 : linear_solver(linsolv), K(K_), rhs(rhs_), state(gmm::vect_size(rhs_)) {}
79 template <
typename PLSOLVER>
80 class lin_model_pb : pb_base<PLSOLVER> {
83 using typename pb_base<PLSOLVER>::VECTOR;
84 using typename pb_base<PLSOLVER>::R;
85 using pb_base<PLSOLVER>::state_vector;
86 using pb_base<PLSOLVER>::linear_solve;
87 void compute_all() { md.assembly(model::BUILD_ALL); }
88 lin_model_pb(model &, PLSOLVER) =
delete;
92 lin_model_pb<rmodel_plsolver_type>::lin_model_pb
93 (model &md_, rmodel_plsolver_type linsolv)
94 : pb_base<rmodel_plsolver_type>
95 (linsolv, md_.real_tangent_matrix(), md_.set_real_rhs()),
97 { md.from_variables(state_vector()); }
99 lin_model_pb<cmodel_plsolver_type>::lin_model_pb
100 (model &md_, cmodel_plsolver_type linsolv)
101 : pb_base<cmodel_plsolver_type>
102 (linsolv, md_.complex_tangent_matrix(), md_.set_complex_rhs()),
104 { md.from_variables(state_vector()); }
110 template <
typename PLSOLVER>
111 class nonlin_model_pb :
protected pb_base<PLSOLVER> {
113 using typename pb_base<PLSOLVER>::VECTOR;
114 using typename pb_base<PLSOLVER>::R;
117 abstract_newton_line_search &ls;
121 using pb_base<PLSOLVER>::residual;
122 using pb_base<PLSOLVER>::residual_norm;
123 using pb_base<PLSOLVER>::state_vector;
124 using pb_base<PLSOLVER>::state_norm;
125 using pb_base<PLSOLVER>::add_to_residual;
126 using pb_base<PLSOLVER>::perturbation;
127 using pb_base<PLSOLVER>::linear_solve;
129 virtual R approx_external_load_norm() {
return md.approx_external_load(); }
131 virtual void compute_tangent_matrix() {
132 md.to_variables(state_vector());
133 md.assembly(model::BUILD_MATRIX);
136 virtual void compute_residual() {
137 md.to_variables(state_vector());
138 md.assembly(model::BUILD_RHS);
143 gmm::resize(stateinit, gmm::vect_size(state_vector()));
147 res = residual_norm();
149 R0 = gmm::real(gmm::vect_sp(dr, residual()));
150 ls.init_search(res, iter.get_iteration(), R0);
152 alpha = ls.next_try();
153 gmm::add(stateinit, gmm::scaled(dr, alpha), state_vector());
156 res = residual_norm();
158 R0 = gmm::real(gmm::vect_sp(dr, residual()));
160 }
while (!ls.is_converged(res, R0));
162 if (alpha != ls.converged_value()) {
163 alpha = ls.converged_value();
164 gmm::add(stateinit, gmm::scaled(dr, alpha), state_vector());
165 res = ls.converged_residual();
172 nonlin_model_pb(model &md_, abstract_newton_line_search &ls_,
173 PLSOLVER linear_solver_) =
delete;
177 nonlin_model_pb<rmodel_plsolver_type>::nonlin_model_pb
178 (model &md_, abstract_newton_line_search &ls_, rmodel_plsolver_type linsolv)
179 : pb_base<rmodel_plsolver_type>
180 (linsolv, md_.real_tangent_matrix(), md_.set_real_rhs()),
182 { md.from_variables(state_vector()); }
184 nonlin_model_pb<cmodel_plsolver_type>::nonlin_model_pb
185 (model &md_, abstract_newton_line_search &ls_, cmodel_plsolver_type linsolv)
186 : pb_base<cmodel_plsolver_type>
187 (linsolv, md_.complex_tangent_matrix(), md_.set_complex_rhs()),
189 { md.from_variables(state_vector()); }
196 template <
typename PLSOLVER>
197 class nonlin_condensed_model_pb :
public nonlin_model_pb<PLSOLVER> {
199 using typename pb_base<PLSOLVER>::MATRIX;
200 using typename pb_base<PLSOLVER>::VECTOR;
201 using typename pb_base<PLSOLVER>::R;
204 using nonlin_model_pb<PLSOLVER>::md;
206 const MATRIX &internal_K;
210 virtual const VECTOR &residual()
const {
return full_rhs; }
214 using pb_base<PLSOLVER>::state_vector;
215 using pb_base<PLSOLVER>::state_norm;
217 virtual void add_to_residual(VECTOR &extra_rhs, R mult=1.) {
218 if (mult == R(1))
gmm::add(extra_rhs, full_rhs);
219 else if (mult != R(0))
gmm::add(gmm::scaled(extra_rhs, mult), full_rhs);
222 using pb_base<PLSOLVER>::perturbation;
225 VECTOR dr0(md.nb_primary_dof(), R(0));
226 pb_base<PLSOLVER>::linear_solve(dr0, iter);
227 gmm::sub_interval I_prim(0, md.nb_primary_dof()),
228 I_intern(md.nb_primary_dof(), md.nb_internal_dof());
229 gmm::copy(dr0, gmm::sub_vector(dr, I_prim));
232 gmm::scaled(gmm::sub_vector(dr, I_prim), scalar_type(-1)),
233 md.internal_solution(),
234 gmm::sub_vector(dr, I_intern));
237 virtual void compute_tangent_matrix() {
238 md.to_variables(state_vector(), condensed_vars);
239 md.assembly(condensed_vars ? model::BUILD_MATRIX_CONDENSED
240 : model::BUILD_MATRIX);
243 virtual void compute_residual() {
244 md.to_variables(state_vector(), condensed_vars);
245 md.assembly(condensed_vars ? model::BUILD_RHS_WITH_INTERNAL
249 nonlin_condensed_model_pb(model &md_, abstract_newton_line_search &ls_,
250 PLSOLVER linear_solver_) =
delete;
254 nonlin_condensed_model_pb<rmodel_plsolver_type>::nonlin_condensed_model_pb
255 (model &md_, abstract_newton_line_search &ls_, rmodel_plsolver_type linsolv)
256 : nonlin_model_pb<rmodel_plsolver_type>(md_, ls_, linsolv),
257 condensed_vars(md_.has_internal_variables()),
258 internal_K(md_.real_tangent_matrix(condensed_vars)),
259 full_rhs(md_.set_real_rhs(condensed_vars))
261 gmm::resize(state_vector(), md.nb_dof(condensed_vars));
262 md.from_variables(state_vector(), condensed_vars);
266 nonlin_condensed_model_pb<cmodel_plsolver_type>::nonlin_condensed_model_pb
267 (model &md_, abstract_newton_line_search &ls_, cmodel_plsolver_type linsolv)
268 : nonlin_model_pb<cmodel_plsolver_type>(md_, ls_, linsolv),
269 condensed_vars(false), internal_K(md_.complex_tangent_matrix()),
270 full_rhs(md_.set_complex_rhs())
272 GMM_ASSERT1(
false,
"No support for internal variable condensation in "
273 "complex valued models.");
281 static rmodel_plsolver_type rdefault_linear_solver(
const model &md) {
282 return default_linear_solver<model_real_sparse_matrix,
283 model_real_plain_vector>(md);
286 static cmodel_plsolver_type cdefault_linear_solver(
const model &md) {
287 return default_linear_solver<model_complex_sparse_matrix,
288 model_complex_plain_vector>(md);
291 void default_newton_line_search::init_search(
double r,
size_t git,
double) {
292 alpha_min_ratio = 0.9;
294 alpha_max_ratio = 10.0;
297 glob_it = git;
if (git <= 1) count_pat = 0;
298 conv_alpha =
alpha = alpha_old = 1.;
299 conv_r = first_res = r; it = 0;
301 max_ratio_reached =
false;
304 double default_newton_line_search::next_try() {
305 alpha_old =
alpha; ++it;
307 if (alpha >= 0.4)
alpha *= 0.5;
else alpha *= alpha_mult;
311 bool default_newton_line_search::is_converged(
double r,
double) {
313 if (!max_ratio_reached && r < first_res * alpha_max_ratio) {
314 alpha_max_ratio_reached = alpha_old; r_max_ratio_reached = r;
315 it_max_ratio_reached = it; max_ratio_reached =
true;
317 if (max_ratio_reached &&
318 r < r_max_ratio_reached * 0.5 &&
319 r > first_res * 1.1 && it <= it_max_ratio_reached+1) {
320 alpha_max_ratio_reached = alpha_old; r_max_ratio_reached = r;
321 it_max_ratio_reached = it;
323 if (count == 0 || r < conv_r)
324 { conv_r = r; conv_alpha = alpha_old; count = 1; }
325 if (conv_r < first_res) ++count;
327 if (r < first_res * alpha_min_ratio)
328 { count_pat = 0;
return true; }
329 if (count>=5 || (alpha < alpha_min && max_ratio_reached) || alpha<1e-15) {
330 if (conv_r < first_res * 0.99) count_pat = 0;
332 { conv_r=r_max_ratio_reached; conv_alpha=alpha_max_ratio_reached; }
333 if (conv_r >= first_res * 0.999) count_pat++;
345 template <
typename PLSOLVER>
348 abstract_newton_line_search &ls) {
350 typename PLSOLVER::element_type::VECTOR state(md.nb_dof());
351 md.from_variables(state);
352 md.cancel_init_step();
353 md.set_time_integration(2);
354 scalar_type dt = md.get_time_step();
355 scalar_type ddt = md.get_init_time_step();
356 scalar_type t = md.get_time();
359 md.set_time_step(ddt);
362 md.copy_init_time_derivative();
365 md.set_time_step(dt);
367 md.to_variables(state);
368 md.set_time_integration(1);
375 template <
typename PLSOLVER>
378 abstract_newton_line_search &ls) {
380 int time_integration = md.is_time_integration();
381 if (time_integration) {
382 if (time_integration == 1 && md.is_init_step()) {
383 compute_init_values(md, iter, lsolver, ls);
386 md.set_time(md.get_time() + md.get_time_step());
387 md.call_init_affine_dependent_variables(time_integration);
390 if (md.is_linear()) {
391 lin_model_pb<PLSOLVER> mdpb(md, lsolver);
393 mdpb.linear_solve(mdpb.state_vector(), iter);
394 md.to_variables(mdpb.state_vector());
396 std::unique_ptr<nonlin_model_pb<PLSOLVER>> mdpb;
397 if (md.has_internal_variables())
398 mdpb = std::make_unique<nonlin_condensed_model_pb<PLSOLVER>>(md, ls, lsolver);
400 mdpb = std::make_unique<nonlin_model_pb<PLSOLVER>>(md, ls, lsolver);
401 if (
dynamic_cast<newton_search_with_step_control *
>(&ls))
402 Newton_with_step_control(*mdpb, iter);
404 classical_Newton(*mdpb, iter);
405 md.to_variables(mdpb->state_vector());
410 rmodel_plsolver_type lsolver,
411 abstract_newton_line_search &ls) {
412 standard_solve<rmodel_plsolver_type>(md, iter, lsolver, ls);
416 cmodel_plsolver_type lsolver,
417 abstract_newton_line_search &ls) {
418 standard_solve<cmodel_plsolver_type>(md, iter, lsolver, ls);
423 rmodel_plsolver_type lsolver) {
424 default_newton_line_search ls;
429 cmodel_plsolver_type lsolver) {
430 newton_search_with_step_control ls;
436 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.