21#ifndef B2SOLUTION_DATABASE_H_
22#define B2SOLUTION_DATABASE_H_
30#include "b2case_database.H"
32#include "b2ppconfig.h"
36#include "utils/b2database.H"
38#include "utils/b2threading.H"
41#include "tbb/enumerable_thread_specific.h"
44namespace b2000::b2dbv3 {
46struct sol_type_properties {
47 bool is_complex =
false;
49 sol_type_properties(
bool is_complex,
bool is_csda) : is_complex(is_complex), is_csda(is_csda) {}
52std::string sol_type_name(std::string basename, sol_type_properties);
54class GradientContainerOffload {
56 virtual void offload_data() = 0;
59class GradientContainer;
65 database =
dynamic_cast<DataBaseFieldSet*
>(&model_);
67 domain =
dynamic_cast<Domain*
>(&model_.
get_domain());
70 for (
size_t i = 0; i != domain->list_branch.size(); ++i) {
71 list_branch.push_back(Branch(
this));
76 case_ = &
dynamic_cast<b2000::b2dbv3::Case&
>(case__);
77 need_refinement =
false;
80 db_grad_name =
"GRADIENTS";
81 if (db_grad_name.case_undef()) { db_grad_name.case_(case__.
get_id()); }
82 for (
size_t i = 0; i != list_branch.size(); ++i) {
83 list_branch[i].field_list_i.clear();
84 list_branch[i].field_list_d.clear();
85 list_branch[i].field_list_cs.clear();
86 list_branch[i].field_list_c.clear();
88 if (case__.
has_key(
"COMPUTE_FIELDS")) {
89 std::string s = case__.
get_string(
"COMPUTE_FIELDS");
90 for (
size_t i = 0; i < s.size();) {
91 const size_t j = s.find(
'.', i);
92 list_fields_to_compute.insert(s.substr(i, j - i));
93 if (j == std::string::npos) {
break; }
96 list_fields_to_compute_neg =
false;
100 void set_subcase_id(
int subcase_id_)
override {
101 if (subcase_id == subcase_id_) {
return; }
102 terminate_gradient();
103 subcase_id = subcase_id_;
106 void set_system_null_space(
107 const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>& nks,
bool normalize =
true,
108 const std::string suffix =
"NS")
override {
109 SetName sol = case_->get_string(
"DOF_SOL", std::string(
"DISP")) +
"_" + suffix;
110 if (sol.case_undef()) { sol.case_(case_->get_id()); }
111 database->add_field_entry(
112 "DOF Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
113 database->add_field_entry(
114 "DOF Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
115 b2linalg::Vector<double> tmp;
116 for (
size_t j = 0; j != nks.size2(); ++j) {
119 if (normalize) { tmp.normalize(); }
120 domain->save_global_dof(sol, b2linalg::Vector<double, b2linalg::Vdense_constref>(tmp));
125 void set_system_null_space(
126 const b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle_constref>& nks,
127 bool normalize =
true,
const std::string suffix =
"NS")
override {
128 SetName sol = case_->get_string(
"DOF_SOL", std::string(
"DISP")) +
"_" + suffix;
129 if (sol.case_undef()) { sol.case_(case_->get_id()); }
130 database->add_field_entry(
131 "DOF Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
132 database->add_field_entry(
133 "DOF Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
134 b2linalg::Vector<b2000::csda<double>> tmp;
135 for (
size_t j = 0; j != nks.size2(); ++j) {
138 if (normalize) { tmp.normalize(); }
139 domain->save_global_dof(
140 sol, b2linalg::Vector<b2000::csda<double>, b2linalg::Vdense_constref>(tmp));
145 void set_system_null_space(
146 const b2linalg::Matrix<std::complex<double>, b2linalg::Mrectangle_constref>& nks,
147 bool normalize =
true,
const std::string suffix =
"NS")
override {
148 SetName sol = case_->get_string(
"DOF_SOL", std::string(
"DISP")) +
"_" + suffix;
149 if (sol.case_undef()) { sol.case_(case_->get_id()); }
150 database->add_field_entry(
151 "DOF Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
152 database->add_field_entry(
153 "DOF Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
154 b2linalg::Vector<std::complex<double>> tmp;
155 for (
size_t j = 0; j != nks.size2(); ++j) {
158 if (normalize) { tmp.normalize(); }
159 domain->save_global_dof(
160 sol, b2linalg::Vector<std::complex<double>, b2linalg::Vdense_constref>(tmp));
165 bool is_need_refinement()
const override {
return need_refinement; }
167 void set_need_refinement()
override { need_refinement =
true; }
169 b2000::Solution::gradient_container get_gradient_container()
override;
171 void add_sub_solution(Solution& s) { sub_solution.push_back(&s); }
173 void remove_sub_solution(Solution& s) {
174 sub_solution_t::iterator i = std::find(sub_solution.begin(), sub_solution.end(), &s);
175 if (i == sub_solution.end()) { Exception() <<
THROW; }
176 sub_solution.erase(i);
179 void set_value(
const std::string& key,
bool value)
override { key_bool_value[key] = value; }
180 void set_value(
const std::string& key,
int value)
override { key_int_value[key] = value; }
181 void set_value(
const std::string& key,
double value)
override { key_double_value[key] = value; }
182 void set_value(
const std::string& key, std::string& value)
override {
183 key_string_value[key] = value;
187 using key_bool_value_t = std::map<std::string, bool>;
188 key_bool_value_t key_bool_value;
189 using key_int_value_t = std::map<std::string, int>;
190 key_int_value_t key_int_value;
191 using key_double_value_t = std::map<std::string, double>;
192 key_double_value_t key_double_value;
193 using key_string_value_t = std::map<std::string, std::string>;
194 key_string_value_t key_string_value;
197 void store_value_in_rtable_and_clear(RTable& rt) {
198 for (key_bool_value_t::iterator i = key_bool_value.begin(); i != key_bool_value.end();
200 rt.set(i->first, i->second);
202 key_bool_value.clear();
203 for (key_int_value_t::iterator i = key_int_value.begin(); i != key_int_value.end(); ++i) {
204 rt.set(i->first, i->second);
206 key_int_value.clear();
207 for (key_double_value_t::iterator i = key_double_value.begin(); i != key_double_value.end();
209 rt.set(i->first, i->second);
211 key_double_value.clear();
212 for (key_string_value_t::iterator i = key_string_value.begin(); i != key_string_value.end();
214 rt.set(i->first, i->second);
216 key_string_value.clear();
219 DataBaseFieldSet* database{};
222 b2000::b2dbv3::Case* case_{};
224 bool need_refinement{};
226 using sub_solution_t = std::vector<b2000::Solution*>;
227 sub_solution_t sub_solution{};
229 void set_cycle(
int cycle_,
bool end_of_stage_) {
231 end_of_stage = end_of_stage_;
232 db_grad_name.cycle(cycle);
235 void terminate_gradient() {
237 for (
size_t i = 0; i != list_branch.size(); ++i) {
238 SetName grad_id = db_grad_name;
239 grad_id.branch(domain->list_branch[i].id);
240 if (subcase_id != 0) { grad_id.subcase(subcase_id); }
241 list_branch[i].save_fields(grad_id, *database);
248 void add_gradient_solution_case_information(RTable& rtable) {
249 std::set<std::string> list_sampling_fields;
250 for (
size_t i = 0; i != list_branch.size(); ++i) {
251 for (Branch::field_list_i_t::const_iterator j = list_branch[i].field_list_i.begin();
252 j != list_branch[i].field_list_i.end(); ++j) {
253 list_sampling_fields.insert(j->first.name);
255 for (Branch::field_list_d_t::const_iterator j = list_branch[i].field_list_d.begin();
256 j != list_branch[i].field_list_d.end(); ++j) {
257 list_sampling_fields.insert(j->first.name);
259 for (Branch::field_list_cs_t::const_iterator j = list_branch[i].field_list_cs.begin();
260 j != list_branch[i].field_list_cs.end(); ++j) {
261 list_sampling_fields.insert(j->first.name);
263 for (Branch::field_list_c_t::const_iterator j = list_branch[i].field_list_c.begin();
264 j != list_branch[i].field_list_c.end(); ++j) {
265 list_sampling_fields.insert(j->first.name);
268 if (!list_sampling_fields.empty()) {
269 std::string list_sampling_fields_string;
270 for (std::set<std::string>::const_iterator i = list_sampling_fields.begin();;) {
271 list_sampling_fields_string += *i;
272 if (++i == list_sampling_fields.end()) {
break; }
273 list_sampling_fields_string +=
',';
275 rtable.set(
"SP_SOL", list_sampling_fields_string);
280 bool list_fields_to_compute_neg{
true};
281 std::set<std::string> list_fields_to_compute;
283 friend class GradientContainer;
286 SetName db_grad_name;
289 bool have_gradient{};
290 std::set<GradientContainerOffload*> gradient_container_set;
295 Branch(GradientSolution* parent_)
296 : parent(parent_), old_ip_list_size(0), old_elem_ip_list_size(0) {}
298 GradientSolution* parent;
300 struct CompInternalElementPosition
301 :
public std::function<bool(
302 b2000::GradientContainer::InternalElementPosition,
303 b2000::GradientContainer::InternalElementPosition)> {
304 constexpr bool operator()(
307 constexpr double eps = 1e-7;
308 if (a.layer != b.layer) {
return a.layer < b.layer; }
309 if (std::abs(a.t - b.t) > eps) {
return a.t < b.t; }
310 if (std::abs(a.s - b.s) > eps) {
return a.s < b.s; }
311 if (std::abs(a.r - b.r) > eps) {
return a.r < b.r; }
321 using ip_list_t = std::map<
323 CompInternalElementPosition>;
325 size_t old_ip_list_size;
326 std::string old_ip_list_name;
329 mcInt32 branch_elem_id;
330 ip_list_t::iterator ip;
331 bool operator<(
const ElemIPptr& b)
const {
332 if (branch_elem_id != b.branch_elem_id) {
333 return branch_elem_id < b.branch_elem_id;
335 return ip == b.ip ? false : CompInternalElementPosition()(ip->first, b.ip->first);
339 using elem_ip_list_t = std::map<ElemIPptr, mcInt32>;
340 elem_ip_list_t elem_ip_list;
341 size_t old_elem_ip_list_size;
342 std::string old_elem_ip_list_name;
345 mcInt32 branch_elem_id;
347 ElemIP(
const ElemIPptr& ei) : branch_elem_id(ei.branch_elem_id), ip(ei.ip->second) {}
350 SetName old_coor_ip_name;
351 SetName old_mbase_ip_name;
353 struct CompFieldDescription :
public std::function<bool(
354 b2000::GradientContainer::FieldDescription,
355 b2000::GradientContainer::FieldDescription)> {
359 return a.name < b.name;
363 template <
typename T>
364 struct FieldValueReduction {
365 FieldValueReduction()
382 void add(
const T v,
const elem_ip_list_t::iterator pos,
const double area) {
383 if (!max_set || v > max) {
388 if (!min_set || v < min) {
393 integration += area * v;
400 elem_ip_list_t::iterator max_pos;
401 elem_ip_list_t::iterator min_pos;
405 template <
typename T>
407 std::vector<elem_ip_list_t::iterator> elem_ip;
408 std::vector<T> values;
409 std::vector<FieldValueReduction<T>> vr_value;
411 using field_list_i_t = std::map<
413 field_list_i_t field_list_i;
414 field_list_i_t::iterator field_list_i_cur;
416 using field_list_d_t = std::map<
418 field_list_d_t field_list_d;
419 field_list_d_t::iterator field_list_d_cur;
421 using field_list_cs_t = std::map<
423 CompFieldDescription>;
424 field_list_cs_t field_list_cs;
425 field_list_cs_t::iterator field_list_cs_cur;
427 using field_list_c_t = std::map<
429 CompFieldDescription>;
430 field_list_c_t field_list_c;
431 field_list_c_t::iterator field_list_c_cur;
434 b2linalg::Matrix<mcOff, b2linalg::Mrectangle> strs;
436 void save_fields(
const SetName& grad_id, DataBaseFieldSet& database) {
437 if (strs.size2() != 0) {
438 database.set(grad_id, strs);
441 desc.set(
"TYPE",
"B2000-GRAD");
442 database.set_desc(grad_id, desc);
447 for (std::set<GradientContainerOffload*>::iterator i =
448 parent->gradient_container_set.begin();
449 i != parent->gradient_container_set.end(); ++i) {
450 (*i)->offload_data();
455 for (Branch::ip_list_t::iterator i = ip_list.begin(); i != ip_list.end();) {
456 if (i->second != 0) {
464 if (ip_list.empty()) {
return; }
465 if (new_ip || ip_list.size() != old_ip_list_size) {
466 std::vector<b2000::GradientContainer::InternalElementPosition> ip_list_v;
467 ip_list_v.reserve(ip_list.size());
468 for (Branch::ip_list_t::iterator i = ip_list.begin(); i != ip_list.end(); ++i) {
469 ip_list_v.push_back(i->first);
470 ++ip_list_v.back().layer;
472 SetName ip_name(grad_id);
475 std::vector<DataBase::ArrayTableCol> col_att;
476 col_att.push_back(DataBase::ArrayTableCol(
477 "rst", 3, ip_list_v.size(), &ip_list_v.front().r,
479 col_att.push_back(DataBase::ArrayTableCol(
480 "layer", 1, ip_list_v.size(), &ip_list_v.front().layer,
482 database.set(ip_name, col_att);
484 old_ip_list_name = ip_name;
485 old_ip_list_size = ip_list.size();
488 bool new_elem_ip =
false;
489 size_t elem_ip_id = 0;
490 for (Branch::elem_ip_list_t::iterator i = elem_ip_list.begin();
491 i != elem_ip_list.end();) {
492 if (i->second != 0) {
493 elem_ip_list.erase(i++);
496 i->second = ++elem_ip_id;
500 if (new_ip || new_elem_ip || elem_ip_list.size() != old_elem_ip_list_size) {
501 std::vector<ElemIP> elem_ip_list_v;
502 elem_ip_list_v.reserve(elem_ip_list.size());
503 for (Branch::elem_ip_list_t::iterator i = elem_ip_list.begin();
504 i != elem_ip_list.end(); ++i) {
505 elem_ip_list_v.push_back(i->first);
507 SetName elem_ip_name(grad_id);
508 elem_ip_name.gname(
"ELEM_IP");
509 elem_ip_name.subcase(0);
511 std::vector<DataBase::ArrayTableCol> col_att;
512 col_att.push_back(DataBase::ArrayTableCol(
513 "elem", 1, elem_ip_list_v.size(), &elem_ip_list_v.front().branch_elem_id,
515 col_att.push_back(DataBase::ArrayTableCol(
516 "ip", 1, elem_ip_list_v.size(), &elem_ip_list_v.front().ip,
sizeof(ElemIP)));
517 database.set(elem_ip_name, col_att);
520 std::ostringstream o;
521 SetName etab_name(
"ETAB");
522 etab_name.branch(grad_id.get_branch());
523 o << 1 <<
"->" << etab_name <<
"," << 2 <<
"->" << old_ip_list_name;
524 desc.set(
"JOIN", o.str());
525 database.set_desc(elem_ip_name, desc);
528 old_elem_ip_list_name = elem_ip_name;
529 old_elem_ip_list_size = elem_ip_list.size();
532 save_fields_typed<int>(grad_id, database, new_elem_ip, field_list_i);
533 save_fields_typed<double>(grad_id, database, new_elem_ip, field_list_d);
534 save_fields_typed<b2000::csda<double>>(grad_id, database, new_elem_ip, field_list_cs);
535 save_fields_typed<std::complex<double>>(grad_id, database, new_elem_ip, field_list_c);
538 template <
typename T>
539 void save_fields_typed(
540 const SetName& grad_id, DataBaseFieldSet& database,
const bool new_elem_ip,
545 for (std::set<GradientContainerOffload*>::iterator i =
546 parent->gradient_container_set.begin();
547 i != parent->gradient_container_set.end(); ++i) {
548 (*i)->offload_data();
551 for (
typename std::map<
553 CompFieldDescription>::iterator f = field_list.begin();
554 f != field_list.end(); ++f) {
555 if (f->second.elem_ip.empty()) {
continue; }
557 SetName field_name(grad_id);
558 field_name.gname(f->first.name);
561 if (f->first.name ==
"COOR_IP") {
562 if (!new_elem_ip && field_name.get_case() == old_coor_ip_name.get_case()
563 && field_name.get_subcase() == old_coor_ip_name.get_subcase()) {
564 f->second.elem_ip.clear();
565 f->second.values.clear();
568 old_coor_ip_name = field_name;
571 if (f->first.name ==
"MBASE_IP") {
572 if (!new_elem_ip && field_name.get_case() == old_mbase_ip_name.get_case()
573 && field_name.get_subcase() == old_mbase_ip_name.get_subcase()) {
574 f->second.elem_ip.clear();
575 f->second.values.clear();
578 old_mbase_ip_name = field_name;
582 database.add_field_entry(
583 f->first.description, field_name.get_gname(),
"FIELD-SAMPLING",
"BRANCH",
584 false,
false,
false);
585 std::vector<mcInt32> elem_ip_tmp;
586 std::vector<DataBase::ArrayTableCol> col_att;
587 bool field_pos_sorted =
true;
588 if (f->second.elem_ip.size() > 1) {
589 const std::vector<elem_ip_list_t::iterator>::const_iterator i_end =
590 f->second.elem_ip.end() - 1;
591 for (std::vector<elem_ip_list_t::iterator>::const_iterator i =
592 f->second.elem_ip.begin();
594 std::vector<elem_ip_list_t::iterator>::const_iterator ii = i++;
595 if (!((*i)->second > (*ii)->second)) {
596 field_pos_sorted =
false;
601 if (f->second.elem_ip.size() == old_elem_ip_list_size) {
602 if (!field_pos_sorted) {
603 const int field_nb_comp = f->first.nb_comp;
604 std::vector<std::pair<mcInt32, size_t>> elem_ip_tmp1(
605 f->second.elem_ip.size());
606 for (
size_t i = 0; i != elem_ip_tmp1.size(); ++i) {
607 elem_ip_tmp1[i].first = f->second.elem_ip[i]->second;
608 elem_ip_tmp1[i].second = i * field_nb_comp;
610 std::sort(elem_ip_tmp1.begin(), elem_ip_tmp1.end(), CompareFirstOfPair());
611 std::vector<T> values_tmp;
612 values_tmp.reserve(elem_ip_tmp1.size());
613 const typename std::vector<T>::const_iterator fi = f->second.values.begin();
614 for (
size_t i = 0; i != elem_ip_tmp1.size(); ++i) {
616 values_tmp.end(), fi + elem_ip_tmp1[i].second,
617 fi + elem_ip_tmp1[i].second + field_nb_comp);
619 f->second.values.swap(values_tmp);
622 elem_ip_tmp.resize(f->second.elem_ip.size());
623 if (field_pos_sorted) {
624 for (
size_t i = 0; i != elem_ip_tmp.size(); ++i) {
625 elem_ip_tmp[i] = f->second.elem_ip[i]->second;
628 const int field_nb_comp = f->first.nb_comp;
629 std::vector<std::pair<mcInt32, size_t>> elem_ip_tmp1(
630 f->second.elem_ip.size());
631 for (
size_t i = 0; i != elem_ip_tmp1.size(); ++i) {
632 elem_ip_tmp1[i].first = f->second.elem_ip[i]->second;
633 elem_ip_tmp1[i].second = i * field_nb_comp;
635 std::sort(elem_ip_tmp1.begin(), elem_ip_tmp1.end(), CompareFirstOfPair());
636 std::vector<T> values_tmp;
637 values_tmp.reserve(elem_ip_tmp1.size());
638 const typename std::vector<T>::const_iterator fi = f->second.values.begin();
639 for (
size_t i = 0; i != elem_ip_tmp1.size(); ++i) {
641 values_tmp.end(), fi + elem_ip_tmp1[i].second,
642 fi + elem_ip_tmp1[i].second + field_nb_comp);
643 elem_ip_tmp[i] = elem_ip_tmp1[i].first;
645 f->second.values.swap(values_tmp);
647 col_att.push_back(DataBase::ArrayTableCol(
648 "pos", 1, elem_ip_tmp.size(), &elem_ip_tmp.front(),
sizeof(mcInt32)));
650 f->second.elem_ip.clear();
651 col_att.push_back(DataBase::ArrayTableCol(
652 "value", f->first.nb_comp, f->second.values.size() / f->first.nb_comp,
653 &f->second.values.front(),
sizeof(T) * f->first.nb_comp));
654 database.set(field_name, col_att);
655 f->second.values.clear();
658 std::ostringstream o;
659 o << col_att.size() - 1 <<
"->" << old_elem_ip_list_name;
660 desc.set(
"JOIN", o.str());
661 desc.set(
"DOMAIN",
"FIELD-SAMPLING");
662 desc.set(
"COMP_NAMES", f->first.components_name);
663 desc.set(
"DESCR", f->first.description);
664 desc.set(
"DOMAIN_NDIM", f->first.domain_ndim);
665 desc.set(
"NB_COMP", f->first.nb_comp);
666 if (f->first.tensor_order) {
667 desc.set(
"TENSOR_ORDER", f->first.tensor_order);
668 desc.set(
"TENSOR_SIZE", f->first.tensor_size);
669 desc.set(
"TENSOR_SYM", (f->first.tensor_symmetric ? 1 : 0));
673 if (f->first.tensor_order < 0) {
676 std::vector<mcInt32> max_elem_ip;
677 std::vector<mcInt32> min_elem_ip;
678 std::vector<T> integral;
679 assert((
int)f->second.vr_value.size() == f->first.nb_comp);
680 for (
int i = 0; i != f->first.nb_comp; ++i) {
681 assert(f->second.vr_value[i].max_pos != elem_ip_list.end());
682 assert(f->second.vr_value[i].min_pos != elem_ip_list.end());
683 max.push_back(f->second.vr_value[i].max);
684 min.push_back(f->second.vr_value[i].min);
685 max_elem_ip.push_back(f->second.vr_value[i].max_pos->second);
686 min_elem_ip.push_back(f->second.vr_value[i].min_pos->second);
687 integral.push_back(f->second.vr_value[i].integration);
688 f->second.vr_value[i].reset();
690 desc.set(
"MAX", max);
691 desc.set(
"MAX_ELEM_IP", max_elem_ip);
692 desc.set(
"MIN", min);
693 desc.set(
"MIN_ELEM_IP", min_elem_ip);
694 desc.set(
"INTEGRAL", integral);
696 database.set_desc(field_name, desc);
702 std::vector<Branch> list_branch;
707 GradientContainer(GradientSolution& solution_) : solution(solution_) {}
709 ~GradientContainer()
override {
710 b2Mutex::scoped_lock lock(solution.mutex);
713 std::set<GradientContainerOffload*>::iterator i =
714 solution.gradient_container_set.find(
this);
715 if (i != solution.gradient_container_set.end()) {
716 solution.gradient_container_set.erase(i);
720 bool set_current_element(
const Element& e)
override {
721 Context& c = get_context();
722 const std::pair<ssize_t, size_t> new_eid =
723 solution.domain->get_internal_branch_and_element_id(e);
724 if (new_eid != c.eid) {
725 b2Mutex::scoped_lock lock(solution.mutex);
727 offload_data_for_context(c);
729 c.branch = &solution.list_branch[c.eid.first];
730 c.element_volume = 0;
732 assert(c.branch !=
nullptr);
736 void set_current_position(
const InternalElementPosition& pos,
const double volume)
override {
737 Context& c = get_context();
738 assert(c.branch !=
nullptr);
740 c.point = c.point_data_map.insert(
741 c.point, PointDataMap::value_type(PointKey(c.eid, pos), PointData()));
742 (*c.point).second.volume = volume;
743 c.element_volume += volume;
746 void set_current_volume(
const double volume)
override {
747 Context& c = get_context();
748 assert(c.point != c.point_data_map.end());
749 (*c.point).second.volume = volume;
750 c.element_volume += volume;
753 double get_element_volume()
override {
return get_context().element_volume; }
755 void set_field_value(
const FieldDescription& descr,
const int* value)
override {
756 Context& c = get_context();
757 assert(c.point != c.point_data_map.end());
758 FieldDescriptionSet::const_iterator i = c.descr_set.insert(descr).first;
759 PointData& p = (*c.point).second;
760 p.idata.descr.push_back(i);
761 p.idata.data.insert(p.idata.data.end(), value, value + descr.nb_comp);
764 void set_field_value(
const FieldDescription& descr,
const double* value)
override {
765 Context& c = get_context();
766 assert(c.point != c.point_data_map.end());
767 FieldDescriptionSet::const_iterator i = c.descr_set.insert(descr).first;
768 PointData& p = (*c.point).second;
769 p.ddata.descr.push_back(i);
770 p.ddata.data.insert(p.ddata.data.end(), value, value + descr.nb_comp);
773 void set_field_value(
const FieldDescription& descr,
const b2000::csda<double>* value)
override {
774 Context& c = get_context();
775 assert(c.point != c.point_data_map.end());
776 FieldDescriptionSet::const_iterator i = c.descr_set.insert(descr).first;
777 PointData& p = (*c.point).second;
778 p.csdata.descr.push_back(i);
779 p.csdata.data.insert(p.csdata.data.end(), value, value + descr.nb_comp);
782 void set_field_value(
783 const FieldDescription& descr,
const std::complex<double>* value)
override {
784 Context& c = get_context();
785 assert(c.point != c.point_data_map.end());
786 FieldDescriptionSet::const_iterator i = c.descr_set.insert(descr).first;
787 PointData& p = (*c.point).second;
788 p.cdata.descr.push_back(i);
789 p.cdata.data.insert(p.cdata.data.end(), value, value + descr.nb_comp);
792 void set_failure_index(
const double failure_index)
override {
793 Context& c = get_context();
794 assert(c.point != c.point_data_map.end());
795 (*c.point).second.failure_index = std::max((*c.point).second.failure_index, failure_index);
798 void set_current_discrete_position(
const DiscreteInternalElementPosition& pos)
override {
802 void set_discrete_value(
const FieldDescription& descr,
const int* value)
override {
806 void set_discrete_value(
const FieldDescription& descr,
const double* value)
override {
810 void set_discrete_value(
811 const FieldDescription& descr,
const b2000::csda<double>* value)
override {
815 void set_discrete_value(
816 const FieldDescription& descr,
const std::complex<double>* value)
override {
820 bool compute_field_value(
const std::string& name)
const override {
821 std::set<std::string>::const_iterator i = solution.list_fields_to_compute.find(name);
822 if (i == solution.list_fields_to_compute.end()) {
823 return solution.list_fields_to_compute_neg;
829 GradientSolution& solution;
833 std::pair<ssize_t, size_t> eid;
834 InternalElementPosition ip;
836 PointKey(
const std::pair<ssize_t, size_t> eid_, InternalElementPosition ip_)
837 : eid(eid_), ip(ip_) {}
839 bool operator<(
const PointKey& o)
const {
840 static constexpr double eps = 1e-7;
841 if (eid != o.eid) {
return eid < o.eid; }
842 if (ip.layer != o.ip.layer) {
return ip.layer < o.ip.layer; }
843 if (std::abs(ip.t - o.ip.t) > eps) {
return ip.t < o.ip.t; }
844 if (std::abs(ip.s - o.ip.s) > eps) {
return ip.s < o.ip.s; }
845 if (std::abs(ip.r - o.ip.r) > eps) {
return ip.r < o.ip.r; }
850 struct CompFieldDescription :
public std::function<bool(FieldDescription, FieldDescription)> {
851 bool operator()(
const FieldDescription& a,
const FieldDescription& b)
const {
852 return a.name < b.name;
856 using FieldDescriptionSet = std::set<FieldDescription, CompFieldDescription>;
858 template <
typename T>
860 std::vector<FieldDescriptionSet::const_iterator> descr;
863 using IData = Data<int>;
864 using DData = Data<double>;
865 using CSData = Data<b2000::csda<double>>;
866 using CData = Data<std::complex<double>>;
871 double failure_index;
877 PointData() : volume(0), failure_index(0) {}
879 using PointDataMap = std::map<PointKey, PointData>;
882 GradientSolution::Branch* branch;
883 std::pair<ssize_t, size_t> eid;
884 FieldDescriptionSet descr_set;
885 PointDataMap point_data_map;
886 PointDataMap::iterator point;
887 double element_volume;
889 Context() : branch(nullptr), eid(-1, 0), point(point_data_map.begin()), element_volume(0) {}
893 eid = std::pair<ssize_t, size_t>(-1, 0);
894 point_data_map.clear();
895 point = point_data_map.begin();
900 tbb::enumerable_thread_specific<Context> contexts;
905 Context& get_context() {
907 return contexts.local();
913 void offload_data()
override {
915 for (tbb::enumerable_thread_specific<Context>::iterator i = contexts.begin();
916 i != contexts.end(); ++i) {
918 offload_data_for_context(c);
921 offload_data_for_context(the_context);
925 void offload_idata_for_context_and_point(
926 Context& c,
const PointData& point_data,
927 GradientSolution::Branch::elem_ip_list_t::iterator& current_elem_ip) {
929 for (
size_t j = 0; j != point_data.idata.descr.size(); ++j) {
930 const FieldDescription& descr = *(point_data.idata.descr[j]);
931 const int* value = &point_data.idata.data[o];
934 GradientSolution::Branch::field_list_i_t::iterator k =
935 c.branch->field_list_i.find(descr);
936 if (k == c.branch->field_list_i.end()) {
937 k = c.branch->field_list_i
938 .insert(GradientSolution::Branch::field_list_i_t::value_type(
939 descr, GradientSolution::Branch::Field<int>()))
942 GradientSolution::Branch::Field<int>& f = (*k).second;
943 f.elem_ip.push_back(current_elem_ip);
944 f.values.insert(f.values.end(), value, value + descr.nb_comp);
948 void offload_ddata_for_context_and_point(
949 Context& c,
const PointData& point_data,
950 GradientSolution::Branch::elem_ip_list_t::iterator& current_elem_ip) {
952 for (
size_t j = 0; j != point_data.ddata.descr.size(); ++j) {
953 const FieldDescription& descr = *(point_data.ddata.descr[j]);
954 const double* value = &point_data.ddata.data[o];
957 GradientSolution::Branch::field_list_d_t::iterator k =
958 c.branch->field_list_d.find(descr);
959 if (k == c.branch->field_list_d.end()) {
960 k = c.branch->field_list_d
961 .insert(GradientSolution::Branch::field_list_d_t::value_type(
962 descr, GradientSolution::Branch::Field<double>()))
965 GradientSolution::Branch::Field<double>& f = (*k).second;
966 f.elem_ip.push_back(current_elem_ip);
967 f.values.insert(f.values.end(), value, value + descr.nb_comp);
968 if (descr.tensor_order < 0) {
970 if (f.vr_value.empty()) { f.vr_value.resize(descr.nb_comp); }
971 for (
int l = 0; l != descr.nb_comp; ++l) {
972 f.vr_value[l].add(value[l], current_elem_ip, point_data.volume);
978 void offload_csdata_for_context_and_point(
979 Context& c,
const PointData& point_data,
980 GradientSolution::Branch::elem_ip_list_t::iterator& current_elem_ip) {
982 for (
size_t j = 0; j != point_data.csdata.descr.size(); ++j) {
983 const FieldDescription& descr = *(point_data.csdata.descr[j]);
984 const b2000::csda<double>* value = &point_data.csdata.data[o];
987 GradientSolution::Branch::field_list_cs_t::iterator k =
988 c.branch->field_list_cs.find(descr);
989 if (k == c.branch->field_list_cs.end()) {
990 k = c.branch->field_list_cs
991 .insert(GradientSolution::Branch::field_list_cs_t::value_type(
992 descr, GradientSolution::Branch::Field<b2000::csda<double>>()))
995 GradientSolution::Branch::Field<b2000::csda<double>>& f = (*k).second;
996 f.elem_ip.push_back(current_elem_ip);
997 f.values.insert(f.values.end(), value, value + descr.nb_comp);
998 if (descr.tensor_order < 0) {
1000 if (f.vr_value.empty()) { f.vr_value.resize(descr.nb_comp); }
1001 for (
int l = 0; l != descr.nb_comp; ++l) {
1002 f.vr_value[l].add(value[l], current_elem_ip, point_data.volume);
1008 void offload_cdata_for_context_and_point(
1009 Context& c,
const PointData& point_data,
1010 GradientSolution::Branch::elem_ip_list_t::iterator& current_elem_ip) {
1012 for (
size_t j = 0; j != point_data.cdata.descr.size(); ++j) {
1013 const FieldDescription& descr = *(point_data.cdata.descr[j]);
1014 const std::complex<double>* value = &point_data.cdata.data[o];
1017 GradientSolution::Branch::field_list_c_t::iterator k =
1018 c.branch->field_list_c.find(descr);
1019 if (k == c.branch->field_list_c.end()) {
1020 k = c.branch->field_list_c
1021 .insert(GradientSolution::Branch::field_list_c_t::value_type(
1022 descr, GradientSolution::Branch::Field<std::complex<double>>()))
1025 GradientSolution::Branch::Field<std::complex<double>>& f = (*k).second;
1026 f.elem_ip.push_back(current_elem_ip);
1027 f.values.insert(f.values.end(), value, value + descr.nb_comp);
1031 void offload_data_for_context(Context& c) {
1032 if (c.point_data_map.empty()) {
return; }
1033 assert(c.branch !=
nullptr);
1036 PointDataMap::const_iterator imax = c.point_data_map.begin();
1037 for (PointDataMap::const_iterator i = c.point_data_map.begin(); i != c.point_data_map.end();
1039 if ((*i).second.failure_index > (*imax).second.failure_index) { imax = i; }
1042 GradientSolution::Branch::ip_list_t::iterator current_ip = c.branch->ip_list.end();
1043 GradientSolution::Branch::elem_ip_list_t::iterator current_elem_ip =
1044 c.branch->elem_ip_list.end();
1047 for (PointDataMap::const_iterator i = c.point_data_map.begin(); i != c.point_data_map.end();
1049 const PointKey& key = (*i).first;
1050 const PointData&
data = (*i).second;
1053 if ((*imax).second.failure_index >
data.failure_index) {
continue; }
1057 current_ip = c.branch->ip_list.insert(
1058 current_ip, GradientSolution::Branch::ip_list_t::value_type(key.ip, 0));
1059 current_ip->second = 0;
1060 const GradientSolution::Branch::ElemIPptr elem_ip_id = {
1061 mcInt32(c.eid.second) + 1, current_ip};
1062 current_elem_ip = c.branch->elem_ip_list.insert(
1064 GradientSolution::Branch::elem_ip_list_t::value_type(elem_ip_id, 0));
1065 current_elem_ip->second = 0;
1068 offload_idata_for_context_and_point(c, data, current_elem_ip);
1069 offload_ddata_for_context_and_point(c, data, current_elem_ip);
1070 offload_csdata_for_context_and_point(c, data, current_elem_ip);
1071 offload_cdata_for_context_and_point(c, data, current_elem_ip);
1079inline b2000::Solution::gradient_container GradientSolution::get_gradient_container() {
1080 int gi = case_->get_int(
"GRADIENTS", 0);
1081 have_gradient =
false;
1083 if (gi == 0) {
return b2000::Solution::gradient_container(
nullptr); }
1084 }
else if (!((gi > 0 && (cycle % gi == 0 || end_of_stage)) || (gi == -1 && end_of_stage))) {
1085 return b2000::Solution::gradient_container(
nullptr);
1087 have_gradient =
true;
1089 b2dbv3::GradientContainer* gc =
new b2dbv3::GradientContainer(*
this);
1090 gradient_container_set.insert(gc);
1091 return b2000::Solution::gradient_container(gc);
1094template <
typename T>
1095class SolutionStaticLinear :
public b2000::b2dbv3::GradientSolution,
1096 public b2000::SolutionStaticLinear<T> {
1098 bool compute_dof()
const override {
return true; }
1100 void set_subcase_id(
int subcase_id_)
override {
1101 b2000::b2dbv3::GradientSolution::set_subcase_id(subcase_id_);
1104 void set_dof(
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof)
override {
1105 SetName sol = case_->get_string(
"DOF_SOL", std::string(
"DISP"));
1106 if (sol.case_undef()) { sol.case_(case_->get_id()); }
1107 if (subcase_id != 0) { sol.subcase(subcase_id); }
1108 database->add_field_entry(
1109 "DOF Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
1110 database->add_field_entry(
1111 "DOF Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
1112 domain->save_global_dof(sol, dof);
1115 void get_dof(b2linalg::Vector<T, b2linalg::Vdense_ref> dof)
override {
1116 SetName sol = case_->get_string(
"DOF_SOL", std::string(
"DISP"));
1117 if (sol.case_undef()) { sol.case_(case_->get_id()); }
1118 if (subcase_id != 0) { sol.subcase(subcase_id); }
1119 domain->load_global_dof(sol, dof);
1122 bool compute_natural_boundary_condition()
const override {
return true; }
1124 void set_natural_boundary_condition(
1125 const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof)
override {
1126 SetName sol = case_->get_string(
"NBC_SOL",
"FORC");
1127 if (sol.case_undef()) { sol.case_(case_->get_id()); }
1128 if (subcase_id != 0) { sol.subcase(subcase_id); }
1129 database->add_field_entry(
1130 "NBC Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
1131 database->add_field_entry(
1132 "NBC Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
1133 domain->save_global_dof(sol, dof);
1136 bool compute_constraint_value()
const override {
return case_->get_bool(
"COMPUTE_RCFO",
true); }
1138 void set_constraint_value(
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof)
override {
1139 SetName sol = case_->get_string(
"RESIDUUM_SOL",
"RCFO");
1140 if (sol.case_undef()) { sol.case_(case_->get_id()); }
1141 if (subcase_id != 0) { sol.subcase(subcase_id); }
1142 database->add_field_entry(
1143 "Residuum Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
1144 database->add_field_entry(
1145 "Residuum Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
1146 domain->save_global_dof(sol, dof);
1149 void terminate_case(
bool success,
const RTable& attributes)
override {
1150 terminate_gradient();
1151 RTable& rtable = case_->get_solution_rtable();
1152 rtable.update(attributes);
1153 store_value_in_rtable_and_clear(rtable);
1154 rtable.set(
"TERMINATION", success ?
"NORMAL" :
"FAILURE");
1156 "DOF_SOL", SetName(case_->get_string(
"DOF_SOL", std::string(
"DISP"))).get_gname());
1158 "NBC_SOL", SetName(case_->get_string(
"NBC_SOL", std::string(
"FORC"))).get_gname());
1159 if (compute_constraint_value()) {
1162 SetName(case_->get_string(
"RESIDUUM_SOL", std::string(
"RCFO"))).get_gname());
1164 add_gradient_solution_case_information(rtable);
1165 SetName name(
"SOLUTION");
1166 name.case_(case_->get_id());
1167 database->set(name, rtable);
1171 using type_t = ObjectTypeComplete<SolutionStaticLinear, Solution::type_t>;
1175template <
typename T>
1176typename SolutionStaticLinear<T>::type_t SolutionStaticLinear<T>::type(
1177 "SolutionStaticLinear", type_name<T>(),
1178 StringList(
"STATIC_LINEAR_SOLUTION",
"LINEAR",
"LINEAR_P_REFINEMENT"), module,
1179 &b2000::Solution::type);
1181template <
typename T>
1182class SolutionFreeVibration :
public b2000::b2dbv3::GradientSolution,
1183 public b2000::SolutionFreeVibration<T> {
1186 GradientSolution::set_case(case__);
1191 int& number_of_mode,
char which[3], T& sigma_min, T& sigma_max)
const override {
1192 sigma_min = case_->get_csda_double(
"SHIFT", 0.0);
1193 sigma_min *= (M_PIl * 2);
1194 sigma_min *= sigma_min;
1195 sigma_max = sigma_min;
1196 number_of_mode = case_->get_int(
"NMODES", 1);
1197 std::string whichs = case_->get_string(
"WHICH_EIGENVALUES",
"SM");
1198 strcpy(which, whichs.c_str());
1202 int mode, T eigenvalue,
1203 const b2linalg::Vector<T, b2linalg::Vdense_constref>& eigenvector)
override {
1204 database->add_field_entry(
"Eigenmodes",
"MODE",
"NODE",
"BRANCH",
false,
false,
false);
1205 database->add_field_entry(
"Eigenmodes",
"MODE_E",
"CELL",
"BRANCH",
false,
false,
false);
1206 SetName name(
"MODE");
1207 if (name.case_undef()) { name.case_(case_->get_id()); }
1211 rtable.set(
"MODE", mode);
1212 rtable.set(
"EIGVAL", eigenvalue);
1213 bool pos_eigenvalue =
true;
1214 if constexpr (std::is_same<T, double>::value) { pos_eigenvalue = eigenvalue >= 0; }
1215 if (pos_eigenvalue) {
1216 T w =
sqrt(eigenvalue);
1217 rtable.set(
"OMEGA", w);
1218 T freq = w /
static_cast<T
>(2 * M_PIl);
1219 rtable.set(
"FREQ", freq);
1221 rtable.set(
"TYPE",
"FREQ");
1222 if (case_->get_bool(
"M_ORTHONORMAL",
true) ==
true) {
1225 rtable.set(
"MODK", eigenvalue);
1226 rtable.set(
"MODM", 1.0);
1227 domain->save_global_dof(name, eigenvector, rtable);
1230 T inv_norm_inf = 1.0 / eigenvector.norm_inf();
1231 rtable.set(
"MODK", inv_norm_inf * inv_norm_inf * eigenvalue);
1232 rtable.set(
"MODM", inv_norm_inf * inv_norm_inf);
1233 b2linalg::Vector<T, b2linalg::Vdense> tmp;
1234 tmp = inv_norm_inf * eigenvector;
1235 domain->save_global_dof(
1236 name, (
const b2linalg::Vector<T, b2linalg::Vdense_constref>)(tmp), rtable);
1240 void terminate_case(
bool success,
const RTable& attributes)
override {
1241 terminate_gradient();
1242 RTable& rtable = case_->get_solution_rtable();
1243 store_value_in_rtable_and_clear(rtable);
1244 rtable.update(attributes);
1245 rtable.set(
"TERMINATION", success ?
"NORMAL" :
"FAILURE");
1246 rtable.set(
"NMODES", nmodes);
1247 rtable.set(
"DOF_SOL",
"MODE");
1248 add_gradient_solution_case_information(rtable);
1249 SetName name(
"SOLUTION");
1250 name.case_(case_->get_id());
1251 database->set(name, rtable);
1255 using type_t = ObjectTypeComplete<SolutionFreeVibration, Solution::type_t>;
1262template <
typename T>
1263typename SolutionFreeVibration<T>::type_t SolutionFreeVibration<T>::type(
1264 "SolutionFreeVibration", type_name<T>(),
1266 "FREE_VIBRATION_SOLUTION",
"VIBRATION",
"FREE_VIBRATION",
1267 "FREQUENCY_DEPENDENT_FREE_VIBRATION"),
1268 module, &b2000::Solution::type);
1270template <
typename T>
1271class SolutionLinearisedPrebuckling :
public b2000::b2dbv3::GradientSolution,
1272 public b2000::SolutionLinearisedPrebuckling<T> {
1275 GradientSolution::set_case(case__);
1279 void set_subcase_id(
int subcase_id_)
override {
1280 b2000::b2dbv3::GradientSolution::set_subcase_id(subcase_id_);
1283 bool compute_dof()
const override {
return true; }
1285 void set_dof(
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof)
override {
1286 SetName sol = case_->get_string(
"DOF_SOL", std::string(
"DISP"));
1287 if (sol.case_undef()) { sol.case_(case_->get_id()); }
1288 database->add_field_entry(
1289 "DOF Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
1290 database->add_field_entry(
1291 "DOF Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
1292 domain->save_global_dof(sol, dof);
1295 void get_dof(b2linalg::Vector<T, b2linalg::Vdense_ref> dof)
override {
1296 SetName sol = case_->get_string(
"DOF_SOL", std::string(
"DISP"));
1297 if (sol.case_undef()) { sol.case_(case_->get_id()); }
1298 domain->load_global_dof(sol, dof);
1301 bool compute_natural_boundary_condition()
const override {
return true; }
1303 void set_natural_boundary_condition(
1304 const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof)
override {
1305 SetName sol = case_->get_string(
"NBC_SOL",
"FORC");
1306 if (sol.case_undef()) { sol.case_(case_->get_id()); }
1307 database->add_field_entry(
1308 "NBC Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
1309 database->add_field_entry(
1310 "NBC Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
1311 domain->save_global_dof(sol, dof);
1314 bool compute_constraint_value()
const override {
return case_->get_bool(
"COMPUTE_RCFO",
true); }
1316 void set_constraint_value(
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof)
override {
1317 SetName sol = case_->get_string(
"RESIDUUM_SOL",
"REFO");
1318 if (sol.case_undef()) { sol.case_(case_->get_id()); }
1319 database->add_field_entry(
1320 "Residuum Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
1321 database->add_field_entry(
1322 "Residuum Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
1323 domain->save_global_dof(sol, dof);
1325 void which_modes(
int& number_of_mode,
char which[3], T& sigma)
const override {
1326 sigma = case_->get_csda_double(
"SHIFT", 0.0);
1327 number_of_mode = case_->get_int(
"NMODES", 1);
1328 std::string whichs = case_->get_string(
"WHICH_EIGENVALUES",
"SM");
1329 strcpy(which, whichs.c_str());
1333 int mode, T eigenvalue,
1334 const b2linalg::Vector<T, b2linalg::Vdense_constref>& eigenvector)
override {
1335 database->add_field_entry(
"Buckling modes",
"BMODE",
"NODE",
"BRANCH",
false,
false,
false);
1336 database->add_field_entry(
1337 "Buckling modes",
"BMODE_E",
"CELL",
"BRANCH",
false,
false,
false);
1338 SetName name(
"BMODE");
1339 if (name.case_undef()) { name.case_(case_->get_id()); }
1341 rtable.set(
"EIGVAL", eigenvalue);
1342 rtable.set(
"TYPE",
"Crit load factor");
1344 b2linalg::Vector<T, b2linalg::Vdense> tmp;
1345 tmp = (
static_cast<T
>(1.0) / eigenvector.norm_inf()) * eigenvector;
1346 domain->save_global_dof(
1347 name.subcase(mode + 1),
1348 (
const b2linalg::Vector<T, b2linalg::Vdense_constref>)(tmp), rtable);
1353 void terminate_case(
bool success,
const RTable& attributes)
override {
1354 terminate_gradient();
1355 RTable& rtable = case_->get_solution_rtable();
1356 store_value_in_rtable_and_clear(rtable);
1357 rtable.update(attributes);
1358 rtable.set(
"TERMINATION", success ?
"NORMAL" :
"FAILURE");
1359 rtable.set(
"NMODES", nmodes);
1361 "DOF_SOL", SetName(case_->get_string(
"DOF_SOL", std::string(
"DISP"))).get_gname());
1363 "NBC_SOL", SetName(case_->get_string(
"NBC_SOL", std::string(
"FORC"))).get_gname());
1364 if (compute_constraint_value()) {
1367 SetName(case_->get_string(
"RESIDUUM_SOL", std::string(
"RCFO"))).get_gname());
1369 add_gradient_solution_case_information(rtable);
1370 SetName name(
"SOLUTION");
1371 name.case_(case_->get_id());
1372 database->set(name, rtable);
1376 using type_t = ObjectTypeComplete<SolutionLinearisedPrebuckling, Solution::type_t>;
1382template <
typename T>
1383typename SolutionLinearisedPrebuckling<T>::type_t SolutionLinearisedPrebuckling<T>::type(
1384 "SolutionLinearisedPrebuckling", type_name<T>(),
1385 StringList(
"LINEARISED_PREBUCKLING_SOLUTION",
"L_BIFURCATION",
"LINEARISED_PREBUCKLING"),
1386 module, &b2000::Solution::type);
1388template <
typename T>
1389class SolutionIterative :
public GradientSolution,
virtual public b2000::SolutionIterative {
1394 end_of_stage(false),
1395 sync_db_interval(-1),
1397 time_at_start_stage(0) {}
1400 GradientSolution::set_case(case__);
1408 if (case_ != &case__) {
1410 cycle = case__.
get_int(
"STEP_INIT_NUM", 0);
1411 time_at_start_stage = 0;
1420 int c = case__.
get_int(
"STEP_INIT_NUM", 0);
1423 logger <<
logging::info <<
"Restart at step=" << c << logging::LOGFLUSH;
1427 sync_db_interval = case__.
get_int(
"SYNC_DB_INTERVAL", -1);
1430 void new_cycle(
bool end_of_stage_ =
false)
override {
1434 end_of_stage = end_of_stage_;
1435 GradientSolution::set_cycle(cycle, end_of_stage_);
1436 for (GradientSolution::sub_solution_t::iterator s = GradientSolution::sub_solution.begin();
1437 s != GradientSolution::sub_solution.end(); ++s) {
1438 dynamic_cast<b2000::SolutionIterative&
>(**s).new_cycle(end_of_stage_);
1442 void set_system_null_space(
1443 const b2linalg::Matrix<T, b2linalg::Mrectangle_constref>& nks,
bool normalize =
true,
1444 const std::string suffix =
"NS")
override {
1445 SetName sol = case_->get_string(
"DOF_SOL", std::string(
"DISP")) +
"_" + suffix;
1446 if (sol.case_undef()) { sol.case_(case_->get_id()); }
1447 sol.cycle(cycle + 1);
1448 database->add_field_entry(
1449 "DOF Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
1450 database->add_field_entry(
1451 "DOF Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
1452 b2linalg::Vector<T> tmp;
1453 for (
size_t j = 0; j != nks.size2(); ++j) {
1456 if (normalize) { tmp.normalize(); }
1457 domain->save_global_dof(sol, b2linalg::Vector<T, b2linalg::Vdense_constref>(tmp));
1461 void terminate_cycle(
double time,
double dtime,
const RTable& attributes)
override {
1462 current_time = time;
1463 terminate_gradient();
1464 store_value_in_rtable_and_clear(rtable);
1465 rtable.set(
"STAGE_ID", case_->get_stage_id());
1466 rtable.set(
"STAGE_NUMBER", case_->get_stage_number() + 1);
1467 rtable.set(
"TIME", time + time_at_start_stage);
1468 rtable.set(
"STAGE_TIME", time);
1469 rtable.set(
"DELTA_TIME", dtime);
1470 rtable.update(attributes);
1471 SetName name(
"SOLUTION-STEP");
1473 name.case_(case_->get_id());
1474 database->set(name, rtable);
1475 if (sync_db_interval == -1) {
1476 database->sync_delayed();
1477 }
else if (cycle % std::max(1, sync_db_interval) == 0) {
1480 for (GradientSolution::sub_solution_t::iterator s = GradientSolution::sub_solution.begin();
1481 s != GradientSolution::sub_solution.end(); ++s) {
1482 dynamic_cast<b2000::SolutionIterative&
>(**s).terminate_cycle(time, dtime, attributes);
1486 void terminate_stage(
bool success =
true)
override {
1487 RTable& rtable = case_->get_solution_rtable();
1488 rtable.set(
"TERMINATION", success ?
"NORMAL" :
"FAILURE");
1489 rtable.set(
"LAST_STEP", cycle);
1490 add_gradient_solution_case_information(rtable);
1491 SetName name(
"SOLUTION-STAGE");
1492 name.case_(case_->get_id());
1493 name.subcase(case_->get_stage_number() + 1);
1494 database->set(name, rtable);
1496 for (GradientSolution::sub_solution_t::iterator s = GradientSolution::sub_solution.begin();
1497 s != GradientSolution::sub_solution.end(); ++s) {
1498 dynamic_cast<b2000::SolutionIterative&
>(**s).terminate_stage(success);
1500 time_at_start_stage = current_time;
1503 size_t get_cycle_id()
override {
return cycle; }
1505 size_t get_subcycle_id()
override {
return subcycle; }
1507 std::string get_domain_state_id()
override {
1508 return SetName(
"STATE.GLOB").cycle(cycle).case_(case_->get_id());
1511 using nbc_t = TypedNaturalBoundaryCondition<T, b2linalg::Msym_compressed_col_update_inv>;
1514 RTable& get_cycle_rtable() {
return rtable; }
1518 int sync_db_interval;
1519 double current_time;
1520 double time_at_start_stage;
1524template <
typename T>
1525class SolutionStaticNonlinear :
virtual public SolutionIterative<T>,
1526 public b2000::SolutionStaticNonlinear<T> {
1528 void terminate_case(
bool success,
const RTable& attributes)
override {
1530 rtable.update(attributes);
1531 rtable.set(
"TERMINATION", success ?
"NORMAL" :
"FAILURE");
1532 rtable.set(
"NSTEPS", this->cycle);
1533 rtable.set(
"NSTAGES", this->case_->get_stage_number() + 1);
1536 SetName(this->case_->get_string(
"DOF_SOL", std::string(
"DISP"))).get_gname());
1539 SetName(this->case_->get_string(
"NBC_SOL", std::string(
"FORC"))).get_gname());
1542 SetName(this->case_->get_string(
"RESIDUUM_SOL", std::string(
"RCFO"))).get_gname());
1543 this->add_gradient_solution_case_information(rtable);
1544 SetName name(
"SOLUTION");
1545 name.case_(this->case_->get_id());
1546 this->database->set(name, rtable);
1547 this->database->sync();
1549 for (GradientSolution::sub_solution_t::iterator s = GradientSolution::sub_solution.begin();
1550 s != GradientSolution::sub_solution.end(); ++s) {
1551 dynamic_cast<b2000::SolutionIterative&
>(**s).terminate_case(success, attributes);
1556 double time,
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof,
1557 const b2linalg::Vector<T, b2linalg::Vdense_constref>& nbc,
1558 const b2linalg::Vector<T, b2linalg::Vdense_constref>& residue,
1559 bool unconverged_subcycle =
false) {
1561 rtable.set(
"STAGE_ID", this->case_->get_stage_id());
1562 rtable.set(
"STAGE", this->case_->get_stage_number());
1563 rtable.set(
"LAMBDA", time + this->time_at_start_stage);
1564 rtable.set(
"STAGE_LAMBDA", time);
1565 if (!dof.is_null()) {
1566 SetName name = this->case_->get_string(
"DOF_SOL",
"DISP");
1567 if (unconverged_subcycle) {
1568 name.cycle(this->cycle + 1);
1569 name.subcycle(this->subcycle + 1);
1571 name.cycle(this->cycle);
1573 if (name.case_undef()) { name.case_(this->case_->get_id()); }
1574 this->database->add_field_entry(
1575 "DOF Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
1576 this->database->add_field_entry(
1577 "DOF Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
1578 this->domain->save_global_dof(name, dof, rtable);
1580 if (!nbc.is_null()) {
1581 SetName name = this->case_->get_string(
"NBC_SOL",
"FORC");
1582 if (unconverged_subcycle) {
1583 name.cycle(this->cycle + 1);
1584 name.subcycle(this->subcycle + 1);
1586 name.cycle(this->cycle);
1588 if (name.case_undef()) { name.case_(this->case_->get_id()); }
1589 this->database->add_field_entry(
1590 "NBC Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
1591 this->database->add_field_entry(
1592 "NBC Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
1593 this->domain->save_global_dof(name, nbc, rtable);
1595 if (!residue.is_null()) {
1596 SetName name = this->case_->get_string(
"RESIDUUM_SOL",
"REFO");
1597 if (unconverged_subcycle) {
1598 name.cycle(this->cycle + 1);
1599 name.subcycle(this->subcycle + 1);
1601 name.cycle(this->cycle);
1603 if (name.case_undef()) { name.case_(this->case_->get_id()); }
1604 this->database->add_field_entry(
1605 "Residuum Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
1606 this->database->add_field_entry(
1607 "Residuum Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
1609 this->domain->save_global_dof(name, residue, rtable);
1611 if (this->case_->get_int(
"SAVE_NBC_COMP", 0) == 1) {
1613 name.cycle(this->cycle);
1614 name.case_(this->case_->get_id());
1615 dynamic_cast<typename SolutionIterative<T>::nbc_t&
>(
1616 this->model->get_natural_boundary_condition(
1617 SolutionIterative<T>::nbc_t::type.get_subtype(
1618 "TypedNaturalBoundaryConditionListComponent"
1619 + type_name<T, b2linalg::Msym_compressed_col_update_inv>())))
1620 .save_nonlinear_value(name, dof, time);
1622 if (unconverged_subcycle) {
1624 this->database->sync();
1626 for (GradientSolution::sub_solution_t::iterator s = GradientSolution::sub_solution.begin();
1627 s != GradientSolution::sub_solution.end(); ++s) {
1628 dynamic_cast<b2000::SolutionStaticNonlinear<T>&
>(**s).set_dof(
1629 time, dof, nbc, residue, unconverged_subcycle);
1633 void get_dof(
double& time, b2linalg::Vector<T, b2linalg::Vdense_ref> dof) {
1634 SetName name = this->case_->get_string(
"DOF_SOL",
"DISP");
1635 name.cycle(this->cycle);
1636 if (name.case_undef()) { name.case_(this->case_->get_id()); }
1638 this->domain->load_global_dof(name, dof, &desc);
1639 time = desc.get_double(
"LAMBDA");
1642 void set_equilibrium(
1643 double time,
const b2linalg::Vector<T, b2linalg::Vdense_constref>& residue) {
1645 rtable.set(
"STAGE_ID", this->case_->get_stage_id());
1646 rtable.set(
"STAGE", this->case_->get_stage_number());
1647 rtable.set(
"LAMBDA", time + this->time_at_start_stage);
1648 rtable.set(
"STAGE_LAMBDA", time);
1649 SetName name =
"NR_EQUILIBRIUM";
1650 name.cycle(this->cycle + 1);
1651 name.subcycle(this->subcycle + 1);
1652 name.case_(this->case_->get_id());
1653 this->database->add_field_entry(
1654 "Residue", name.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
1655 this->database->add_field_entry(
1656 "Residue", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
1657 this->domain->save_global_dof(name, residue, rtable);
1658 for (GradientSolution::sub_solution_t::iterator s = GradientSolution::sub_solution.begin();
1659 s != GradientSolution::sub_solution.end(); ++s) {
1660 dynamic_cast<b2000::SolutionStaticNonlinear<T>&
>(**s).set_equilibrium(time, residue);
1664 using type_t = ObjectTypeComplete<SolutionStaticNonlinear, Solution::type_t>;
1668template <
typename T>
1669typename SolutionStaticNonlinear<T>::type_t SolutionStaticNonlinear<T>::type(
1670 "SolutionStaticNonlinear", type_name<T>(),
1671 StringList(
"STATIC_NONLINEAR_SOLUTION",
"NONLINEAR",
"COLLAPSE"), module,
1672 &b2000::Solution::type);
1674template <
typename T>
1675class SolutionDynamicNonlinear :
virtual public SolutionIterative<T>,
1676 public b2000::SolutionDynamicNonlinear<T> {
1678 SolutionDynamicNonlinear() {
1679 last_rate_bc_work = 0;
1683 void terminate_case(
bool success,
const RTable& attributes)
override {
1684 RTable& rtable = this->case_->get_solution_rtable();
1685 rtable.update(attributes);
1686 rtable.set(
"TERMINATION", success ?
"NORMAL" :
"FAILURE");
1687 rtable.set(
"NSTEPS", this->cycle);
1688 rtable.set(
"NSTAGES", this->case_->get_stage_number() + 1);
1691 SetName(this->case_->get_string(
"DOF_SOL", std::string(
"DISP"))).get_gname());
1694 SetName(this->case_->get_string(
"DOF_SOL", std::string(
"DISP")) +
"D").get_gname());
1697 SetName(this->case_->get_string(
"DOF_SOL", std::string(
"DISP")) +
"DD").get_gname());
1700 SetName(this->case_->get_string(
"NBC_SOL", std::string(
"FORC"))).get_gname());
1703 SetName(this->case_->get_string(
"RESIDUUM_SOL", std::string(
"RCFO"))).get_gname());
1704 this->add_gradient_solution_case_information(rtable);
1705 SetName name(
"SOLUTION");
1706 name.case_(this->case_->get_id());
1707 this->database->set(name, rtable);
1708 this->database->sync();
1713 const b2linalg::Matrix<T, b2linalg::Mrectangle_constref>& dof,
const double time,
1714 const b2linalg::Vector<T, b2linalg::Vdense_constref>& nbc,
1715 const b2linalg::Vector<T, b2linalg::Vdense_constref>& residue,
1716 bool unconverged_subcycle =
false)
override {
1718 rtable.set(
"STAGE_ID", this->case_->get_stage_id());
1719 rtable.set(
"STAGE", this->case_->get_stage_number());
1720 rtable.set(
"TIME", time + this->time_at_start_stage);
1721 rtable.set(
"STAGE_TIME", time);
1722 if (!dof.is_null()) {
1723 std::string dname =
"";
1724 for (
size_t i = 0; i != dof.size2(); ++i) {
1725 SetName name = this->case_->get_string(
"DOF_SOL",
"DISP") + dname;
1726 if (unconverged_subcycle) {
1727 name.cycle(this->cycle + 1);
1728 name.subcycle(this->subcycle + 1);
1730 name.cycle(this->cycle);
1732 if (name.case_undef()) { name.case_(this->case_->get_id()); }
1733 this->database->add_field_entry(
1734 "DOF Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
1735 this->database->add_field_entry(
1736 "DOF Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
1738 this->domain->save_global_dof(name, dof[i], rtable);
1742 if (!nbc.is_null()) {
1743 SetName name = this->case_->get_string(
"NBC_SOL",
"FORC");
1744 if (unconverged_subcycle) {
1745 name.cycle(this->cycle + 1);
1746 name.subcycle(this->subcycle + 1);
1748 name.cycle(this->cycle);
1750 if (name.case_undef()) { name.case_(this->case_->get_id()); }
1751 this->database->add_field_entry(
1752 "NBC Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
1753 this->database->add_field_entry(
1754 "NBC Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
1755 this->domain->save_global_dof(name, nbc, rtable);
1757 if (!residue.is_null()) {
1758 SetName name = this->case_->get_string(
"RESIDUUM_SOL",
"REFO");
1759 if (unconverged_subcycle) {
1760 name.cycle(this->cycle + 1);
1761 name.subcycle(this->subcycle + 1);
1763 name.cycle(this->cycle);
1765 if (name.case_undef()) { name.case_(this->case_->get_id()); }
1766 this->database->add_field_entry(
1767 "Residuum Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
1768 this->database->add_field_entry(
1769 "Residuum Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
1771 this->domain->save_global_dof(name, residue, rtable);
1773 if (this->case_->get_int(
"SAVE_NBC_COMP", 0) == 1) {
1775 if (unconverged_subcycle) {
1776 name.cycle(this->cycle + 1);
1777 name.subcycle(this->subcycle + 1);
1779 name.cycle(this->cycle);
1781 name.case_(this->case_->get_id());
1782 dynamic_cast<typename SolutionIterative<T>::nbc_t&
>(
1783 this->model->get_natural_boundary_condition(
1784 SolutionIterative<T>::nbc_t::type.get_subtype(
1785 "TypedNaturalBoundaryConditionListComponent"
1786 + type_name<T, b2linalg::Msym_compressed_col_update_inv>())))
1787 .save_nonlinear_value(name, dof[0], time);
1789 if (unconverged_subcycle) {
1791 this->database->sync();
1792 }
else if (!dof.is_null()) {
1795 if (!nbc.is_null()) { tmp += nbc * dof[1]; }
1796 if (!residue.is_null()) { tmp += residue * dof[1]; }
1798 (last_rate_bc_work + tmp) *
static_cast<T
>((time - this->current_time) / 2);
1799 last_rate_bc_work = tmp;
1800 RTable& rtable = this->get_cycle_rtable();
1801 rtable.set(
"RATE_BC_WORK", last_rate_bc_work);
1802 rtable.set(
"BC_WORK", last_bc_work);
1806 using type_t = ObjectTypeComplete<SolutionDynamicNonlinear, Solution::type_t>;
1810 T last_rate_bc_work;
1814template <
typename T>
1815typename SolutionDynamicNonlinear<T>::type_t SolutionDynamicNonlinear<T>::type(
1816 "SolutionDynamicNonlinear", type_name<T>(),
1818 "DYNAMIC_NONLINEAR_SOLUTION",
"DYNAMIC_NONLINEAR",
"TRANSIENT_NONLINEAR",
1820 module, &b2000::Solution::type);
1822class SolutionModelReduction
1823 :
public b2000::b2dbv3::GradientSolution,
1824 public b2000::SolutionModelReduction<double, b2linalg::Mpacked>
1830 void get_interface_dof(b2linalg::Index& interface_dof)
override {
1832 name.case_(case_->get_string(
"SET_INTERFACE_ID",
"interface"));
1834 name.gname(
"FACESET");
1836 std::set<size_t> interface_dof_set;
1837 for (b2dbv3::Domain::list_branch_t::const_iterator i = domain->list_branch.begin();
1838 i != domain->list_branch.end(); ++i) {
1840 if (database->has_key(name)) {
1841 b2linalg::Matrix<int, b2linalg::Mrectangle> faceset(2, 0);
1842 database->get(name, faceset);
1843 b2linalg::Vector<double, b2linalg::Vdense> internal_coor(2);
1844 for (
size_t j = 0; j != faceset.size2(); ++j) {
1845 b2linalg::Index dof_numbering;
1846 b2linalg::Matrix<double, b2linalg::Mrectangle> d_value_d_dof;
1847 if (
auto tve =
dynamic_cast<TypedElement<double>*
>(
1848 i->list_all_elements[faceset(0, j) - 1]);
1850 tve->face_field_value(
1851 faceset(1, j),
"?", internal_coor,
1852 b2linalg::Matrix<double, b2linalg::Mrectangle_constref>::null, 0,
1853 b2linalg::Vector<double, b2linalg::Vdense>::null,
1854 b2linalg::Matrix<double, b2linalg::Mrectangle>::null,
1855 dof_numbering, d_value_d_dof, b2linalg::Index::null);
1857 interface_dof_set.insert(dof_numbering.begin(), dof_numbering.end());
1862 if (!interface_dof_set.empty()) {
1863 interface_dof.assign(interface_dof_set.begin(), interface_dof_set.end());
1868 name.gname(
"NODESET");
1869 domain->load_node_set(name, nodes_set);
1870 if (!nodes_set.empty()) {
1872 for (
size_t n = 0; n != nodes_set.size(); ++n) {
1873 s += nodes_set[n]->get_number_of_dof();
1875 interface_dof.assign(s, 0);
1876 size_t* i = &interface_dof[0];
1877 for (
size_t n = 0; n != nodes_set.size(); ++n) {
1878 i = nodes_set[n]->get_global_dof_numbering(i);
1883 DBError() <<
"The database don't have NODESET of FACESET interface set" <<
THROW;
1887 const size_t nb_interface_dof,
1888 const b2linalg::Matrix<double, b2linalg::Mrectangle>& basis,
1889 std::vector<b2linalg::Matrix<double, b2linalg::Mpacked>>& reduced_matrix)
override {
1890 database->add_field_entry(
1891 "ReducedBasis",
"REDUCED_BASIS",
"NODE",
"BRANCH",
false,
false,
false);
1892 database->add_field_entry(
1893 "ReducedBasis",
"REDUCED_BASIS_E",
"CELL",
"BRANCH",
false,
false,
false);
1894 SetName name(
"REDUCED_BASIS");
1895 name.case_(case_->get_id());
1899 if (!nodes_set.empty()) {
1901 for (
size_t n = 0; n != nodes_set.size(); ++n) {
1902 std::pair<size_t, size_t> ibni =
1903 domain->get_internal_branch_and_node_id(*nodes_set[n]);
1904 desc_i.set(
"NI_BRANCH",
int(ibni.first) + 1);
1905 desc_i.set(
"NI_NODE",
int(ibni.second) + 1);
1906 const int nd = nodes_set[n]->get_number_of_dof();
1907 for (
int i = 0; i != nd; ++i, ++j) {
1908 desc_i.set(
"NI_DOF", i + 1);
1910 domain->save_global_dof(name, basis[j], desc_i);
1914 for (; j != basis.size2(); ++j) {
1916 domain->save_global_dof(name, basis[j], desc);
1919 name.gname(
"REDUCED_SYSTEM");
1920 for (
size_t i = 0; i != reduced_matrix.size(); ++i) {
1921 if (reduced_matrix[i].size1() != 0) {
1923 database->set(name, reduced_matrix[i]);
1926 current_case_nb_interface_dof = nb_interface_dof;
1927 current_case_nb_internal_dof = basis.size2() - nb_interface_dof;
1930 void terminate_case(
bool success,
const RTable& attributes)
override {
1931 terminate_gradient();
1932 RTable& rtable = case_->get_solution_rtable();
1933 store_value_in_rtable_and_clear(rtable);
1934 rtable.update(attributes);
1935 rtable.set(
"TERMINATION", success ?
"NORMAL" :
"FAILURE");
1936 rtable.set(
"NB_INTERFACE_DOF",
int(current_case_nb_interface_dof));
1937 rtable.set(
"NB_INTERNAL_DOF",
int(current_case_nb_internal_dof));
1938 SetName name(
"SOLUTION");
1939 name.case_(case_->get_id());
1940 database->set(name, rtable);
1944 using type_t = ObjectTypeComplete<SolutionModelReduction, Solution::type_t>;
1948 std::vector<Node*> nodes_set;
1949 size_t current_case_nb_interface_dof;
1950 size_t current_case_nb_internal_dof;
1953class SolutionBeamCrossSection :
public b2000::SolutionBeamCrossSection,
1954 public b2000::b2dbv3::GradientSolution {
1956 void terminate_case(
bool success,
const RTable& attributes)
override {
1957 terminate_gradient();
1958 RTable& rtable = case_->get_solution_rtable();
1959 store_value_in_rtable_and_clear(rtable);
1960 rtable.update(attributes);
1961 rtable.set(
"TERMINATION", success ?
"NORMAL" :
"FAILURE");
1962 SetName name(
"SOLUTION");
1963 name.case_(case_->get_id());
1964 database->set(name, rtable);
1969 SetName& name,
const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>& m) {
1970 database->add_field_entry(
1971 "DOF Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
1974 desc.set(
"SYSTEM",
"BRANCH");
1975 desc.set(
"TYPE",
"NODE");
1978 for (
size_t branch = 0; branch != domain->list_branch.size(); ++branch) {
1979 name.branch(domain->list_branch[branch].id);
1980 if (domain->list_branch[branch].max_number_of_dof_by_node == 0) {
continue; }
1983 m(b2linalg::Interval(pos, pos + domain->list_branch[branch].list_nodes.size())));
1984 pos += domain->list_branch[branch].list_nodes.size();
1985 database->set_desc(name, desc);
1990 const double neutral_point[2],
const double inertia_mass,
const double inertia_point[2],
1991 const double inertia_moment[3],
1992 const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>& dof,
1993 const b2linalg::Matrix<double> strain[7],
const b2linalg::Matrix<double> stress[7],
1994 const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>& constitutive_matrix,
1995 const b2linalg::Vector<double, b2linalg::Vdense_constref>& constant_load)
override {
1996 SetName name(
"BCS_CONSTITUTIVE_MATRIX");
1997 if (name.case_undef()) { name.case_(case_->get_id()); }
1998 database->set(name, constitutive_matrix);
2001 std::vector<double> tmp(neutral_point, neutral_point + 2);
2002 rt.set(
"NEUTRAL_AXIS", tmp);
2003 rt.set(
"MASS", inertia_mass);
2004 tmp.assign(inertia_point, inertia_point + 2);
2005 rt.set(
"MASS_CENTER", tmp);
2006 tmp.assign(inertia_moment, inertia_moment + 3);
2007 rt.set(
"MASS_INERTIA_MOMENTS", tmp);
2009 std::vector<double> tmp(&constant_load[0], &constant_load[6]);
2010 rt.set(
"CONSTANT_FORCE_AND_MOMENT", tmp);
2012 database->set_desc(name, rt);
2014 for (
size_t i = 0; i != 7; ++i) {
2015 name.gname(case_->get_string(
"DOF_SOL",
"DISP"));
2016 name.subcase(i + 1);
2017 database->add_field_entry(
2018 "DOF Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
2019 domain->save_global_dof(name, dof[i]);
2021 name.gname(
"STRAIN");
2022 save_field(name, strain[i]);
2023 name.gname(
"STRESS");
2024 save_field(name, stress[i]);
2028 using type_t = ObjectTypeComplete<SolutionBeamCrossSection, Solution::type_t>;
2032class SolutionTaylorExpansionsBuckling :
public b2000::b2dbv3::GradientSolution,
2033 public b2000::SolutionTaylorExpansionsBuckling<double> {
2035 SolutionTaylorExpansionsBuckling() : nbmodes(0) {}
2037 void which_modes(
int& number_of_mode,
char which[3],
double& sigma)
const override {
2038 sigma = case_->get_double(
"SHIFT", 0);
2039 number_of_mode = case_->get_int(
"NMODES", 1);
2040 std::string whichs = case_->get_string(
"WHICH_EIGENVALUES",
"RA");
2041 strcpy(which, whichs.c_str());
2044 void terminate_case(
bool success,
const RTable& attributes)
override {
2045 RTable& rtable = case_->get_solution_rtable();
2046 store_value_in_rtable_and_clear(rtable);
2047 rtable.update(attributes);
2048 rtable.set(
"NMODE", nbmodes);
2050 "DOF_SOL", SetName(case_->get_string(
"DOF_SOL", std::string(
"DISP"))).get_gname());
2052 "NBC_SOL", SetName(case_->get_string(
"NBC_SOL", std::string(
"FORC"))).get_gname());
2055 SetName(case_->get_string(
"RESIDUUM_SOL", std::string(
"RCFO"))).get_gname());
2056 add_gradient_solution_case_information(rtable);
2057 SetName name(
"SOLUTION");
2058 name.case_(case_->get_id());
2059 database->set(name, rtable);
2065 const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>& path,
2066 const b2linalg::Vector<double, b2linalg::Vdense_constref>& time)
override {
2068 SetName name = case_->get_string(
"PDOF_SOL",
"PDISP");
2069 if (name.case_undef()) { name.case_(case_->get_id()); }
2070 database->add_field_entry(
2071 "DOF Path Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
2072 database->add_field_entry(
2073 "DOF Path Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
2074 for (
size_t j = 0; j != path.size2(); ++j) {
2075 rtable.set(
"LAMBDA", time[j]);
2076 name.subcase(j + 1);
2077 domain->save_global_dof(name, path[j], rtable);
2083 const int mode,
const double cc,
const double cci,
2084 const b2linalg::Vector<double, b2linalg::Vdense_constref>& dof,
const double time,
2085 const b2linalg::Vector<double, b2linalg::Vdense_constref>& nbc,
2086 const b2linalg::Vector<double, b2linalg::Vdense_constref>& residue,
2087 const b2linalg::Vector<double, b2linalg::Vdense_constref>& eigenvector)
override {
2090 rtable.set(
"SOLUTION_PATH_COORDINATE", cc);
2091 rtable.set(
"SOLUTION_PATH_COORDINATE_i", cci);
2092 rtable.set(
"LAMBDA", time);
2093 if (!dof.is_null()) {
2094 SetName name = case_->get_string(
"DOF_SOL",
"DISP");
2095 name.subcase(mode + 1);
2096 if (name.case_undef()) { name.case_(case_->get_id()); }
2097 database->add_field_entry(
2098 "DOF Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
2099 database->add_field_entry(
2100 "DOF Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
2101 domain->save_global_dof(name, dof, rtable);
2103 if (!nbc.is_null()) {
2104 SetName name = case_->get_string(
"NBC_SOL",
"FORC");
2105 name.subcase(mode + 1);
2106 if (name.case_undef()) { name.case_(case_->get_id()); }
2107 database->add_field_entry(
2108 "NBC Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
2109 database->add_field_entry(
2110 "NBC Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
2111 domain->save_global_dof(name, nbc, rtable);
2113 if (!residue.is_null()) {
2114 SetName name = case_->get_string(
"RESIDUUM_SOL",
"REFO");
2115 name.subcase(mode + 1);
2116 if (name.case_undef()) { name.case_(case_->get_id()); }
2117 database->add_field_entry(
2118 "Residuum Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
2119 database->add_field_entry(
2120 "Residuum Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
2122 domain->save_global_dof(name, residue, rtable);
2125 SetName name = case_->get_string(
"BMODE",
"BMODE");
2126 name.subcase(mode + 1);
2127 if (name.case_undef()) { name.case_(case_->get_id()); }
2128 database->add_field_entry(
2129 "Buckling Mode", name.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
2130 database->add_field_entry(
2131 "Buckling Mode", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
2132 domain->save_global_dof(name, eigenvector, rtable);
2136 using type_t = ObjectTypeComplete<SolutionTaylorExpansionsBuckling, Solution::type_t>;
2144template <
typename T>
2145class SolutionMonolithic :
virtual public SolutionIterative<T>,
2146 public b2000::SolutionMonolithic<T> {
2154 void set_dof(
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof)
override {
2155 SetName sol = this->case_->get_string(
"DOF_SOL", std::string(
"DISP"));
2156 if (sol.case_undef()) { sol.case_(this->case_->get_id()); }
2157 if (this->subcase_id != 0) { sol.subcase(this->subcase_id); }
2158 this->database->add_field_entry(
2159 "DOF Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
2160 this->database->add_field_entry(
2161 "DOF Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
false);
2162 this->domain->save_global_dof(sol, dof);
2174 void set_natural_boundary_condition(
2175 const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof)
override {
2176 SetName sol = this->case_->get_string(
"NBC_SOL",
"FORC");
2177 if (sol.case_undef()) { sol.case_(this->case_->get_id()); }
2178 if (this->subcase_id != 0) { sol.subcase(this->subcase_id); }
2179 this->database->add_field_entry(
2180 "NBC Solution", sol.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
2181 this->database->add_field_entry(
2182 "NBC Solution", sol.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
2183 this->domain->save_global_dof(sol, dof);
2186 bool compute_constraint_value()
const override {
2187 return (this->case_->get_bool(
"COMPUTE_RCFO",
false));
2228 void terminate_case(
bool success,
const RTable& attributes)
override {
2229 RTable& rtable = this->case_->get_solution_rtable();
2230 rtable.update(attributes);
2231 rtable.set(
"TERMINATION", success ?
"NORMAL" :
"FAILURE");
2232 rtable.set(
"NSTEPS", this->cycle);
2233 rtable.set(
"NSTAGES", this->case_->get_stage_number() + 1);
2236 SetName(this->case_->get_string(
"DOF_SOL", std::string(
"DISP"))).get_gname());
2239 SetName(this->case_->get_string(
"DOF_SOL", std::string(
"DISP")) +
"D").get_gname());
2242 SetName(this->case_->get_string(
"DOF_SOL", std::string(
"DISP")) +
"DD").get_gname());
2245 SetName(this->case_->get_string(
"NBC_SOL", std::string(
"FORC"))).get_gname());
2248 SetName(this->case_->get_string(
"RESIDUUM_SOL", std::string(
"RCFO"))).get_gname());
2249 this->add_gradient_solution_case_information(rtable);
2250 SetName name(
"SOLUTION");
2251 name.case_(this->case_->get_id());
2252 this->database->set(name, rtable);
2253 this->database->sync();
2258 const b2linalg::Matrix<T, b2linalg::Mrectangle_constref>& dof,
const double time,
2259 const b2linalg::Vector<T, b2linalg::Vdense_constref>& nbc,
2260 const b2linalg::Vector<T, b2linalg::Vdense_constref>& residue,
2261 bool unconverged_subcycle =
false)
override {
2263 rtable.set(
"STAGE_ID", this->case_->get_stage_id());
2264 rtable.set(
"STAGE", this->case_->get_stage_number());
2265 rtable.set(
"TIME", time + this->time_at_start_stage);
2266 rtable.set(
"STAGE_TIME", time);
2267 if (!dof.is_null()) {
2268 std::string dname =
"";
2269 for (
size_t i = 0; i != dof.size2(); ++i) {
2270 SetName name = this->case_->get_string(
"DOF_SOL",
"DISP") + dname;
2271 if (unconverged_subcycle) {
2272 name.cycle(this->cycle + 1);
2273 name.subcycle(this->subcycle + 1);
2275 name.cycle(this->cycle);
2277 if (name.case_undef()) { name.case_(this->case_->get_id()); }
2278 this->database->add_field_entry(
2279 "DOF Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
false,
false);
2280 this->database->add_field_entry(
2281 "DOF Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
false,
2283 this->domain->save_global_dof(name, dof[i], rtable);
2287 if (!nbc.is_null()) {
2288 SetName name = this->case_->get_string(
"NBC_SOL",
"FORC");
2289 if (unconverged_subcycle) {
2290 name.cycle(this->cycle + 1);
2291 name.subcycle(this->subcycle + 1);
2293 name.cycle(this->cycle);
2295 if (name.case_undef()) { name.case_(this->case_->get_id()); }
2296 this->database->add_field_entry(
2297 "NBC Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
2298 this->database->add_field_entry(
2299 "NBC Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
true);
2300 this->domain->save_global_dof(name, nbc, rtable);
2302 if (!residue.is_null()) {
2303 SetName name = this->case_->get_string(
"RESIDUUM_SOL",
"REFO");
2304 if (unconverged_subcycle) {
2305 name.cycle(this->cycle + 1);
2306 name.subcycle(this->subcycle + 1);
2308 name.cycle(this->cycle);
2310 if (name.case_undef()) { name.case_(this->case_->get_id()); }
2311 this->database->add_field_entry(
2312 "Residuum Solution", name.get_gname(),
"NODE",
"BRANCH",
false,
true,
true);
2313 this->database->add_field_entry(
2314 "Residuum Solution", name.get_gname() +
"_E",
"CELL",
"BRANCH",
false,
true,
2316 this->domain->save_global_dof(name, residue, rtable);
2318 if (this->case_->get_int(
"SAVE_NBC_COMP", 0) == 1) {
2320 if (unconverged_subcycle) {
2321 name.cycle(this->cycle + 1);
2322 name.subcycle(this->subcycle + 1);
2324 name.cycle(this->cycle);
2326 name.case_(this->case_->get_id());
2327 dynamic_cast<typename SolutionIterative<T>::nbc_t&
>(
2328 this->model->get_natural_boundary_condition(
2329 SolutionIterative<T>::nbc_t::type.get_subtype(
2330 "TypedNaturalBoundaryConditionListComponent"
2331 + type_name<T, b2linalg::Msym_compressed_col_update_inv>())))
2332 .save_nonlinear_value(name, dof[0], time);
2334 if (unconverged_subcycle) {
2336 this->database->sync();
2337 }
else if (!dof.is_null()) {
2340 if (!nbc.is_null()) { tmp += nbc * dof[1]; }
2341 if (!residue.is_null()) { tmp += residue * dof[1]; }
2343 (last_rate_bc_work + tmp) *
static_cast<T
>((time - this->current_time) / 2);
2344 last_rate_bc_work = tmp;
2345 RTable& rtable = this->get_cycle_rtable();
2346 rtable.set(
"RATE_BC_WORK", last_rate_bc_work);
2347 rtable.set(
"BC_WORK", last_bc_work);
2351 using type_t = ObjectTypeComplete<SolutionMonolithic, Solution::type_t>;
2355 T last_rate_bc_work{};
2359template <
typename T>
2360typename SolutionMonolithic<T>::type_t SolutionMonolithic<T>::type(
2361 "SolutionMonolithic", type_name<T>(),
2363 "MLINEAR",
"MSTATIC_LINEAR_SOLUTION",
"MDYNAMIC_LINEAR",
"MTRANSIENT_LINEAR",
2364 "MNONLINEAR",
"MSTATIC_NONLINEAR_SOLUTION",
"MDYNAMIC_NONLINEAR",
2365 "MTRANSIENT_NONLINEAR"),
2366 module, &b2000::Solution::type);
csda< T > sqrt(const csda< T > &a)
Square root of a csda number.
Definition b2csda.H:396
bool operator<(const csda< T1 > &a, const csda< T2 > &b)
Comparison of two csda numbers is performed on the real part only.
Definition b2csda.H:262
#define THROW
Definition b2exception.H:198
virtual std::string get_id() const =0
virtual std::string get_string(const std::string &key) const =0
virtual int get_int(const std::string &key) const =0
virtual bool has_key(const std::string &key) const =0
Definition b2solution.H:54
virtual Domain & get_domain()=0
Definition b2solution.H:227
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829
GenericException< TypeError_name > TypeError
Definition b2exception.H:325
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314
GenericException< DBError_name > DBError
Definition b2exception.H:340
Definition b2solution.H:71
Definition b2solution.H:110