21#ifndef B2BOUNDARY_CONDITION_NLR_COUPLING_H_
22#define B2BOUNDARY_CONDITION_NLR_COUPLING_H_
26#include "b2model_database.H"
27#include "b2solution_database.H"
30#include "model/b2element.H"
31#include "model_imp/b2boundary_condition_component.H"
32#include "utils/b2linear_algebra.H"
37namespace b2000::b2dbv3 {
39class StaticResidueFunctionNLRCoupling {
42 typedef b2linalg::Msymmetric MATRIX_FORMAT;
43 typedef TypedNaturalBoundaryConditionListComponent<T, MATRIX_FORMAT::sparse_inversible>
45 typedef TypedEssentialBoundaryConditionListComponent<T> ebc_list_t;
46 typedef TypedModelReductionBoundaryConditionListComponent<T> mrbc_list_t;
48 StaticResidueFunctionNLRCoupling()
50 number_of_non_lagrang_dof(0),
56 constraint_has_penalty(false),
58 lagrange_mult_scale(0) {}
60 virtual ~StaticResidueFunctionNLRCoupling() {}
62 void init(Model& model_,
const AttributeList& attribute) {
64 domain = &model->get_domain();
65 ebc = &
dynamic_cast<ebc_list_t::typed_base_t&
>(
66 model->get_essential_boundary_condition(&ebc_list_t::type));
67 mrbc = &
dynamic_cast<mrbc_list_t::typed_base_t&
>(
68 model->get_model_reduction_boundary_condition(&mrbc_list_t::type));
69 nbc = &
dynamic_cast<nbc_list_t::typed_base_t&
>(
70 model->get_natural_boundary_condition(&nbc_list_t::type));
71 nbc_sol.resize(domain->get_number_of_dof());
72 fi.resize(domain->get_number_of_dof());
74 constraint_has_penalty =
75 attribute.get_string(
"CONSTRAINT_METHOD",
"REDUCTION") ==
"PENALTY";
77 constraint_has_penalty |=
78 attribute.get_string(
"NONLINEAR_CONSTRAINT_METHOD",
"OTHER") ==
"PENALTY";
80 number_of_dof = number_of_non_lagrang_dof =
81 mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1);
82 if (constraint_has_penalty) {
83 penalty_factor = attribute.get_double(
"CONSTRAINT_PENALTY", 1e10);
85 number_of_dof += ebc->get_size(
false);
86 penalty_factor = attribute.get_double(
"CONSTRAINT_PENALTY", 1);
87 if (attribute.get_string(
"NONLINEAR_CONSTRAINT_METHOD",
"OTHER") ==
"LAGRANGE") {
90 lagrange_mult_scale = attribute.get_double(
"LAGRANGE_MULT_SCALE_PENALTY", 1.0);
94 size_t get_number_of_dof() {
return number_of_dof; }
96 size_t get_number_of_non_lagrange_dof() {
return number_of_non_lagrang_dof; }
99 const b2linalg::Vector<T, b2linalg::Vdense_constref> dof,
const double time,
100 EquilibriumSolution equilibrium_solution,
101 b2linalg::Vector<T, b2linalg::Vdense_ref> dof_sol) {
102 mrbc_get_nonlinear_value(
103 dof(b2linalg::Interval(
104 0, mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1))),
105 time, equilibrium_solution, dof_sol,
106 b2linalg::Matrix<T, b2linalg::Mcompressed_col>::null,
107 b2linalg::Vector<T, b2linalg::Vdense_ref>::null,
nullptr);
110 const b2linalg::Vector<T, b2linalg::Vdense_constref> get_residuum_sol() {
return fi; }
112 const b2linalg::Vector<T, b2linalg::Vdense_constref> get_nbc_sol() {
return nbc_sol; }
114 T get_residue_normalization() {
return std::max(fi * fi, nbc_sol * nbc_sol); }
116 double get_energy_normalisation1() {
118 for (
size_t i = 0; i != r.size(); ++i) {
119 res += std::max(
norm(r[i] * nbc_sol[i]),
norm(r[i] * fi[i]));
124 double get_energy() {
126 for (
size_t i = 0; i != r.size(); ++i) { res += r[i] * (fi[i] + nbc_sol[i]); }
131 const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof_global,
132 const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof,
const double time,
133 const double delta_time,
const EquilibriumSolution equilibrium_solution,
134 b2linalg::Vector<T, b2linalg::Vdense_ref> residue,
135 b2linalg::Matrix<T, MATRIX_FORMAT::sparse_inversible>& d_residue_d_dof,
136 const b2linalg::Matrix<T>& C, b2linalg::Matrix<T>& RtKC,
137 b2linalg::Matrix<T, b2linalg::Mrectangle>& CtKC,
138 b2linalg::Vector<T, b2linalg::Vdense_ref> d_residue_d_time, SolverHints* solver_hints) {
139 b2linalg::Interval disp_range(
140 0, mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1));
141 b2linalg::Interval lagrange_mult_range(
142 mrbc->get_size(
false, b2linalg::Vector<T, b2linalg::Vdense>::null, 1), number_of_dof);
144 const size_t nb_dof = domain->get_number_of_dof();
146 if (!d_residue_d_dof.is_null()) {
147 if (d_residue_d_dof.size1() != dof.size()) { d_residue_d_dof.resize(dof.size()); }
148 d_residue_d_dof.set_zero_same_struct();
149 RtKC.resize(dof.size(), C.size2());
154 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_r_d_dof;
155 b2linalg::Vector<T, b2linalg::Vdense> d_r_d_time(domain->get_number_of_dof());
156 mrbc_get_nonlinear_value(
157 dof(disp_range), time, equilibrium_solution, r, trans_d_r_d_dof, d_r_d_time,
161 b2linalg::Matrix<T, MATRIX_FORMAT::sparse_inversible> d_fe_d_dof;
162 b2linalg::Vector<T, b2linalg::Vdense> d_fe_d_time(domain->get_number_of_dof());
164 nbc->get_nonlinear_value(
165 r, time, equilibrium_solution, residue,
166 (d_residue_d_dof.is_null()
167 ? b2linalg::Matrix<T, MATRIX_FORMAT::sparse_inversible>::null
169 (d_residue_d_time.is_null() ? d_residue_d_time
170 : b2linalg::Vector<T, b2linalg::Vdense_ref>(d_fe_d_time)),
173 d_fe_d_time = -d_fe_d_time;
174 if (d_fe_d_dof.size1() != 0) {
175 d_residue_d_dof += -trans_d_r_d_dof * d_fe_d_dof * transposed(trans_d_r_d_dof);
178 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_d_l_d_dof;
179 b2linalg::Vector<T> l;
181 if (constraint_has_penalty) {
182 l.resize(ebc->get_size(
false));
183 ebc->get_nonlinear_value(
184 r, time, equilibrium_solution, l, trans_d_l_d_dof,
185 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, solver_hints);
187 ebc->get_nonlinear_value(
188 r, time, equilibrium_solution, residue(lagrange_mult_range), trans_d_l_d_dof,
189 d_residue_d_time.is_null() ? d_residue_d_time
190 : d_residue_d_time(lagrange_mult_range),
192 if (!d_residue_d_time.is_null()) {
193 d_residue_d_time(lagrange_mult_range) +=
194 b2linalg::transposed(trans_d_l_d_dof) * d_r_d_time;
198 if (!d_residue_d_time.is_null() && d_fe_d_dof.size1()) {
199 d_fe_d_time -= d_fe_d_dof * d_r_d_time;
205 b2linalg::Index index;
206 b2linalg::Vector<T, b2linalg::Vdense> value_e;
207 b2linalg::Vector<T, b2linalg::Vdense> d_value_d_time_e;
208 std::vector<bool> d_value_d_dof_e_flags(
209 d_residue_d_dof.is_null() && d_residue_d_time.is_null() ? 0 : 1, true);
210 std::vector<b2linalg::Matrix<T, MATRIX_FORMAT::dense> > d_value_d_dof_e(
211 d_value_d_dof_e_flags.size());
212 std::unique_ptr<b2000::Domain::ElementIterator> i = domain->get_element_iterator();
213 if (K.size1() == 0) { K.resize(nb_dof, nb_dof); }
214 K.set_zero_same_struct();
215 for (Element* element = i->next(); element !=
nullptr; element = i->next()) {
216 if (
auto te =
dynamic_cast<TypedElement<T>*
>(element); te !=
nullptr) {
218 *model,
false, equilibrium_solution, time, delta_time,
219 b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(r),
221 solver_hints, index, value_e, d_value_d_dof_e_flags, d_value_d_dof_e,
222 (d_residue_d_time.is_null() ? b2linalg::Vector<T, b2linalg::Vdense>::null
223 : d_value_d_time_e));
225 fi(index) += value_e;
227 if (!d_residue_d_time.is_null()) {
228 d_value_d_time_e += d_value_d_dof_e[0] * d_r_d_time(index);
229 d_residue_d_time(index) += d_value_d_time_e;
231 if (!d_residue_d_dof.is_null()) {
233 T, b2linalg::Mstructured_constref<b2linalg::Mpacked_st_constref> >
234 Kelem = b2linalg::StructuredMatrix(nb_dof, index, d_value_d_dof_e[0]);
236 trans_d_r_d_dof * Kelem * b2linalg::transposed(trans_d_r_d_dof);
241 b2linalg::Vector<double> KCi;
242 b2linalg::Matrix<T, b2linalg::Msym_compressed_col_st_constref> Kref(K);
243 for (
size_t j = 0; j != C.size2(); ++j) {
245 RtKC[j] += trans_d_r_d_dof * KCi;
246 CtKC[j] += b2linalg::transposed(C) * KCi;
252 b2linalg::Vector<T> tmp = fi;
253 if (constraint_has_penalty) {
254 tmp += (trans_d_l_d_dof * l) * penalty_factor;
256 if (MATRIX_FORMAT::symmetric && penalty_factor != 0) {
259 b2linalg::Vector<T> tmp1;
260 tmp1 = residue(lagrange_mult_range) * penalty_factor;
261 tmp1 += dof(lagrange_mult_range) * lagrange_mult_scale;
262 tmp += trans_d_l_d_dof * tmp1;
263 residue(lagrange_mult_range) *= lagrange_mult_scale;
265 tmp += lagrange_mult_scale * trans_d_l_d_dof * dof(lagrange_mult_range);
268 residue(disp_range) = trans_d_r_d_dof * tmp;
271 if (!d_residue_d_dof.is_null()) {
272 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_LR;
273 trans_LR = trans_d_r_d_dof * trans_d_l_d_dof;
274 if (penalty_factor != 0 && (constraint_has_penalty || MATRIX_FORMAT::symmetric)) {
277 d_residue_d_dof(disp_range, disp_range) +=
278 (trans_LR * transposed(trans_LR)) * penalty_factor;
280 if (!constraint_has_penalty) {
281 trans_LR *= lagrange_mult_scale;
282 b2linalg::Matrix<T, b2linalg::Mcompressed_col> LR = transposed(trans_LR);
283 d_residue_d_dof(lagrange_mult_range, disp_range) += LR;
284 if (!MATRIX_FORMAT::symmetric) {
285 d_residue_d_dof(disp_range, lagrange_mult_range) += trans_LR;
290 if (!d_residue_d_time.is_null()) {
291 d_residue_d_time(disp_range) = trans_d_r_d_dof * d_fe_d_time;
295 void mrbc_get_nonlinear_inverse_value(
296 const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof,
double time,
297 b2linalg::Vector<T, b2linalg::Vdense_ref> reduced_dof) {
298 mrbc->get_nonlinear_inverse_value(
299 b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(dof), time,
300 b2linalg::Matrix<T, b2linalg::Mrectangle_ref>(reduced_dof));
304 virtual void mrbc_get_nonlinear_value(
305 const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof,
double time,
306 EquilibriumSolution equilibrium_solution, b2linalg::Vector<T, b2linalg::Vdense_ref> value,
307 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& d_value_d_dof_trans,
308 b2linalg::Vector<T, b2linalg::Vdense_ref> d_value_d_time, SolverHints* solver_hints) {
309 mrbc->get_nonlinear_value(
310 dof, time, equilibrium_solution, value, d_value_d_dof_trans,
311 b2linalg::Matrix<T, b2linalg::Mrectangle_ref>(d_value_d_time), solver_hints);
314 size_t number_of_dof;
315 size_t number_of_non_lagrang_dof;
318 TypedModelReductionBoundaryCondition<T>* mrbc;
319 ebc_list_t::typed_base_t* ebc;
320 nbc_list_t::typed_base_t* nbc;
321 b2linalg::Vector<T, b2linalg::Vdense> fi;
322 b2linalg::Vector<T, b2linalg::Vdense> nbc_sol;
323 b2linalg::Vector<T, b2linalg::Vdense> r;
324 bool constraint_has_penalty;
325 double penalty_factor;
326 double lagrange_mult_scale;
327 b2linalg::Matrix<T, MATRIX_FORMAT::sparse_inversible> K;
330class NBC_NLR_Coupling;
332class SolutionStaticNonlinearNLRCoupling :
public b2000::SolutionStaticNonlinear<double> {
334 SolutionStaticNonlinearNLRCoupling()
335 : nlr_coupling(nullptr), local_solution(nullptr), subcase_id(0) {}
337 void set_nlr_coupling(NBC_NLR_Coupling& nlr_coupling);
343 void set_subcase_id(
const int subcase_id_)
override { subcase_id = subcase_id_; }
345 void set_need_refinement()
override {}
347 b2000::SolutionStaticNonlinear<double>::gradient_container get_gradient_container()
override {
348 return local_solution->get_gradient_container();
351 void new_cycle(
bool end_of_stage =
false)
override { local_solution->new_cycle(end_of_stage); }
353 void terminate_cycle(
double time,
double dtime,
const RTable& attributes)
override {
354 local_solution->terminate_cycle(time, dtime, attributes);
357 void terminate_stage(
bool success =
true)
override;
359 void terminate_case(
bool success,
const RTable& attributes)
override;
361 int get_subcase_id()
const {
return subcase_id; }
363 size_t get_cycle_id()
override {
return local_solution->get_cycle_id(); }
365 size_t get_subcycle_id()
override {
return local_solution->get_subcycle_id(); }
367 std::string get_domain_state_id()
override {
return local_solution->get_domain_state_id(); }
370 double time,
const b2linalg::Vector<double, b2linalg::Vdense_constref>& dof,
371 const b2linalg::Vector<double, b2linalg::Vdense_constref>& nbc,
372 const b2linalg::Vector<double, b2linalg::Vdense_constref>& residue,
373 bool unconverged_subcycle =
false)
override;
375 void set_equilibrium(
376 double time,
const b2linalg::Vector<double, b2linalg::Vdense_constref>& dof)
override {}
378 void get_dof(
double& time, b2linalg::Vector<double, b2linalg::Vdense_ref> dof)
override {
383 NBC_NLR_Coupling* nlr_coupling;
384 b2000::b2dbv3::SolutionStaticNonlinear<double>* local_solution;
388class NBC_NLR_Coupling :
public TypedNaturalBoundaryConditionComponent<
389 double, b2linalg::Msym_compressed_col_update_inv> {
391 NBC_NLR_Coupling() : local_case(nullptr), global_model(nullptr), C_linear(true) {}
394 const std::string& id_, TimeFunction* scalef_,
b2000::Model& model_,
395 const b2000::Case& case_,
const int subcase_id_)
override {
397 global_model = &model_;
398 subcase_id = subcase_id_;
401 std::string get_id()
const override {
return id; }
403 int get_subcase_id()
const override {
return subcase_id; }
409 void add_nonlinear_nbc_value(
410 const b2linalg::Vector<double, b2linalg::Vdense_constref>& global_dof_all,
double time,
411 EquilibriumSolution equilibrium_solution,
412 b2linalg::Vector<double, b2linalg::Vdense_ref> value_,
413 b2linalg::Matrix<double, b2linalg::Msym_compressed_col_update_inv>& d_value_d_dof,
414 b2linalg::Vector<double, b2linalg::Vdense_ref> d_value_d_time,
415 SolverHints* solver_hints)
override {
418 if (C.size1() == 0) { update_local_model(); }
420 if (equilibrium_solution.input_level == 0) {
421 prev_global_dof = conv_global_dof;
422 prev_local_dof = conv_local_dof;
424 b2linalg::Vector<double> local_dof = prev_local_dof;
426 b2linalg::Vector<double> global_dof = global_dof_all(C_index);
429 if (prev_global_dof.size() != 0) {
430 b2linalg::Vector<double> delta_global_dof;
431 delta_global_dof = prev_global_dof - global_dof;
432 b2linalg::Vector<double> delta_d;
433 delta_d = local_RtKC * delta_global_dof;
434 delta_d = b2linalg::inverse(local_RtKR) * delta_d;
435 local_dof += delta_d;
437 if (equilibrium_solution.output_level == 0) { conv_global_dof = global_dof; }
438 if (equilibrium_solution.output_level != -1) { prev_global_dof = global_dof; }
441 b2linalg::Matrix<double, b2linalg::Mrectangle> local_CtKC(C.size2(), C.size2());
444 b2linalg::Vector<double> residue(local_model_residue.get_number_of_dof());
446 b2linalg::Vector<double> global_dof_on_local;
448 global_dof_on_local = C * global_dof;
450 get_global_to_local_dof(global_dof_all, global_dof_on_local, C);
452 local_model_residue.get_residue(
453 global_dof_on_local, local_dof, time, 0, equilibrium_solution, residue,
454 (d_value_d_dof.is_null()
455 ? b2linalg::Matrix<double, b2linalg::Msym_compressed_col_update_inv>::null
457 C, local_RtKC, local_CtKC, b2linalg::Vector<double, b2linalg::Vdense_ref>::null,
462 if (!d_value_d_dof.is_null() && local_RtKR.size1() != 0) {
463 b2linalg::Matrix<double> M;
464 M = inverse(local_RtKR) * local_RtKC;
465 local_CtKC -= (b2linalg::transposed(local_RtKC) * M);
492 b2linalg::Vector<double> delta_d;
494 if (equilibrium_solution.output_level != -1 || !value_.is_null()) {
495 delta_d = b2linalg::inverse(local_RtKR) * residue;
496 if (equilibrium_solution.output_level != -1) {
497 local_dof -= delta_d;
498 prev_local_dof = local_dof;
503 if (!value_.is_null()) {
504 b2linalg::Vector<double> tmp;
505 tmp = -transposed(C) * local_model_residue.get_residuum_sol();
506 tmp += transposed(local_RtKC) * delta_d;
507 value_(C_index) += tmp;
511 if (!d_value_d_dof.is_null()) {
512 if (d_value_d_dof.size1() == 0) {
513 d_value_d_dof.resize(global_dof_all.size(), global_dof_all.size());
515 b2linalg::Matrix<double, b2linalg::Mupper_packed> local_CtKC_sym;
516 local_CtKC_sym = -local_CtKC;
518 b2linalg::StructuredMatrix(d_value_d_dof.size1(), C_index, local_CtKC_sym);
523 b2linalg::Index index_e;
524 b2linalg::Vector<double, b2linalg::Vdense> value_e;
525 b2linalg::Vector<double, b2linalg::Vdense> d_value_d_time_e;
526 std::vector<bool> d_value_d_dof_e_flags(
527 d_value_d_dof.is_null() && d_value_d_time.is_null() ? 0 : 1, true);
528 std::vector<b2linalg::Matrix<double, b2linalg::Mpacked> > d_value_d_dof_e(
529 d_value_d_dof_e_flags.size());
530 for (global_elements_t::iterator e = global_elements.begin();
531 e != global_elements.end(); ++e) {
532 if (
auto te =
dynamic_cast<TypedElement<double>*
>(*e); te !=
nullptr) {
534 *global_model,
false, equilibrium_solution, time, 0,
535 b2linalg::Matrix<double, b2linalg::Mrectangle_constref>(global_dof_all),
537 solver_hints, index_e,
538 (value_.is_null() ? b2linalg::Vector<double, b2linalg::Vdense>::null
540 d_value_d_dof_e_flags, d_value_d_dof_e,
541 (d_value_d_time.is_null()
542 ? b2linalg::Vector<double, b2linalg::Vdense>::null
543 : d_value_d_time_e));
545 if (!value_.is_null()) { value_(index_e) += value_e; }
546 if (!d_value_d_dof.is_null()) {
547 d_value_d_dof += b2linalg::StructuredMatrix(
548 d_value_d_dof.size1(), index_e, d_value_d_dof_e[0]);
554 typedef ObjectTypeComplete<
555 NBC_NLR_Coupling, TypedNaturalBoundaryConditionComponent<double>::type_t>
560 using global_elements_t = std::set<TypedElement<double>*>;
561 friend class SolutionStaticNonlinearNLRCoupling;
562 SolutionStaticNonlinearNLRCoupling solution;
567 b2000::CaseList::case_iterator local_case_iterator;
582 b2linalg::Matrix<double> C;
583 b2linalg::Index C_index;
585 std::map<size_t, size_t> C_index_set;
589 void update_local_model() {
590 local_model.
init(
id);
592 local_case_iterator = local_model.
get_case_list().get_case_iterator();
593 local_case = local_case_iterator->next();
596 solution.set_nlr_coupling(*
this);
597 dynamic_cast<b2000::b2dbv3::SolutionStaticNonlinear<double>&
>(global_model->
get_solution())
598 .add_sub_solution(solution);
604 global_elements.clear();
605 std::unique_ptr<b2000::Domain::ElementIterator> local_element_iter =
607 Element* element =
nullptr;
608 for (element = local_element_iter->next(); element !=
nullptr;
609 element = local_element_iter->next()) {
611 global_domain, *element, b2linalg::Matrix<double>::null);
612 TypedElement<double>& global_element_typed =
613 dynamic_cast<TypedElement<double>&
>(*global_element);
614 global_elements.insert(&global_element_typed);
624 std::unique_ptr<b2000::Domain::NodeIterator> local_node_iter =
626 const std::string field_name =
"DISP";
627 for (Node* local_node = local_node_iter->next(); local_node !=
nullptr;
628 local_node = local_node_iter->next()) {
629 b2linalg::Vector<double> global_icoor;
631 global_domain, *local_node, global_icoor);
632 b2linalg::Index dof_numbering;
633 b2linalg::Matrix<double, b2linalg::Mrectangle> d_value_d_dof;
634 TypedElement<double>& e =
dynamic_cast<TypedElement<double>&
>(*global_element);
635#ifdef CHECK_GLOBAL_TO_LOCAL_MAPPING
637 b2linalg::Vector<double> global_coor;
639 global_icoor, global_coor,
640 b2linalg::Matrix<double, b2linalg::Mrectangle>::null);
641 std::pair<int, const coor_type*> local_coor = local_node->get_coor();
642 for (
int i = 0; i != local_coor.first; ++i) {
643 if (
norm(local_coor.second[i] - global_coor[i])
644 > CHECK_GLOBAL_TO_LOCAL_MAPPING) {
646 <<
"The local mapping for the local node "
647 << local_node->get_object_name() <<
" is not correct." <<
THROW;
652 if (!e.body_field_linear_on_dof(field_name)) { C_linear =
false; }
654 field_name, global_icoor,
655 b2linalg::Matrix<double, b2linalg::Mrectangle_constref>::null, 1,
656 b2linalg::Vector<double, b2linalg::Vdense>::null,
657 b2linalg::Matrix<double, b2linalg::Mrectangle>::null, dof_numbering,
659 for (
size_t i = 0; i != dof_numbering.size(); ++i) {
660 C_index_set[dof_numbering[i]] = 0;
664 C_index.resize(C_index_set.size());
667 for (std::map<size_t, size_t>::iterator i = C_index_set.begin();
668 i != C_index_set.end(); ++i, ++ii) {
669 C_index[ii] = i->first;
679 get_global_to_local_dof(
680 b2linalg::Vector<double, b2linalg::Vdense_constref>::null,
681 b2linalg::Vector<double, b2linalg::Vdense>::null, C);
686 local_model_residue.init(local_model, *local_case);
687 conv_local_dof.clear();
688 conv_local_dof.resize(local_model_residue.get_number_of_dof());
689 prev_local_dof = conv_local_dof;
692 void get_global_to_local_dof(
693 const b2linalg::Vector<double, b2linalg::Vdense_constref>& dof_global,
694 b2linalg::Vector<double, b2linalg::Vdense>& dof_local,
695 b2linalg::Matrix<double, b2linalg::Mrectangle_ref> C) {
698 const std::string field_name =
"DISP";
699 if (!dof_local.is_null()) {
700 dof_local.set_zero();
703 if (!C.is_null()) { C.set_zero(); }
704 std::unique_ptr<b2000::Domain::NodeIterator> local_node_iter =
707 for (Node* local_node = local_node_iter->next(); local_node !=
nullptr;
708 local_node = local_node_iter->next()) {
709 b2linalg::Vector<double> global_icoor;
710 Element* global_element =
712 b2linalg::Index dof_numbering;
713 b2linalg::Vector<double, b2linalg::Vdense> value;
714 b2linalg::Matrix<double, b2linalg::Mrectangle> d_value_d_dof;
715 dynamic_cast<TypedElement<double>&
>(*global_element)
717 field_name, global_icoor,
718 (dof_global.is_null()
719 ? b2linalg::Matrix<double, b2linalg::Mrectangle_constref>::null
720 : b2linalg::Matrix<double, b2linalg::Mrectangle_constref>(
723 (dof_local.is_null() ? b2linalg::Vector<double, b2linalg::Vdense>::null
725 b2linalg::Matrix<double, b2linalg::Mrectangle>::null, dof_numbering,
726 (C.is_null() ? b2linalg::Matrix<double, b2linalg::Mrectangle>::null
728 if (!dof_local.is_null()) {
729 for (
size_t i = 0; i != value.size(); ++i) { dof_local[ii + i] = value[i]; }
732#if BCNC_CHECK_DERIVATIVE
733 if (!dof_global.is_null()) {
734 const double h = 1e-4;
735 const double inv_12h = 1.0 / (12 * h);
736 b2linalg::Vector<double> dof_h = dof_global;
737 b2linalg::Vector<double> diff;
738 b2linalg::Vector<double> value_tmp;
739 TypedElement<double>& e =
dynamic_cast<TypedElement<double>&
>(*global_element);
740 bool first_error =
true;
741 for (
size_t j = 0; j != dof_numbering.size(); ++j) {
742 const size_t jj = dof_numbering[j];
743 dof_h[jj] = dof_global[jj] - 2 * h;
745 field_name, global_icoor,
746 b2linalg::Matrix<double, b2linalg::Mrectangle_constref>(dof_h), 1,
747 value_tmp, b2linalg::Matrix<double, b2linalg::Mrectangle>::null,
748 b2linalg::Index::null,
749 b2linalg::Matrix<double, b2linalg::Mrectangle>::null);
750 diff = inv_12h * value_tmp;
752 dof_h[jj] = dof_global[jj] + 2 * h;
754 field_name, global_icoor,
755 b2linalg::Matrix<double, b2linalg::Mrectangle_constref>(dof_h), 1,
756 value_tmp, b2linalg::Matrix<double, b2linalg::Mrectangle>::null,
757 b2linalg::Index::null,
758 b2linalg::Matrix<double, b2linalg::Mrectangle>::null);
759 diff += -inv_12h * value_tmp;
761 dof_h[jj] = dof_global[jj] - h;
763 field_name, global_icoor,
764 b2linalg::Matrix<double, b2linalg::Mrectangle_constref>(dof_h), 1,
765 value_tmp, b2linalg::Matrix<double, b2linalg::Mrectangle>::null,
766 b2linalg::Index::null,
767 b2linalg::Matrix<double, b2linalg::Mrectangle>::null);
768 diff += (-8.0 * inv_12h) * value_tmp;
770 dof_h[jj] = dof_global[jj] + h;
772 field_name, global_icoor,
773 b2linalg::Matrix<double, b2linalg::Mrectangle_constref>(dof_h), 1,
774 value_tmp, b2linalg::Matrix<double, b2linalg::Mrectangle>::null,
775 b2linalg::Index::null,
776 b2linalg::Matrix<double, b2linalg::Mrectangle>::null);
777 diff += (8.0 * inv_12h) * value_tmp;
779 dof_h[jj] = dof_global[jj];
781 for (
size_t i = 0; i != diff.size(); ++i) {
782 if (std::abs(diff[i] - d_value_d_dof(i, j)) > 1e-6) {
785 <<
", local node=" << local_node->get_object_name()
786 <<
", coor=" << global_icoor[0] <<
", "
787 << global_icoor[1] <<
", " << global_icoor[2]
791 std::cerr <<
" d_value_d_dof(" << i <<
", " << j
792 <<
")=" << d_value_d_dof(i, j) <<
", numeric=" << diff[i]
799 for (
size_t j = 0; j != d_value_d_dof.size2(); ++j) {
800 const size_t jj = C_index_set[dof_numbering[j]];
801 for (
size_t i = 0; i != d_value_d_dof.size1(); ++i) {
802 C(ii + i, jj) = d_value_d_dof(i, j);
806 ii += dof_local.is_null() ? d_value_d_dof.size1() : value.size();
811 b2linalg::Vector<double> conv_global_dof;
812 b2linalg::Vector<double> prev_global_dof;
813 b2linalg::Vector<double> conv_local_dof;
814 b2linalg::Vector<double> prev_local_dof;
815 b2linalg::Matrix<double, b2linalg::Msym_compressed_col_update_inv> local_RtKR;
816 b2linalg::Matrix<double> local_RtKC;
818 global_elements_t global_elements;
820 StaticResidueFunctionNLRCoupling local_model_residue;
823inline void SolutionStaticNonlinearNLRCoupling::set_nlr_coupling(NBC_NLR_Coupling& nlr_coupling_) {
824 nlr_coupling = &nlr_coupling_;
825 local_solution = &
dynamic_cast<b2000::b2dbv3::SolutionStaticNonlinear<double>&
>(
826 nlr_coupling->local_model.get_solution());
829inline void SolutionStaticNonlinearNLRCoupling::set_dof(
830 double time,
const b2linalg::Vector<double, b2linalg::Vdense_constref>& global_dof_all,
831 const b2linalg::Vector<double, b2linalg::Vdense_constref>& nbc,
832 const b2linalg::Vector<double, b2linalg::Vdense_constref>& residue,
833 bool unconverged_subcycle) {
835 b2000::Domain& local_domain = nlr_coupling->local_model.get_domain();
836 b2linalg::Vector<double, b2linalg::Vdense> g;
838 nlr_coupling->conv_local_dof = nlr_coupling->prev_local_dof;
839 nlr_coupling->local_model_residue.get_solution(nlr_coupling->conv_local_dof, time,
true, g);
843 SetName name = nlr_coupling->local_case->get_string(
"DOF_SOL",
"DISP") +
"_H1";
844 if (unconverged_subcycle) {
845 name.cycle(local_solution->get_cycle_id() + 1);
846 name.subcycle(local_solution->get_subcycle_id() + 1);
848 name.cycle(local_solution->get_cycle_id());
850 if (name.case_undef()) { name.case_(nlr_coupling->local_case->get_id()); }
851 name.subcase(subcase_id);
852 dynamic_cast<DataBaseFieldSet&
>(nlr_coupling->local_model)
854 "DOF Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
856 rtable.set(
"STAGE_ID", nlr_coupling->local_case->get_stage_id());
857 rtable.set(
"STAGE", nlr_coupling->local_case->get_stage_number());
858 rtable.set(
"LAMBDA", time);
859 dynamic_cast<b2dbv3::Domain&
>(nlr_coupling->local_model.get_domain())
861 name, b2linalg::Vector<double, b2linalg::Vdense_constref>(g), rtable);
866 if (nlr_coupling->C_linear) {
867 b2linalg::Vector<double> global_dof = global_dof_all(nlr_coupling->C_index);
868 g += nlr_coupling->C * global_dof;
870 b2linalg::Vector<double> global_dof_on_local;
871 nlr_coupling->get_global_to_local_dof(
872 global_dof_all, global_dof_on_local, nlr_coupling->C);
873 g += global_dof_on_local;
878 local_solution->set_dof(
879 time, g, nlr_coupling->local_model_residue.get_nbc_sol(),
880 nlr_coupling->local_model_residue.get_residuum_sol(), unconverged_subcycle);
883 b2000::SolutionStaticNonlinear<double>::gradient_container gc =
884 local_solution->get_gradient_container();
886 local_domain.set_dof(g);
888 b2linalg::Index index;
889 for (Element* e = ii->next(); e !=
nullptr; e = ii->next()) {
890 if (
auto te =
dynamic_cast<TypedElement<double>*
>(e); te !=
nullptr) {
892 nlr_coupling->local_model,
897 b2linalg::Matrix<double, b2linalg::Mrectangle_constref>(g),
898 gc.get() !=
nullptr && gc->set_current_element(*e) ? gc.get() :
nullptr,
900 index, b2linalg::Vector<double, b2linalg::Vdense>::null,
901 TypedElement<double>::d_value_d_dof_flags_null,
902 TypedElement<double>::d_value_d_dof_null,
903 b2linalg::Vector<double, b2linalg::Vdense>::null);
909inline void SolutionStaticNonlinearNLRCoupling::terminate_stage(
bool success) {
910 local_solution->terminate_stage(success);
911 if (nlr_coupling->local_case->next_stage()) {
912 nlr_coupling->local_model.set_case(*nlr_coupling->local_case);
916inline void SolutionStaticNonlinearNLRCoupling::terminate_case(
917 bool success,
const RTable& attributes) {
918 local_solution->terminate_case(success, attributes);
919 nlr_coupling->local_case = nlr_coupling->local_case_iterator->next();
920 if (nlr_coupling->local_case) { nlr_coupling->local_model.set_case(*nlr_coupling->local_case); }
csda< T > norm(const csda< T > &a)
Definition b2csda.H:343
#define THROW
Definition b2exception.H:198
virtual Element * get_parent_element_and_nodes_mapping(Domain &parent_domain, const Element &element, b2linalg::Matrix< double > &parent_nodes_internal_coor)
Definition b2domain.H:431
virtual size_t get_number_of_dof() const =0
virtual element_iterator get_element_iterator()=0
virtual node_iterator get_node_iterator()=0
virtual Element * get_parent_element_mapping(Domain &parent_domain, const Node &node, b2linalg::Vector< double > &parent_internal_coor)
Definition b2domain.H:453
const std::string & get_object_name() const override
Definition b2element.H:220
virtual void body_geom(const b2linalg::Vector< double, b2linalg::Vdense_constref > &internal_coor, b2linalg::Vector< double > &geom, b2linalg::Matrix< double, b2linalg::Mrectangle > &d_geom_d_icoor)
Definition b2element.H:963
virtual Solution & get_solution()=0
virtual Domain & get_domain()=0
Type
Definition b2boundary_condition.H:49
@ conservative
Definition b2boundary_condition.H:60
Definition b2model_database.H:44
Domain & get_domain() override
Definition b2model_database.C:164
void init(const std::string &dbname="", Dictionary *cmdline_set_=nullptr) override
Definition b2model_database.C:47
CaseList & get_case_list() override
Definition b2model_database.C:154
void set_case(b2000::Case &case_) override
Definition b2model_database.C:81
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314