21#ifndef B2LINEARIZE_PREBUCKLING_SOLVER_H_
22#define B2LINEARIZE_PREBUCKLING_SOLVER_H_
26#include "b2ppconfig.h"
27#include "b2static_nonlinear_utile.H"
30#include "utils/b2linear_algebra.H"
32#include "utils/b2nonlinear_system_solver.H"
33#include "utils/b2numerical_differentiation.H"
39namespace b2000::solver {
41template <
typename T,
typename MATRIX_FORMAT>
42class TaylorExpansionsBucklingSolver :
public Solver {
44 using type_t = ObjectTypeComplete<TaylorExpansionsBucklingSolver, Solver::type_t>;
46 void solve()
override {
47 while (solve_iteration()) { ; }
50 bool solve_iteration()
override {
52 if (case_iterator_.get() ==
nullptr) {
55 case_ = case_iterator_->next();
60 <<
"The Taylor expansion buckling solver cannot hand a case with multiple "
61 "stages. The extra stages are ignored."
64 solve_on_case(*
case_);
73 void solve_on_case(Case&
case_);
75 void solve_nonlinear_refinement(
76 Case&
case_, DefaultStaticResidueFunction<T, MATRIX_FORMAT>& residue_function,
77 b2linalg::Vector<double, b2linalg::Vdense_ref> value,
double& time,
78 b2linalg::Vector<double, b2linalg::Vdense_ref> eigenvector,
79 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K);
81 void solve_nonlinear_refinement_sha2(
82 Case&
case_, DefaultStaticResidueFunction<T, MATRIX_FORMAT>& residue_function,
83 b2linalg::Vector<double, b2linalg::Vdense_ref> value,
double& time,
84 b2linalg::Vector<double, b2linalg::Vdense_ref> eigenvector,
85 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K) {
86 NonLinearSystem nls(
case_, residue_function, K);
87 b2linalg::Vector<T> x;
88 nls.init(value, time, eigenvector, x);
89 Sha2NonlinearSolver solver(5);
91 nls.set_result(x, value, time, eigenvector);
94 class NonLinearSystem {
96 typedef b2linalg::Vector<T> x_type;
97 typedef b2linalg::Vector<T> r_type;
100 Case&
case_, DefaultStaticResidueFunction<T, MATRIX_FORMAT>& residue_function_,
101 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K_)
102 : residue_function(residue_function_), K(K_) {
104 "APPROXIMATION_ORDER_REFINEMENT",
case_.
get_int(
"APPROXIMATION_ORDER", 1));
105 h = std::pow(1e-15, 1.0 / (approximation_order + 1))
109 use_constraint_with_time =
false;
111 s = residue_function.get_number_of_dof();
113 d_residue_d_time.resize(s);
114 Z.set_same_structure(K);
115 TMP.set_same_structure(K);
122 b2linalg::Vector<double, b2linalg::Vdense_ref> value,
double& time,
123 b2linalg::Vector<double, b2linalg::Vdense_ref> eigenvector_,
124 b2linalg::Vector<double>& x) {
126 x(b2linalg::Interval(0, s)) = value;
127 x(b2linalg::Interval(s, 2 * s)) = eigenvector_;
130 b2linalg::Vector<double, b2linalg::Vdense_ref> eigenvector =
131 x(b2linalg::Interval(s, 2 * s));
133 1.0 / (eigenvector.norm2() * (use_constraint_with_time ? std::sqrt(time) : 1));
137 b2linalg::Vector<double>& x, b2linalg::Vector<double, b2linalg::Vdense_ref> value,
138 double& time, b2linalg::Vector<double, b2linalg::Vdense_ref> eigenvector_) {
139 value = x(b2linalg::Interval(0, s));
140 eigenvector_ = x(b2linalg::Interval(s, 2 * s));
144 void operator()(
const x_type& x, r_type& r,
bool update_der =
false) {
145 EquilibriumSolution esf(
false);
146 b2linalg::Vector<double, b2linalg::Vdense_constref> value = x(b2linalg::Interval(0, s));
147 b2linalg::Vector<double, b2linalg::Vdense_constref> eigenvector =
148 x(b2linalg::Interval(s, 2 * s));
149 double time = x[2 * s];
152 b2linalg::Vector<double, b2linalg::Vdense_ref> residue = r(b2linalg::Interval(0, s));
153 b2linalg::Vector<double, b2linalg::Vdense_ref> Ke = r(b2linalg::Interval(s, 2 * s));
156 K.set_zero_same_struct();
157 d_residue_d_time.set_zero();
159 residue_function.get_residue(
160 value, time, 0, esf, residue, K, d_residue_d_time, 0, 0, 0);
162 residue_function.get_residue(
163 value, time, 0, esf, residue,
164 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null,
165 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, 0);
167 Ke = (b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref>)K * eigenvector;
168 const double eigenvector_eigenvector = eigenvector * eigenvector;
169 r[2 * s] = eigenvector_eigenvector * (use_constraint_with_time ? time : 1) - 1;
172 void operator()(
const x_type& x, r_type& r,
const x_type& dx, r_type& dr) {
173 EquilibriumSolution esf(
false);
174 b2linalg::Vector<double, b2linalg::Vdense_constref> value = x(b2linalg::Interval(0, s));
175 b2linalg::Vector<double, b2linalg::Vdense_constref> eigenvector =
176 x(b2linalg::Interval(s, 2 * s));
177 double time = x[2 * s];
181 b2linalg::Vector<double, b2linalg::Vdense_ref> residue = r(b2linalg::Interval(0, s));
182 b2linalg::Vector<double, b2linalg::Vdense_ref> Ke = r(b2linalg::Interval(s, 2 * s));
185 K.set_zero_same_struct();
186 d_residue_d_time.set_zero();
187 residue_function.get_residue(
188 value, time, 0, esf, residue, K, d_residue_d_time, 0, 0, 0);
189 Ke = (b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref>)K * eigenvector;
190 const double eigenvector_eigenvector = eigenvector * eigenvector;
191 r[2 * s] = eigenvector_eigenvector * (use_constraint_with_time ? time : 1) - 1;
193 dr(b2linalg::Interval(0, s)) = K * dx(b2linalg::Interval(0, s));
194 dr(b2linalg::Interval(0, s)) += d_residue_d_time * dx[2 * s];
195 dr(b2linalg::Interval(s, 2 * s)) = K * dx(b2linalg::Interval(s, 2 * s));
198 const double hh = h / eigenvector.norm2();
199 Z.set_zero_same_struct();
200 Z += (diff_coeff[0] / hh) * K;
201 for (
unsigned int i = 1; i < diff_coeff.size(); ++i) {
203 tmp += (i * hh) * eigenvector;
204 TMP.set_zero_same_struct();
205 residue_function.get_residue(
206 tmp, time, 0, esf, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, TMP,
207 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, 0);
208 Z += (diff_coeff[i] / hh) * TMP;
211 dr(b2linalg::Interval(s, 2 * s)) += Z * dx(b2linalg::Interval(0, s));
214 tmp = (diff_coeff[0] / h) * Ke;
215 for (
unsigned int i = 1; i < diff_coeff.size(); ++i) {
216 TMP.set_zero_same_struct();
217 residue_function.get_residue(
218 value, time + i * h, 0, esf,
219 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, TMP,
220 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, 0);
221 tmp += (diff_coeff[i] / h)
222 * (b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref>)TMP
226 dr(b2linalg::Interval(s, 2 * s)) += tmp * dx[2 * s];
228 if (use_constraint_with_time) {
229 dr[2 * s] = 2 * x[2 * s] * (eigenvector * dx(b2linalg::Interval(s, 2 * s)))
230 + (eigenvector * eigenvector) * dx[2 * s];
232 dr[2 * s] = 2 * (eigenvector * dx(b2linalg::Interval(s, 2 * s)));
238 bool nd(
const x_type& x,
const r_type& r, x_type& d) {
239 EquilibriumSolution esf(
false);
240 b2linalg::Vector<double, b2linalg::Vdense_constref> value = x(b2linalg::Interval(0, s));
241 b2linalg::Vector<double, b2linalg::Vdense_constref> eigenvector =
242 x(b2linalg::Interval(s, 2 * s));
243 double time = x[2 * s];
244 b2linalg::Vector<double, b2linalg::Vdense_constref> residue =
245 r(b2linalg::Interval(0, s));
246 b2linalg::Vector<double, b2linalg::Vdense_constref> Ke =
247 r(b2linalg::Interval(s, 2 * s));
250 qfp[0] = b2linalg::inverse(K) * residue;
251 qfp[1] = b2linalg::inverse(K) * d_residue_d_time;
255 const double hh = h / eigenvector.norm2();
256 Z.set_zero_same_struct();
257 Z += (diff_coeff[0] / hh) * K;
258 for (
unsigned int i = 1; i < diff_coeff.size(); ++i) {
260 tmp += (i * hh) * eigenvector;
261 TMP.set_zero_same_struct();
262 residue_function.get_residue(
263 tmp, time, 0, esf, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, TMP,
264 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, 0);
265 Z += (diff_coeff[i] / hh) * TMP;
269 phifp = (b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref>)Z * qfp;
273 tmp = (diff_coeff[0] / h) * Ke;
274 for (
unsigned int i = 1; i < diff_coeff.size(); ++i) {
275 TMP.set_zero_same_struct();
276 residue_function.get_residue(
277 value, time + i * h, 0, esf,
278 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, TMP,
279 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, 0);
280 tmp += (diff_coeff[i] / h)
281 * (b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref>)TMP
289 phifp[0] = inverse(K) * phifp[0];
290 phifp[1] = inverse(K) * phifp[1];
294 const double eigenvector_eigenvector = eigenvector * eigenvector;
296 if (use_constraint_with_time) {
297 dc = -(r[2 * s] + 2 * time * (eigenvector * phifp[0]))
298 / (eigenvector_eigenvector + 2 * time * (eigenvector * phifp[1]));
300 dc = -(r[2 * s] + 2 * (eigenvector * phifp[0])) / (2 * (eigenvector * phifp[1]));
303 qfp[0] += dc * qfp[1];
304 phifp[0] += dc * phifp[1];
306 d(b2linalg::Interval(0, s)) = qfp[0];
307 d(b2linalg::Interval(s, 2 * s)) = phifp[0];
312 void gd(
const x_type& x,
const r_type& r, x_type& d) {
313 EquilibriumSolution esf(
false);
314 b2linalg::Vector<double, b2linalg::Vdense_constref> value = x(b2linalg::Interval(0, s));
315 b2linalg::Vector<double, b2linalg::Vdense_constref> eigenvector =
316 x(b2linalg::Interval(s, 2 * s));
317 double time = x[2 * s];
318 b2linalg::Vector<double, b2linalg::Vdense_constref> Ke =
319 r(b2linalg::Interval(s, 2 * s));
322 K.set_zero_same_struct();
323 d_residue_d_time.set_zero();
324 residue_function.get_residue(
325 value, time, 0, esf, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, K,
326 d_residue_d_time, 0, 0, 0);
328 d(b2linalg::Interval(0, s)) = K * r(b2linalg::Interval(0, s));
329 d(b2linalg::Interval(0, s)) += d_residue_d_time * r[2 * s];
330 d(b2linalg::Interval(s, 2 * s)) = K * r(b2linalg::Interval(s, 2 * s));
333 const double hh = h / eigenvector.norm2();
334 Z.set_zero_same_struct();
335 Z += (diff_coeff[0] / hh) * K;
336 for (
unsigned int i = 1; i < diff_coeff.size(); ++i) {
338 tmp += (i * hh) * eigenvector;
339 TMP.set_zero_same_struct();
340 residue_function.get_residue(
341 tmp, time, 0, esf, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, TMP,
342 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, 0);
343 Z += (diff_coeff[i] / hh) * TMP;
346 d(b2linalg::Interval(s, 2 * s)) += Z * r(b2linalg::Interval(0, s));
349 tmp = (diff_coeff[0] / h) * Ke;
350 for (
unsigned int i = 1; i < diff_coeff.size(); ++i) {
351 TMP.set_zero_same_struct();
352 residue_function.get_residue(
353 value, time + i * h, 0, esf,
354 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, TMP,
355 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, 0);
356 tmp += (diff_coeff[i] / h)
357 * (b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref>)TMP
361 d(b2linalg::Interval(s, 2 * s)) += tmp * r[2 * s];
363 if (use_constraint_with_time) {
364 d[2 * s] = 2 * x[2 * s] * (eigenvector * r(b2linalg::Interval(s, 2 * s)))
365 + (eigenvector * eigenvector) * r[2 * s];
367 d[2 * s] = 2 * (eigenvector * r(b2linalg::Interval(s, 2 * s)));
374 DefaultStaticResidueFunction<T, MATRIX_FORMAT>& residue_function;
375 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K;
378 b2linalg::Vector<T, b2linalg::Vdense> residue;
379 b2linalg::Vector<T, b2linalg::Vdense> d_residue_d_time;
380 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> Z;
381 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> TMP;
382 b2linalg::Vector<T, b2linalg::Vdense> tmp;
383 b2linalg::Matrix<T, b2linalg::Mrectangle> qfp;
384 b2linalg::Matrix<T, b2linalg::Mrectangle> phifp;
386 double approximation_order;
388 std::vector<double> diff_coeff;
390 bool use_constraint_with_time;
393 SolverUtils<T, MATRIX_FORMAT> solver_utile;
396template <
typename T,
typename MATRIX_FORMAT>
397typename TaylorExpansionsBucklingSolver<T, MATRIX_FORMAT>::type_t
398 TaylorExpansionsBucklingSolver<T, MATRIX_FORMAT>::type(
399 "TaylorExpansionsBucklingSolver", type_name<T, MATRIX_FORMAT>(),
400 StringList(
"TAYLOR_EXPANSIONS_BUCKLING",
"P_BIFURCATION"), module, &Solver::type);
409template <
typename T,
typename MATRIX_FORMAT>
410void b2000::solver::TaylorExpansionsBucklingSolver<T, MATRIX_FORMAT>::solve_nonlinear_refinement(
411 Case& case_, DefaultStaticResidueFunction<T, MATRIX_FORMAT>& residue_function,
412 b2linalg::Vector<double, b2linalg::Vdense_ref> value,
double& time,
413 b2linalg::Vector<double, b2linalg::Vdense_ref> eigenvector,
414 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K) {
415 const double approximation_order =
416 case_.get_int(
"APPROXIMATION_ORDER_REFINEMENT", case_.get_int(
"APPROXIMATION_ORDER", 1));
417 const double h = std::pow(1e-15, 1.0 / (approximation_order + 1))
418 * case_.get_double(
"H_SCALE_REFINEMENT", case_.get_double(
"H_SCALE", 1.0));
419 std::vector<double> diff_coeff;
421 const double eps = 1e-5;
423 const bool use_constraint_with_time =
false;
425 const size_t s = value.size();
426 b2linalg::Vector<T, b2linalg::Vdense> residue(s);
427 b2linalg::Vector<T, b2linalg::Vdense> d_residue_d_time(s);
428 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> Z;
429 Z.set_same_structure(K);
430 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> TMP;
431 TMP.set_same_structure(K);
432 b2linalg::Vector<T, b2linalg::Vdense> tmp(s);
433 b2linalg::Vector<T, b2linalg::Vdense> Ke(s);
434 b2linalg::Matrix<T, b2linalg::Mrectangle> qfp(s, 2);
435 b2linalg::Matrix<T, b2linalg::Mrectangle> phifp(s, 2);
436 eigenvector *= 1.0 / (eigenvector.norm2() * (use_constraint_with_time ? std::sqrt(time) : 1));
439 EquilibriumSolution esf(
false);
441 K.set_zero_same_struct();
442 d_residue_d_time.set_zero();
443 residue_function.get_residue(value, time, 0, esf, residue, K, d_residue_d_time, 0, 0, 0);
444 Ke = (b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref>)K * eigenvector;
445 const double eigenvector_eigenvector = eigenvector * eigenvector;
446 double c = eigenvector_eigenvector * (use_constraint_with_time ? time : 1) - 1;
448 const double res1 = residue.norm2();
449 const double res2 = Ke.norm2();
450 const double res3 = c;
451 std::cout << res1 <<
" " << res2 <<
" " << res3 <<
" " << time << std::endl;
452 if (res1 < eps && res2 < eps && res3 < eps) {
break; }
454 qfp[0] = inverse(K) * residue;
455 qfp[1] = inverse(K) * d_residue_d_time;
460 double hh = h / eigenvector.norm2();
462 tmp += hh * eigenvector;
463 Z.set_zero_same_struct();
464 residue_function.get_residue(
465 tmp, time, 0, esf, b2000::b2linalg::Vector<T, b2000::b2linalg::Vdense_ref>::null,
466 Z, b2000::b2linalg::Vector<T, b2000::b2linalg::Vdense_ref>::null, 0, 0, 0);
474 const double hh = h / eigenvector.norm2();
475 Z.set_zero_same_struct();
476 Z += (diff_coeff[0] / hh) * K;
477 for (
unsigned int i = 1; i < diff_coeff.size(); ++i) {
479 tmp += (i * hh) * eigenvector;
480 TMP.set_zero_same_struct();
481 residue_function.get_residue(
482 tmp, time, 0, esf, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, TMP,
483 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, 0);
484 Z += (diff_coeff[i] / hh) * TMP;
489 phifp = (b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref>)Z * qfp;
494 Z.set_zero_same_struct();
495 residue_function.get_residue(
496 value, time + h, 0, esf,
497 b2000::b2linalg::Vector<T, b2000::b2linalg::Vdense_ref>::null, Z,
498 b2000::b2linalg::Vector<T, b2000::b2linalg::Vdense_ref>::null, 0, 0, 0);
499 tmp = (b2000::b2linalg::Matrix<T, b2000::b2linalg::Msym_compressed_col_st_constref>)Z
508 tmp = (diff_coeff[0] / h) * Ke;
509 for (
unsigned int i = 1; i < diff_coeff.size(); ++i) {
510 TMP.set_zero_same_struct();
511 residue_function.get_residue(
512 value, time + i * h, 0, esf, b2linalg::Vector<T, b2linalg::Vdense_ref>::null,
513 TMP, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, 0);
514 tmp += (diff_coeff[i] / h)
515 * (b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref>)TMP
524 phifp[0] = inverse(K) * phifp[0];
525 phifp[1] = inverse(K) * phifp[1];
529 if (use_constraint_with_time) {
530 dc = -(c + 2 * time * (eigenvector * phifp[0]))
531 / (eigenvector_eigenvector + 2 * time * (eigenvector * phifp[1]));
533 dc = -(c + 2 * (eigenvector * phifp[0])) / (2 * (eigenvector * phifp[1]));
536 const double s = case_.get_double(
"NRS", 1);
540 qfp[0] += dc * qfp[1];
542 phifp[0] += dc * phifp[1];
543 eigenvector += phifp[0];
554template <
typename T,
typename MATRIX_FORMAT>
555void b2000::solver::TaylorExpansionsBucklingSolver<T, MATRIX_FORMAT>::solve_on_case(Case& case_) {
556 logging::Logger& logger = logging::get_logger(
"solver.taylor_expansions_buckling");
558 if (model_ ==
nullptr) { Exception() <<
THROW; }
561 logger << logging::info <<
"Start the Taylor expansions buckling solver for the case "
562 << case_.get_id() <<
"." << logging::LOGFLUSH;
563 model_->set_case(case_);
565 logger << logging::info <<
"Assemble the linear problem." << logging::LOGFLUSH;
567 SolutionTaylorExpansionsBuckling<T>& solution =
568 dynamic_cast<SolutionTaylorExpansionsBuckling<T>&
>(model_->get_solution());
573 solution.which_modes(nb_eigeinvalue, which, sigma);
574 const int path_approximation_order =
575 case_.get_int(
"APPROXIMATION_ORDER_PATH", case_.get_int(
"APPROXIMATION_ORDER", 2));
576 const int path_taylor_order =
577 case_.get_int(
"TAYLOR_ORDER_PATH", case_.get_int(
"TAYLOR_ORDER", 1));
578 const double path_h_scale = case_.get_double(
"H_SCALE_PATH", case_.get_double(
"H_SCALE", 1.0));
579 const int K_approximation_order =
580 case_.get_int(
"APPROXIMATION_ORDER_K", case_.get_int(
"APPROXIMATION_ORDER", 2));
581 const int K_taylor_order = case_.get_int(
"TAYLOR_ORDER_K", case_.get_int(
"TAYLOR_ORDER", 1));
582 const double K_h_scale = case_.get_double(
"H_SCALE_K", case_.get_double(
"H_SCALE", 1.0));
583 const double tol_eigenvalue_imag = case_.get_double(
"TOL_EIGENVALUE_IMAG", 1e-6);
585 DefaultStaticResidueFunction<T, MATRIX_FORMAT> residue_function;
586 residue_function.init(*model_, case_);
588 const size_t nb_dof = model_->get_domain().get_number_of_dof();
589 const size_t nb_rdof = residue_function.get_number_of_dof();
590 const size_t nb_lndof = residue_function.get_number_of_non_lagrange_dof();
592 b2linalg::Vector<T, b2linalg::Vdense> rdof(nb_rdof);
595 logger << logging::info <<
"Compute the Taylor expansion of the path solution."
596 << logging::LOGFLUSH;
598 EquilibriumSolution es(
true);
600 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible_ext> K(
601 nb_rdof, 1, model_->get_domain().get_dof_connectivity_type(), case_);
602 b2linalg::Matrix<T, b2linalg::Mrectangle> d_dof_and_time_d_path(nb_rdof + 1, path_taylor_order);
604 b2linalg::Vector<T, b2linalg::Vdense> q(nb_rdof);
605 b2linalg::Vector<T, b2linalg::Vdense> arc(nb_rdof + 1);
608 residue_function.get_d_dof_d_path(
609 rdof, time, K, q, arc, d_dof_and_time_d_path, path_approximation_order, path_h_scale);
612 b2linalg::Matrix<T, b2linalg::Mcompressed_col> reduc_d_value_d_dof_trans;
615 b2linalg::Matrix<T, b2linalg::Mrectangle> path_te(nb_dof, d_dof_and_time_d_path.size2());
616 b2linalg::Vector<T, b2linalg::Vdense> reduc_r(nb_dof);
617 residue_function.mrbc_get_nonlinear_value(
618 rdof, time,
false, b2linalg::Vector<T, b2linalg::Vdense_ref>::null,
619 reduc_d_value_d_dof_trans, reduc_r, 0);
620 path_te = transposed(reduc_d_value_d_dof_trans)
621 * d_dof_and_time_d_path(
622 b2linalg::Interval(0, nb_lndof),
623 b2linalg::Interval(0, d_dof_and_time_d_path.size2()));
624 b2linalg::Vector<T, b2linalg::Vdense> time_te(path_te.size2());
626 for (
size_t j = 0; j != path_te.size2(); ++j) {
628 time_te[j] = d_dof_and_time_d_path(nb_rdof, j) / s;
629 path_te[j] *= 1.0 / s;
630 path_te[j] += time_te[j] * reduc_r;
632 solution.set_path(path_te, time_te);
633 K_h_scale1 = 1.0 / path_te[0].norm2();
636 logger << logging::info <<
"Compute the Taylor expansion of the stiffened matrix."
637 << logging::LOGFLUSH;
639 std::vector<b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> >
640 d2_residue_d_dof_d_path(K_taylor_order);
641 residue_function.get_d2_residue_d_dof_d_path(
642 rdof, time, K, d_dof_and_time_d_path, d2_residue_d_dof_d_path, K_approximation_order,
643 K_h_scale * K_h_scale1);
647 for (
size_t i = 0; i != d2_residue_d_dof_d_path.size(); ++i) {
649 d2_residue_d_dof_d_path[i] *= -1.0 / s;
653 logger << logging::info <<
"Polynomial eigenvalue problem resolution" << logging::LOGFLUSH;
655 b2linalg::Vector<T, b2linalg::Vdense> eigvaluer(nb_eigeinvalue);
656 b2linalg::Vector<T, b2linalg::Vdense> eigvaluei(nb_eigeinvalue);
657 b2linalg::Matrix<T, b2linalg::Mrectangle> eigvector_red(nb_rdof, nb_eigeinvalue);
659 eigvector_red = eigenvector(
660 (
const b2linalg::Matrix<T, b2linalg::Msym_compressed_col_update_inv>&)(K),
'P',
661 d2_residue_d_dof_d_path,
'N', eigvaluer, eigvaluei, which, sigma);
663 logger << logging::info <<
"Compute the buckling displacement and modes" << logging::LOGFLUSH;
665 const int nonlinear_refinement = case_.get_int(
"NONLINEAR_REFINEMENT", 0);
667 for (
int j = 0; j != nb_eigeinvalue; ++j) {
668 if (std::abs(eigvaluei[j] / eigvaluer[j]) > tol_eigenvalue_imag) {
continue; }
669 b2linalg::Vector<double> dr(d_dof_and_time_d_path.size1());
670 dr(b2linalg::Interval(0, nb_rdof)) = rdof;
673 b2linalg::Vector<double> p(d_dof_and_time_d_path.size2());
675 for (
size_t i = 0; i != p.size(); ++i) {
676 s *= eigvaluer[j] / (i + 1);
679 dr += d_dof_and_time_d_path * p;
682 if (j < nonlinear_refinement) {
683 logger << logging::info
684 <<
"Compute the nonlinear refinement on the buckling value and modes " << j
685 <<
"." << logging::LOGFLUSH;
687 solve_nonlinear_refinement_sha2(
688 case_, residue_function, dr(Interval(0, nb_rdof)), dr[nb_rdof], eigvector_red[j],
691 solve_nonlinear_refinement(
692 case_, residue_function, dr(b2linalg::Interval(0, nb_rdof)), dr[nb_rdof],
693 eigvector_red[j], K);
697 b2linalg::Vector<double> d(nb_dof);
698 residue_function.get_solution(dr(b2linalg::Interval(0, nb_rdof)), dr[nb_rdof],
false, d);
699 b2linalg::Vector<double> ev(nb_dof);
700 ev = transposed(reduc_d_value_d_dof_trans) * eigvector_red[j];
701 ev *= 1.0 / ev.norm2();
704 solution.set_solution(
705 j, eigvaluer[j], eigvaluei[j], d, dr[nb_rdof],
706 b2linalg::Vector<T, b2linalg::Vdense_constref>::null,
707 b2linalg::Vector<T, b2linalg::Vdense_constref>::null, ev);
711 solution.terminate_case(
true, attributes);
712 case_.warn_on_non_used_key();
713 logger.LOG(logging::info,
"End of Taylor expansions buckling solver");
#define THROW
Definition b2exception.H:198
Interface to C++ representations of FE solvers.
virtual size_t get_number_of_stage() const =0
virtual double get_double(const std::string &key) const =0
virtual int get_int(const std::string &key) const =0
virtual CaseList & get_case_list()=0
Case * case_
This also.
Definition b2solver.H:93
Model * model_
Definition b2solver.H:91
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829
void get_forward_coefficient(int l, int z, int p, std::vector< double > &a)
Definition b2numerical_differentiation.C:1982