22#ifndef B2DYNAMIC_RESIDUE_FUNCTION_H_
23#define B2DYNAMIC_RESIDUE_FUNCTION_H_
25#include "b2ppconfig.h"
32#include "solvers/b2solver_utils.H"
33#include "solvers/b2static_nonlinear_utile.H"
35namespace b2000::solver {
37template <
typename T,
typename MATRIX_FORMAT>
38class DynamicResidueFunction;
40template <
typename T,
typename MATRIX_FORMAT>
41class DynamicResidueFunction :
public StaticResidueFunctionForTerminationTest<T> {
43 DynamicResidueFunction()
44 : logger(logging::
get_logger(
"solver.static_nonlinear.ResidueFunction")) {}
46 virtual void init(Model& model,
const AttributeList& attribute) = 0;
48 virtual void set_case(Case* case_) = 0;
50 virtual int get_order()
const = 0;
52 virtual b2linalg::SparseMatrixConnectivityType get_dof_connectivity_type()
const = 0;
54 virtual void save_solution(
55 b2linalg::Matrix<T, b2linalg::Mrectangle>& dof,
const double time,
const double dtime,
56 const RTable& attributes,
bool end_of_stage =
false,
57 bool unconverged_subcycle =
false) = 0;
59 virtual void get_residue(
60 const b2linalg::Matrix<T, b2linalg::Mrectangle>& dof_red,
const double time,
61 const double delta_time,
const EquilibriumSolution equilibrium_solution,
62 b2linalg::Vector<T, b2linalg::Vdense>& residue,
63 const b2linalg::Vector<double, b2linalg::Vdense>& d_residue_d_dof_coeff,
64 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& d_residue_d_dofc,
65 b2linalg::Vector<T, b2linalg::Vdense>& d_residue_d_time, SolverHints* solver_hints,
66 CorrectionTerminationTest<T>* termination_test = 0) = 0;
68 virtual const b2linalg::Index& get_dof_field() = 0;
70 typedef ObjectTypeIncomplete<DynamicResidueFunction> type_t;
74 logging::Logger& logger;
77template <
typename T,
typename MATRIX_FORMAT>
78typename DynamicResidueFunction<T, MATRIX_FORMAT>::type_t
79 DynamicResidueFunction<T, MATRIX_FORMAT>::type(
80 "DynamicResidueFunction", type_name<T, MATRIX_FORMAT>(),
81 StringList(
"DYNAMIC_RESIDUE_FUNCTION"), b2000::solver::module);
83template <
typename T,
typename MATRIX_FORMAT = b2linalg::Msymmetric>
84class DynamicOrderNResidueFunction :
public DynamicResidueFunction<T, MATRIX_FORMAT> {
86 typedef TypedNaturalBoundaryCondition<T, typename MATRIX_FORMAT::sparse_inversible> nbc_t;
87 typedef TypedEssentialBoundaryCondition<T> ebc_t;
88 typedef TypedModelReductionBoundaryCondition<T> mrbc_t;
90 DynamicOrderNResidueFunction()
91 : logger(logging::
get_logger(
"solver.dynamic_nonlinear.residue")),
100 constraint_has_penalty(false),
102 lagrange_mult_scale(1),
103 rcfo_only_spc(false) {}
105 void set_case(Case* case_) {}
107 void init(Model& model_,
const AttributeList& attribute) {
109 domain = &model->get_domain();
110 ebc = &
dynamic_cast<ebc_t&
>(model->get_essential_boundary_condition(ebc_t::type.get_subtype(
111 "TypedEssentialBoundaryConditionListComponent" + type_name<T>())));
112 mrbc = &
dynamic_cast<mrbc_t&
>(
113 model->get_model_reduction_boundary_condition(mrbc_t::type.get_subtype(
114 "TypedModelReductionBoundaryConditionListComponent" + type_name<T>())));
115 nbc = &
dynamic_cast<nbc_t&
>(model->get_natural_boundary_condition(nbc_t::type.get_subtype(
116 "TypedNaturalBoundaryConditionListComponent"
117 + type_name<T, typename MATRIX_FORMAT::sparse_inversible>())));
118 solution = &
dynamic_cast<SolutionDynamicNonlinear<T>&
>(model->get_solution());
119 number_of_dof = domain->get_number_of_dof();
120 nbc_sol.resize(number_of_dof);
121 fi.resize(number_of_dof);
123 constraint_has_penalty =
124 attribute.get_string(
"CONSTRAINT_METHOD",
"REDUCTION") ==
"PENALTY";
126 constraint_has_penalty |=
127 attribute.get_string(
"NONLINEAR_CONSTRAINT_METHOD",
"OTHER") ==
"PENALTY";
129 number_of_dof_red = mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1)
130 + (constraint_has_penalty ? 0 : ebc->get_size(
false));
132 if (constraint_has_penalty) {
133 penalty_factor = attribute.get_double(
"CONSTRAINT_PENALTY", 1e10);
135 if (attribute.get_bool(
"REMOVE_DEPENDENT_CONSTRAINTS",
false)) {
136 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_l_d_dof;
137 ebc->get_nonlinear_value(
138 fi, 0,
false, b2linalg::Vector<T, b2linalg::Vdense_ref>::null,
139 trans_d_l_d_dof, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0);
140 trans_d_l_d_dof.get_dep_columns(ebc_to_remove, 3e-13, 1.5);
141 number_of_dof_red -= ebc_to_remove.size();
142 if (!ebc_to_remove.empty()) {
143 DynamicResidueFunction<T, MATRIX_FORMAT>::logger
145 <<
" dependent constraints." << logging::LOGFLUSH;
148 penalty_factor = attribute.get_double(
"CONSTRAINT_PENALTY", 1);
149 if (attribute.get_string(
"NONLINEAR_CONSTRAINT_METHOD",
"OTHER") ==
"LAGRANGE") {
152 lagrange_mult_scale = attribute.get_double(
"LAGRANGE_MULT_SCALE_PENALTY", 1.0);
155 rcfo_only_spc = attribute.get_bool(
"RCFO_ONLY_SPC",
false);
157 && attribute.get_string(
"CONSTRAINT_METHOD",
"REDUCTION") ==
"REDUCTION") {
158 Exception() <<
"It is not possible to compute the reaction "
159 "forces with rcfo_only_spc=yes and "
160 "constraint_method=reduction (which is the default). "
161 "Instead, set constraint_method either to lagrange, "
162 "augmented_lagrange, or penalty."
167 void mrbc_get_nonlinear_value(
168 const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof,
double time,
169 EquilibriumSolution equilibrium_solution, b2linalg::Vector<T, b2linalg::Vdense_ref> value,
170 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& d_value_d_dof_trans,
171 b2linalg::Vector<T, b2linalg::Vdense_ref> d_value_d_time, SolverHints* solver_hints) {
172 mrbc->get_nonlinear_value(
173 dof, time, equilibrium_solution, value, d_value_d_dof_trans,
174 b2linalg::Matrix<T, b2linalg::Mrectangle_ref>(d_value_d_time), solver_hints);
177 size_t get_number_of_dof() {
178 return mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1)
179 + (constraint_has_penalty ? 0 : ebc->get_size(
false) - ebc_to_remove.size());
182 size_t get_number_of_non_lagrange_dof() {
183 return mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1);
186 b2linalg::SparseMatrixConnectivityType get_dof_connectivity_type()
const {
187 return domain->get_dof_connectivity_type();
190 int get_order()
const {
return domain->get_value_info().size() - 1; }
193 b2linalg::Matrix<T, b2linalg::Mrectangle>& dof_red,
const double time,
const double dtime,
194 const RTable& attributes,
bool end_of_stage =
false,
bool unconverged_subcycle =
false) {
195 const size_t mrbc_size =
196 mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1);
197 b2linalg::Interval disp_range(0, mrbc_size);
198 b2linalg::Matrix<T, b2linalg::Mrectangle> dof(number_of_dof, dof_red.size2());
199 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_r_d_dof;
200 b2linalg::Matrix<T, b2linalg::Mrectangle> d_r_d_time(number_of_dof, dof_red.size2() - 1);
201 mrbc->get_nonlinear_value(
202 dof_red[0](disp_range), time,
true, dof[0], trans_d_r_d_dof, d_r_d_time, 0);
203 for (
size_t j = 1; j < dof.size2(); ++j) {
204 dof[j] = transposed(trans_d_r_d_dof) * dof_red[j](disp_range);
205 dof[j] += d_r_d_time[j - 1];
210 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_l_d_dof;
211 b2linalg::Vector<T> l(ebc->get_size(
false));
212 ebc->get_nonlinear_value(
213 dof[0], time,
false, l, trans_d_l_d_dof,
214 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0);
215 if (!ebc_to_remove.empty()) {
216 l.remove(ebc_to_remove);
217 trans_d_l_d_dof.remove_col(ebc_to_remove);
220 if (constraint_has_penalty) {
221 l *= -penalty_factor;
223 b2linalg::Interval lagrange_mult_range(mrbc_size, dof_red.size1());
224 if (MATRIX_FORMAT::symmetric && penalty_factor != 0) {
227 l *= -penalty_factor;
228 l += -lagrange_mult_scale * dof_red[0](lagrange_mult_range);
230 l = -lagrange_mult_scale * dof_red[0](lagrange_mult_range);
233 for (
size_t j = 0; j != trans_d_l_d_dof.size2(); ++j) {
234 if (trans_d_l_d_dof.get_nb_nonzero(j) != 1) { l[j] = 0; }
236 fi = trans_d_l_d_dof * l;
238 if (unconverged_subcycle) {
239 solution->set_solution(dof, time, nbc_sol, fi, unconverged_subcycle);
242 solution->new_cycle(end_of_stage);
243 solution->set_solution(dof, time, nbc_sol, fi);
245 typename SolutionDynamicNonlinear<T>::gradient_container gc =
246 solution->get_gradient_container();
247 domain->set_dof(dof);
248 EquilibriumSolution es(1, 0);
249 solver_utile.get_elements_values(
250 dof, time, dtime, es,
false, trans_d_r_d_dof, d_r_d_time[0],
251 b2linalg::Vector<double, b2linalg::Vdense>::null, *model,
252 b2linalg::Vector<T, b2linalg::Vdense>::null,
253 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null,
254 b2linalg::Vector<T, b2linalg::Vdense>::null, gc.get(), 0, logger, 0);
255 std::string domain_state_id = solution->get_domain_state_id();
256 if (!domain_state_id.empty()) { domain->save_state(domain_state_id); }
257 solution->terminate_cycle(time, dtime, attributes);
258 if (end_of_stage) { solution->terminate_stage(
true); }
262 const b2linalg::Matrix<T, b2linalg::Mrectangle>& dof_red,
const double time,
263 const double delta_time,
const EquilibriumSolution equilibrium_solution,
264 b2linalg::Vector<T, b2linalg::Vdense>& residue,
265 const b2linalg::Vector<double, b2linalg::Vdense>& d_residue_d_dof_coeff,
266 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& d_residue_d_dofc,
267 b2linalg::Vector<T, b2linalg::Vdense>& d_residue_d_time, SolverHints* solver_hints,
268 CorrectionTerminationTest<T>* termination_test = 0) {
269 b2linalg::Interval disp_range(
270 0, mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1));
271 b2linalg::Interval lagrange_mult_range(
272 mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1),
274 if (!residue.is_null()) { residue.set_zero(); }
275 if (!d_residue_d_dofc.is_null()) { d_residue_d_dofc.set_zero_same_struct(); }
277 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_r_d_dof;
278 b2linalg::Matrix<T, b2linalg::Mrectangle> d_r_d_time(number_of_dof, dof_red.size2() - 1);
279 b2linalg::Matrix<T, b2linalg::Mrectangle> dof(number_of_dof, dof_red.size2());
280 mrbc->get_nonlinear_value(
281 dof_red[0](disp_range), time, equilibrium_solution, dof[0], trans_d_r_d_dof,
282 d_r_d_time, solver_hints);
283 for (
size_t j = 1; j < dof.size2(); ++j) {
284 dof[j] = transposed(trans_d_r_d_dof) * dof_red[j](disp_range);
285 dof[j] += d_r_d_time[j - 1];
287 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> d_fe_d_dof;
288 b2linalg::Vector<T, b2linalg::Vdense> d_fe_d_time(number_of_dof);
290 nbc->get_nonlinear_value(
291 dof[0], time, equilibrium_solution,
292 residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
293 : b2linalg::Vector<T, b2linalg::Vdense_ref>(nbc_sol),
294 d_residue_d_dofc.is_null()
295 ? b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null
297 d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
298 : b2linalg::Vector<T, b2linalg::Vdense_ref>(d_fe_d_time),
300 if (termination_test && !residue.is_null()) { termination_test->add_flux(nbc_sol); }
302 d_fe_d_time = -d_fe_d_time;
303 if (d_fe_d_dof.size1() != 0) {
304 d_residue_d_dofc += -(trans_d_r_d_dof * d_fe_d_dof * transposed(trans_d_r_d_dof));
307 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_l_d_dof;
308 b2linalg::Vector<T> l;
310 if (constraint_has_penalty) {
311 if (!residue.is_null()) { l.resize(ebc->get_size(
false)); }
312 ebc->get_nonlinear_value(
313 dof[0], time, equilibrium_solution,
314 (residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
315 : b2linalg::Vector<T, b2linalg::Vdense_ref>(l)),
316 trans_d_l_d_dof, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, solver_hints);
318 if (ebc_to_remove.empty()) {
319 ebc->get_nonlinear_value(
320 dof[0], time, equilibrium_solution,
321 (residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
322 : residue(lagrange_mult_range)),
324 (d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
325 : d_residue_d_time(lagrange_mult_range)),
328 b2linalg::Vector<T> l(residue.is_null() ? 0 : ebc->get_size(false));
329 ebc->get_nonlinear_value(
330 dof[0], time, equilibrium_solution,
331 (residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
332 : b2linalg::Vector<T, b2linalg::Vdense_ref>(l)),
334 (d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
335 : d_residue_d_time(lagrange_mult_range)),
337 if (!residue.is_null()) {
338 l.remove(ebc_to_remove);
339 residue(lagrange_mult_range) = l;
341 trans_d_l_d_dof.remove_col(ebc_to_remove);
343 if (!d_residue_d_time.is_null()) {
344 d_residue_d_time(lagrange_mult_range) +=
345 transposed(trans_d_l_d_dof) * d_r_d_time[0];
349 if (!d_residue_d_time.is_null() && d_fe_d_dof.size1()) {
350 d_fe_d_time -= d_fe_d_dof * d_r_d_time[0];
353 solver_utile.get_elements_values(
354 dof, time, delta_time, equilibrium_solution,
false, trans_d_r_d_dof, d_r_d_time[0],
355 d_residue_d_dof_coeff, *model, fi, d_residue_d_dofc,
356 d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
357 : b2linalg::Vector<T, b2linalg::Vdense_ref>(d_fe_d_time),
358 0, solver_hints, logger, termination_test);
360 if (!residue.is_null()) {
361 b2linalg::Vector<T> tmp = fi;
362 if (constraint_has_penalty) {
363 tmp += (trans_d_l_d_dof * l) * penalty_factor;
365 if (MATRIX_FORMAT::symmetric && penalty_factor != 0) {
368 b2linalg::Vector<T> tmp1;
369 tmp1 = residue(lagrange_mult_range) * penalty_factor;
370 tmp1 += dof_red[0](lagrange_mult_range) * lagrange_mult_scale;
371 tmp += trans_d_l_d_dof * tmp1;
374 lagrange_mult_scale * (trans_d_l_d_dof * dof_red[0](lagrange_mult_range));
376 residue(lagrange_mult_range) *= lagrange_mult_scale;
378 residue(disp_range) = trans_d_r_d_dof * tmp;
380 if (!d_residue_d_dofc.is_null()) {
381 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_LR;
382 trans_LR = trans_d_r_d_dof * trans_d_l_d_dof;
383 if (penalty_factor != 0 && (constraint_has_penalty || MATRIX_FORMAT::symmetric)) {
386 d_residue_d_dofc(disp_range, disp_range) +=
387 (trans_LR * transposed(trans_LR)) * penalty_factor;
389 if (!constraint_has_penalty) {
390 trans_LR *= lagrange_mult_scale;
391 b2linalg::Matrix<T, b2linalg::Mcompressed_col> LR = transposed(trans_LR);
392 d_residue_d_dofc(lagrange_mult_range, disp_range) += LR;
393 if (!MATRIX_FORMAT::symmetric) {
394 d_residue_d_dofc(disp_range, lagrange_mult_range) += trans_LR;
398 if (!d_residue_d_time.is_null()) {
399 d_residue_d_time(disp_range) = trans_d_r_d_dof * d_fe_d_time;
403 const b2linalg::Index& get_dof_field() {
404 if (dof_field.empty()
405 && mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1) != 0) {
406 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_r_d_dof;
407 mrbc->get_nonlinear_value(
408 b2linalg::Vector<double, b2linalg::Vdense_constref>::null, 0,
false,
409 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, trans_d_r_d_dof,
410 b2linalg::Matrix<T, b2linalg::Mrectangle_ref>::null, 0);
411 dof_field.resize(trans_d_r_d_dof.size1());
412 const b2linalg::Index& df = model->get_domain().get_dof_field().second;
416 const size_t s = trans_d_r_d_dof.size2();
417 trans_d_r_d_dof.get_values(colind, rowind, value);
418 const size_t* rowind_ptr = rowind;
419 for (
size_t j = 0; j != s; ++j) {
420 const size_t* rowind_end = rowind + colind[j + 1];
421 for (; rowind_ptr != rowind_end; ++rowind_ptr) {
422 dof_field[*rowind_ptr] = std::max(dof_field[*rowind_ptr], df[j]);
429 typedef ObjectTypeComplete<
430 DynamicOrderNResidueFunction,
typename DynamicResidueFunction<T, MATRIX_FORMAT>::type_t>
435 logging::Logger& logger;
436 size_t number_of_dof;
437 size_t number_of_dof_red;
443 SolutionDynamicNonlinear<T>* solution;
444 b2linalg::Vector<T, b2linalg::Vdense> fi;
445 b2linalg::Vector<T, b2linalg::Vdense> nbc_sol;
446 b2linalg::Index ebc_to_remove;
447 SolverUtils<T, MATRIX_FORMAT> solver_utile;
448 bool constraint_has_penalty;
449 double penalty_factor;
450 double lagrange_mult_scale;
452 b2linalg::Index dof_field;
455template <
typename T,
typename MATRIX_FORMAT>
456typename DynamicOrderNResidueFunction<T, MATRIX_FORMAT>::type_t
457 DynamicOrderNResidueFunction<T, MATRIX_FORMAT>::type(
458 "DynamicOrderNResidueFunction", type_name<T, MATRIX_FORMAT>(),
460 "ORDER_ONE_DYNAMIC_RESIDUE_FUNCTION",
"ORDER_TWO_DYNAMIC_RESIDUE_FUNCTION",
461 "ORDER_N_DYNAMIC_RESIDUE_FUNCTION"),
462 b2000::solver::module, &DynamicResidueFunction<T, MATRIX_FORMAT>::type);
464template <
typename T,
typename MATRIX_FORMAT = b2linalg::Msymmetric>
465class DynamicOrderTwoRayleighDampingResidueFunction
466 :
public DynamicOrderNResidueFunction<T, MATRIX_FORMAT> {
468 typedef DynamicOrderNResidueFunction<T, MATRIX_FORMAT> parent;
470 void init(Model& model,
const AttributeList& attribute) {
471 parent::init(model, attribute);
472 if (parent::get_order() != 2) {
473 Exception() <<
"Rayleigh damping can only be used for models "
478 rayleigh_damping_alpha, rayleigh_damping_beta, *parent::model, parent::logger);
481 void set_case(Case* case_) {
482 rayleigh_damping_alpha = case_->get_double(
"RAYLEIGH_ALPHA");
483 rayleigh_damping_beta = case_->get_double(
"RAYLEIGH_BETA");
487 b2linalg::Matrix<T, b2linalg::Mrectangle>& dof_red,
const double time,
const double dtime,
488 const RTable& attributes,
bool end_of_stage =
false,
bool unconverged_subcycle =
false) {
489 const size_t mrbc_size =
490 parent::mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1);
491 b2linalg::Interval disp_range(0, mrbc_size);
492 b2linalg::Matrix<T, b2linalg::Mrectangle> dof(parent::number_of_dof, dof_red.size2());
493 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_r_d_dof;
494 b2linalg::Matrix<T, b2linalg::Mrectangle> d_r_d_time(
495 parent::number_of_dof, dof_red.size2() - 1);
496 parent::mrbc->get_nonlinear_value(
497 dof_red[0](disp_range), time,
true, dof[0], trans_d_r_d_dof, d_r_d_time, 0);
498 for (
size_t j = 1; j < dof.size2(); ++j) {
499 dof[j] = transposed(trans_d_r_d_dof) * dof_red[j](disp_range);
500 dof[j] += d_r_d_time[j - 1];
502 if (parent::rcfo_only_spc) {
505 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_l_d_dof;
506 b2linalg::Vector<T> l(parent::ebc->get_size(
false));
507 parent::ebc->get_nonlinear_value(
508 dof[0], time,
false, l, trans_d_l_d_dof,
509 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0);
510 if (!parent::ebc_to_remove.empty()) {
511 l.remove(parent::ebc_to_remove);
512 trans_d_l_d_dof.remove_col(parent::ebc_to_remove);
515 if (parent::constraint_has_penalty) {
516 l *= -parent::penalty_factor;
518 b2linalg::Interval lagrange_mult_range(mrbc_size, dof_red.size1());
519 if (MATRIX_FORMAT::symmetric && parent::penalty_factor != 0) {
522 l *= -parent::penalty_factor;
523 l += -parent::lagrange_mult_scale * dof_red[0](lagrange_mult_range);
525 l = -parent::lagrange_mult_scale * dof_red[0](lagrange_mult_range);
528 for (
size_t j = 0; j != trans_d_l_d_dof.size2(); ++j) {
529 if (trans_d_l_d_dof.get_nb_nonzero(j) != 1) { l[j] = 0; }
531 parent::fi = trans_d_l_d_dof * l;
533 if (unconverged_subcycle) {
534 parent::solution->set_solution(
535 dof, time, parent::nbc_sol, parent::fi, unconverged_subcycle);
538 parent::solution->new_cycle(end_of_stage);
539 parent::solution->set_solution(dof, time, parent::nbc_sol, parent::fi);
541 typename SolutionDynamicNonlinear<T>::gradient_container gc =
542 parent::solution->get_gradient_container();
543 parent::domain->set_dof(dof);
544 EquilibriumSolution es(1, 0);
546 solver_utile.get_elements_values(
547 dof, time, dtime, es,
false, trans_d_r_d_dof, d_r_d_time[0],
548 b2linalg::Vector<double, b2linalg::Vdense>::null, *parent::model,
549 b2linalg::Vector<T, b2linalg::Vdense>::null,
550 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null,
551 b2linalg::Vector<T, b2linalg::Vdense>::null, gc.get(), 0, parent::logger, 0, energy);
552 parent::solution->set_value(
"RAYLEIGH_KINEMATIC_ENERGY", energy[0]);
553 parent::solution->set_value(
"RAYLEIGH_RATE_DAMPING_DISSIPATED_ENERGY", energy[1]);
554 parent::solution->set_value(
"RAYLEIGH_DAMPING_DISSIPATED_ENERGY", energy[2]);
555 std::string domain_state_id = parent::solution->get_domain_state_id();
556 if (!domain_state_id.empty()) { parent::domain->save_state(domain_state_id); }
557 parent::solution->terminate_cycle(time, dtime, attributes);
558 if (end_of_stage) { parent::solution->terminate_stage(
true); }
562 const b2linalg::Matrix<T, b2linalg::Mrectangle>& dof_red,
const double time,
563 const double delta_time,
const EquilibriumSolution equilibrium_solution,
564 b2linalg::Vector<T, b2linalg::Vdense>& residue,
565 const b2linalg::Vector<double, b2linalg::Vdense>& d_residue_d_dof_coeff,
566 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& d_residue_d_dofc,
567 b2linalg::Vector<T, b2linalg::Vdense>& d_residue_d_time, SolverHints* solver_hints,
568 CorrectionTerminationTest<T>* termination_test = 0) {
570 b2linalg::Interval disp_range(
571 0, parent::mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1));
572 b2linalg::Interval lagrange_mult_range(
573 parent::mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1),
574 parent::number_of_dof_red);
576 if (!residue.is_null()) { residue.set_zero(); }
577 if (!d_residue_d_dofc.is_null()) { d_residue_d_dofc.set_zero_same_struct(); }
579 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_r_d_dof;
580 b2linalg::Matrix<T, b2linalg::Mrectangle> d_r_d_time(
581 parent::domain->get_number_of_dof(), dof_red.size2() - 1);
582 b2linalg::Matrix<T, b2linalg::Mrectangle> dof(parent::number_of_dof, dof_red.size2());
583 parent::mrbc->get_nonlinear_value(
584 dof_red[0](disp_range), time, equilibrium_solution, dof[0], trans_d_r_d_dof,
585 d_r_d_time, solver_hints);
586 for (
size_t j = 1; j < dof.size2(); ++j) {
587 dof[j] = transposed(trans_d_r_d_dof) * dof_red[j](disp_range);
588 dof[j] += d_r_d_time[j - 1];
590 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> d_fe_d_dof;
591 b2linalg::Vector<T, b2linalg::Vdense> d_fe_d_time(parent::domain->get_number_of_dof());
592 parent::nbc_sol.set_zero();
593 parent::nbc->get_nonlinear_value(
594 dof[0], time, equilibrium_solution,
595 residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
596 : b2linalg::Vector<T, b2linalg::Vdense_ref>(parent::nbc_sol),
597 d_residue_d_dofc.is_null()
598 ? b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null
600 d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
601 : b2linalg::Vector<T, b2linalg::Vdense_ref>(d_fe_d_time),
603 if (termination_test && !residue.is_null()) { termination_test->add_flux(parent::nbc_sol); }
604 parent::fi = -parent::nbc_sol;
605 d_fe_d_time = -d_fe_d_time;
606 if (d_fe_d_dof.size1() != 0) {
607 d_residue_d_dofc += -(trans_d_r_d_dof * d_fe_d_dof * transposed(trans_d_r_d_dof));
610 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_l_d_dof;
611 b2linalg::Vector<T> l;
613 if (parent::constraint_has_penalty) {
614 if (!residue.is_null()) { l.resize(parent::ebc->get_size(
false)); }
615 parent::ebc->get_nonlinear_value(
616 dof[0], time, equilibrium_solution,
617 (residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
618 : b2linalg::Vector<T, b2linalg::Vdense_ref>(l)),
619 trans_d_l_d_dof, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, solver_hints);
621 if (parent::ebc_to_remove.empty()) {
622 parent::ebc->get_nonlinear_value(
623 dof[0], time, equilibrium_solution,
624 residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
625 : residue(lagrange_mult_range),
627 d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
628 : d_residue_d_time(lagrange_mult_range),
631 b2linalg::Vector<T> l(residue.is_null() ? 0 : parent::ebc->get_size(false));
632 parent::ebc->get_nonlinear_value(
633 dof[0], time, equilibrium_solution,
634 (residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
635 : b2linalg::Vector<T, b2linalg::Vdense_ref>(l)),
637 (d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
638 : d_residue_d_time(lagrange_mult_range)),
640 if (!residue.is_null()) {
641 l.remove(parent::ebc_to_remove);
642 residue(lagrange_mult_range) = l;
644 trans_d_l_d_dof.remove_col(parent::ebc_to_remove);
646 if (!d_residue_d_time.is_null()) {
647 d_residue_d_time(lagrange_mult_range) +=
648 transposed(trans_d_l_d_dof) * d_r_d_time[0];
652 if (!d_residue_d_time.is_null() && d_fe_d_dof.size1()) {
653 d_fe_d_time -= d_fe_d_dof * d_r_d_time[0];
656 solver_utile.get_elements_values(
657 dof, time, delta_time, equilibrium_solution,
false, trans_d_r_d_dof, d_r_d_time[0],
658 d_residue_d_dof_coeff, *parent::model, parent::fi, d_residue_d_dofc,
659 d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
660 : b2linalg::Vector<T, b2linalg::Vdense_ref>(d_fe_d_time),
661 0, solver_hints, parent::logger, termination_test);
663 if (!residue.is_null()) {
664 b2linalg::Vector<T> tmp = parent::fi;
665 if (parent::constraint_has_penalty) {
666 tmp += (trans_d_l_d_dof * l) * parent::penalty_factor;
668 if (MATRIX_FORMAT::symmetric && parent::penalty_factor != 0) {
671 b2linalg::Vector<T> tmp1;
672 tmp1 = residue(lagrange_mult_range) * parent::penalty_factor;
673 tmp1 += dof_red[0](lagrange_mult_range) * parent::lagrange_mult_scale;
674 tmp += trans_d_l_d_dof * tmp1;
676 tmp += parent::lagrange_mult_scale
677 * (trans_d_l_d_dof * dof_red[0](lagrange_mult_range));
679 residue(lagrange_mult_range) *= parent::lagrange_mult_scale;
681 residue(disp_range) = trans_d_r_d_dof * tmp;
683 if (!d_residue_d_dofc.is_null()) {
684 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_LR;
685 trans_LR = trans_d_r_d_dof * trans_d_l_d_dof;
686 if (parent::penalty_factor != 0
687 && (parent::constraint_has_penalty || MATRIX_FORMAT::symmetric)) {
690 d_residue_d_dofc(disp_range, disp_range) +=
691 (trans_LR * transposed(trans_LR)) * parent::penalty_factor;
693 if (!parent::constraint_has_penalty) {
694 trans_LR *= parent::lagrange_mult_scale;
695 b2linalg::Matrix<T, b2linalg::Mcompressed_col> LR = transposed(trans_LR);
696 d_residue_d_dofc(lagrange_mult_range, disp_range) += LR;
697 if (!MATRIX_FORMAT::symmetric) {
698 d_residue_d_dofc(disp_range, lagrange_mult_range) += trans_LR;
702 if (!d_residue_d_time.is_null()) {
703 d_residue_d_time(disp_range) = trans_d_r_d_dof * d_fe_d_time;
707 typedef ObjectTypeComplete<
708 DynamicOrderTwoRayleighDampingResidueFunction,
709 typename DynamicResidueFunction<T, MATRIX_FORMAT>::type_t>
714 double rayleigh_damping_alpha;
715 double rayleigh_damping_beta;
716 SolverUtilsOrderTwoRayleighDamping<T, MATRIX_FORMAT> solver_utile;
719template <
typename T,
typename MATRIX_FORMAT>
720typename DynamicOrderTwoRayleighDampingResidueFunction<T, MATRIX_FORMAT>::type_t
721 DynamicOrderTwoRayleighDampingResidueFunction<T, MATRIX_FORMAT>::type(
722 "DynamicOrderTwoRayleighDampingResidueFunction", type_name<T, MATRIX_FORMAT>(),
723 StringList(
"RAYLEIGH_DAMPING_DYNAMIC_RESIDUE_FUNCTION"), b2000::solver::module,
724 &DynamicResidueFunction<T, MATRIX_FORMAT>::type);
726template <
typename T,
typename MATRIX_FORMAT = b2linalg::Msymmetric>
727class QuasistaticViscousDampingResidueFunction
728 :
public DynamicOrderNResidueFunction<T, MATRIX_FORMAT> {
730 typedef DynamicOrderNResidueFunction<T, MATRIX_FORMAT> parent;
732 void init(Model& model,
const AttributeList& attribute) {
733 parent::init(model, attribute);
734 if (parent::get_order() != 2) {
735 Exception() <<
"Quasi-static viscous damping can only be "
736 "used for models of order 2"
740 rayleigh_damping_alpha, rayleigh_damping_beta, *parent::model, parent::logger);
743 void set_case(Case* case_) {
744 const char* alpha_s =
"RAYLEIGH_ALPHA";
745 const char* beta_s =
"RAYLEIGH_BETA";
746 if (case_->has_key(alpha_s) && case_->has_key(beta_s)) {
747 rayleigh_damping_alpha = case_->get_double(
"RAYLEIGH_ALPHA");
748 rayleigh_damping_beta = case_->get_double(
"RAYLEIGH_BETA");
749 dissipated_energy_fraction = 0;
751 dissipated_energy_fraction = case_->get_double(
"DISSIPATED_ENERGY_FRACTION", 1.e-4);
752 rayleigh_damping_alpha = 1e-10;
753 rayleigh_damping_beta = 0;
757 int get_order()
const {
return 1; }
760 b2linalg::Matrix<T, b2linalg::Mrectangle>& dof_red,
const double time,
const double dtime,
761 const RTable& attributes,
bool end_of_stage =
false,
bool unconverged_subcycle =
false) {
762 const size_t mrbc_size =
763 parent::mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1);
764 b2linalg::Interval disp_range(0, mrbc_size);
765 b2linalg::Matrix<T, b2linalg::Mrectangle> dof(parent::number_of_dof, dof_red.size2());
766 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_r_d_dof;
767 b2linalg::Matrix<T, b2linalg::Mrectangle> d_r_d_time(
768 parent::number_of_dof, dof_red.size2() - 1);
769 parent::mrbc->get_nonlinear_value(
770 dof_red[0](disp_range), time,
true, dof[0], trans_d_r_d_dof, d_r_d_time, 0);
771 for (
size_t j = 1; j < dof.size2(); ++j) {
772 dof[j] = transposed(trans_d_r_d_dof) * dof_red[j](disp_range);
773 dof[j] += d_r_d_time[j - 1];
775 if (parent::rcfo_only_spc) {
778 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_l_d_dof;
779 b2linalg::Vector<T> l(parent::ebc->get_size(
false));
780 parent::ebc->get_nonlinear_value(
781 dof[0], time,
false, l, trans_d_l_d_dof,
782 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0);
783 if (!parent::ebc_to_remove.empty()) {
784 l.remove(parent::ebc_to_remove);
785 trans_d_l_d_dof.remove_col(parent::ebc_to_remove);
788 if (parent::constraint_has_penalty) {
789 l *= -parent::penalty_factor;
791 b2linalg::Interval lagrange_mult_range(mrbc_size, dof_red.size1());
792 if (MATRIX_FORMAT::symmetric && parent::penalty_factor != 0) {
795 l *= -parent::penalty_factor;
796 l += -parent::lagrange_mult_scale * dof_red[0](lagrange_mult_range);
798 l = -parent::lagrange_mult_scale * dof_red[0](lagrange_mult_range);
801 for (
size_t j = 0; j != trans_d_l_d_dof.size2(); ++j) {
802 if (trans_d_l_d_dof.get_nb_nonzero(j) != 1) { l[j] = 0; }
804 parent::fi = trans_d_l_d_dof * l;
806 if (unconverged_subcycle) {
807 parent::solution->set_solution(
808 dof, time, parent::nbc_sol, parent::fi, unconverged_subcycle);
811 parent::solution->new_cycle(end_of_stage);
812 parent::solution->set_solution(dof, time, parent::nbc_sol, parent::fi);
814 typename SolutionDynamicNonlinear<T>::gradient_container gc =
815 parent::solution->get_gradient_container();
816 parent::domain->set_dof(dof);
817 EquilibriumSolution es(1, 0);
819 solver_utile.get_elements_values(
820 dof, time, dtime, es,
false, trans_d_r_d_dof, d_r_d_time[0],
821 b2linalg::Vector<double, b2linalg::Vdense>::null, *parent::model,
822 b2linalg::Vector<T, b2linalg::Vdense>::null,
823 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null,
824 b2linalg::Vector<T, b2linalg::Vdense>::null, gc.get(), 0, parent::logger, 0, energy);
825 parent::solution->set_value(
"RAYLEIGH_KINEMATIC_ENERGY", energy[0]);
826 parent::solution->set_value(
"RAYLEIGH_RATE_DAMPING_DISSIPATED_ENERGY", energy[1]);
827 parent::solution->set_value(
"RAYLEIGH_DAMPING_DISSIPATED_ENERGY", energy[2]);
828 if (dissipated_energy_fraction != 0) {
830 for (
size_t i = 0; i != dof.size1(); ++i) {
833 res += dof(i, 0) * (parent::nbc_sol[i] + parent::fi[i]);
835 double sfactor = dissipated_energy_fraction * res / (energy[1] * dtime);
836 parent::logger <<
logging::debug <<
"scale factor for the stabilised method "
837 << sfactor * 1e-10 << logging::LOGFLUSH;
838 solver_utile.scale_raylay_damping(sfactor);
839 dissipated_energy_fraction = 0;
841 std::string domain_state_id = parent::solution->get_domain_state_id();
842 if (!domain_state_id.empty()) { parent::domain->save_state(domain_state_id); }
843 parent::solution->terminate_cycle(time, dtime, attributes);
844 if (end_of_stage) { parent::solution->terminate_stage(
true); }
848 const b2linalg::Matrix<T, b2linalg::Mrectangle>& dof_red,
const double time,
849 const double delta_time,
const EquilibriumSolution equilibrium_solution,
850 b2linalg::Vector<T, b2linalg::Vdense>& residue,
851 const b2linalg::Vector<double, b2linalg::Vdense>& d_residue_d_dof_coeff,
852 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& d_residue_d_dofc,
853 b2linalg::Vector<T, b2linalg::Vdense>& d_residue_d_time, SolverHints* solver_hints,
854 CorrectionTerminationTest<T>* termination_test = 0) {
856 b2linalg::Interval disp_range(
857 0, parent::mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1));
858 b2linalg::Interval lagrange_mult_range(
859 parent::mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1),
860 parent::number_of_dof_red);
862 if (!residue.is_null()) { residue.set_zero(); }
863 if (!d_residue_d_dofc.is_null()) { d_residue_d_dofc.set_zero_same_struct(); }
865 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_r_d_dof;
866 b2linalg::Matrix<T, b2linalg::Mrectangle> d_r_d_time(
867 parent::domain->get_number_of_dof(), dof_red.size2() - 1);
868 b2linalg::Matrix<T, b2linalg::Mrectangle> dof(parent::number_of_dof, dof_red.size2());
869 parent::mrbc->get_nonlinear_value(
870 dof_red[0](disp_range), time, equilibrium_solution, dof[0], trans_d_r_d_dof,
871 d_r_d_time, solver_hints);
872 for (
size_t j = 1; j < dof.size2(); ++j) {
873 dof[j] = transposed(trans_d_r_d_dof) * dof_red[j](disp_range);
874 dof[j] += d_r_d_time[j - 1];
876 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> d_fe_d_dof;
877 b2linalg::Vector<T, b2linalg::Vdense> d_fe_d_time(parent::domain->get_number_of_dof());
878 parent::nbc_sol.set_zero();
879 parent::nbc->get_nonlinear_value(
880 dof[0], time, equilibrium_solution,
881 residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
882 : b2linalg::Vector<T, b2linalg::Vdense_ref>(parent::nbc_sol),
883 d_residue_d_dofc.is_null()
884 ? b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null
886 d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
887 : b2linalg::Vector<T, b2linalg::Vdense_ref>(d_fe_d_time),
889 if (termination_test && !residue.is_null()) { termination_test->add_flux(parent::nbc_sol); }
890 parent::fi = -parent::nbc_sol;
891 d_fe_d_time = -d_fe_d_time;
892 if (d_fe_d_dof.size1() != 0) {
893 d_residue_d_dofc += -(trans_d_r_d_dof * d_fe_d_dof * transposed(trans_d_r_d_dof));
896 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_l_d_dof;
897 b2linalg::Vector<T> l;
899 if (parent::constraint_has_penalty) {
900 if (!residue.is_null()) { l.resize(parent::ebc->get_size(
false)); }
901 parent::ebc->get_nonlinear_value(
902 dof[0], time, equilibrium_solution,
903 (residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
904 : b2linalg::Vector<T, b2linalg::Vdense_ref>(l)),
905 trans_d_l_d_dof, b2linalg::Vector<T, b2linalg::Vdense_ref>::null, solver_hints);
907 if (parent::ebc_to_remove.empty()) {
908 parent::ebc->get_nonlinear_value(
909 dof[0], time, equilibrium_solution,
910 residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
911 : residue(lagrange_mult_range),
913 d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
914 : d_residue_d_time(lagrange_mult_range),
917 b2linalg::Vector<T> l(residue.is_null() ? 0 : parent::ebc->get_size(false));
918 parent::ebc->get_nonlinear_value(
919 dof[0], time, equilibrium_solution,
920 (residue.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
921 : b2linalg::Vector<T, b2linalg::Vdense_ref>(l)),
923 (d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
924 : d_residue_d_time(lagrange_mult_range)),
926 if (!residue.is_null()) {
927 l.remove(parent::ebc_to_remove);
928 residue(lagrange_mult_range) = l;
930 trans_d_l_d_dof.remove_col(parent::ebc_to_remove);
932 if (!d_residue_d_time.is_null()) {
933 d_residue_d_time(lagrange_mult_range) +=
934 transposed(trans_d_l_d_dof) * d_r_d_time[0];
938 if (!d_residue_d_time.is_null() && d_fe_d_dof.size1()) {
939 d_fe_d_time -= d_fe_d_dof * d_r_d_time[0];
942 solver_utile.get_elements_values(
943 dof, time, delta_time, equilibrium_solution,
false, trans_d_r_d_dof, d_r_d_time[0],
944 d_residue_d_dof_coeff, *parent::model, parent::fi, d_residue_d_dofc,
945 d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense_ref>::null
946 : b2linalg::Vector<T, b2linalg::Vdense_ref>(d_fe_d_time),
947 0, solver_hints, parent::logger, termination_test);
949 if (!residue.is_null()) {
950 b2linalg::Vector<T> tmp = parent::fi;
951 if (parent::constraint_has_penalty) {
952 tmp += (trans_d_l_d_dof * l) * parent::penalty_factor;
954 if (MATRIX_FORMAT::symmetric && parent::penalty_factor != 0) {
957 b2linalg::Vector<T> tmp1;
958 tmp1 = residue(lagrange_mult_range) * parent::penalty_factor;
959 tmp1 += dof_red[0](lagrange_mult_range) * parent::lagrange_mult_scale;
960 tmp += trans_d_l_d_dof * tmp1;
962 tmp += parent::lagrange_mult_scale
963 * (trans_d_l_d_dof * dof_red[0](lagrange_mult_range));
965 residue(lagrange_mult_range) *= parent::lagrange_mult_scale;
967 residue(disp_range) = trans_d_r_d_dof * tmp;
969 if (!d_residue_d_dofc.is_null()) {
970 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_LR;
971 trans_LR = trans_d_r_d_dof * trans_d_l_d_dof;
972 if (parent::penalty_factor != 0
973 && (parent::constraint_has_penalty || MATRIX_FORMAT::symmetric)) {
976 d_residue_d_dofc(disp_range, disp_range) +=
977 (trans_LR * transposed(trans_LR)) * parent::penalty_factor;
979 if (!parent::constraint_has_penalty) {
980 trans_LR *= parent::lagrange_mult_scale;
981 b2linalg::Matrix<T, b2linalg::Mcompressed_col> LR = transposed(trans_LR);
982 d_residue_d_dofc(lagrange_mult_range, disp_range) += LR;
983 if (!MATRIX_FORMAT::symmetric) {
984 d_residue_d_dofc(disp_range, lagrange_mult_range) += trans_LR;
988 if (!d_residue_d_time.is_null()) {
989 d_residue_d_time(disp_range) = trans_d_r_d_dof * d_fe_d_time;
993 typedef ObjectTypeComplete<
994 QuasistaticViscousDampingResidueFunction,
995 typename DynamicResidueFunction<T, MATRIX_FORMAT>::type_t>
1000 double rayleigh_damping_alpha;
1001 double rayleigh_damping_beta;
1002 double dissipated_energy_fraction;
1003 SolverUtilsOrderTwoRayleighDamping<T, MATRIX_FORMAT, false> solver_utile;
1006template <
typename T,
typename MATRIX_FORMAT>
1007typename QuasistaticViscousDampingResidueFunction<T, MATRIX_FORMAT>::type_t
1008 QuasistaticViscousDampingResidueFunction<T, MATRIX_FORMAT>::type(
1009 "QuasistaticViscousDampingResidueFunction", type_name<T, MATRIX_FORMAT>(),
1011 "QUASISTATIC_VISCOUS_DAMPING_DYNAMIC_RESIDUE_FUNCTION",
1012 "ARTIFICIAL_DAMPING_DYNAMIC_RESIDUE_FUNCTION"),
1013 b2000::solver::module, &DynamicResidueFunction<T, MATRIX_FORMAT>::type);
#define THROW
Definition b2exception.H:198
Interface to C++ representations of FE solvers.
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829