21#ifndef B2DOMAIN_DATABASE_H_
22#define B2DOMAIN_DATABASE_H_
31#include "b2branch_property.H"
32#include "b2component.H"
33#include "b2domain_property.H"
34#include "b2fortran_element_property.H"
35#include "b2material_property.H"
36#include "b2ppconfig.h"
37#include "ip/b2ip_transformations.H"
39#include "model/b2element.H"
43#include "utils/b2threading.H"
50namespace b2000::b2dbv3 {
64 enum struct element_type_t {
79 for (
auto& i : list_branch) { i.property.set_subcase_id(subcase_id_); }
83 for (
auto& i : list_branch) {
84 if (i.property.have_temperature()) {
return true; }
93 for (list_branch_t::const_iterator i = list_branch.begin(); i != list_branch.end(); ++i) {
94 nb += i->get_number_of_elements();
101 for (list_branch_t::const_iterator i = list_branch.begin(); i != list_branch.end(); ++i) {
102 nb += i->get_number_of_elements_and_subelements();
109 for (list_branch_t::const_iterator i = list_branch.begin(); i != list_branch.end(); ++i) {
110 nb += i->get_number_of_nodes();
115 const std::vector<Element::VariableInfo>
get_value_info()
const override {
return value_info; }
118 struct CompFortranElementProperty {
125 struct ParentNodeMapping {
126 size_t parent_internal_branch;
127 size_t parent_internal_element;
128 double global_icoor[3];
131 struct ParentElementMapping {
132 size_t parent_internal_branch;
133 size_t parent_internal_element;
134 b2linalg::Matrix<double> global_icoor;
137 using list_nodes_t = std::vector<Node*>;
138 using list_elements_t = std::vector<Element*>;
139 using ElementProperties = std::set<FortranElementProperty*, CompFortranElementProperty>;
144 class ElementIterator {
146 ElementIterator(Branch& branch)
147 : estart(branch.list_all_elements.begin()), eend(branch.list_all_elements.end()) {}
155 Element* e = current();
161 if (in_sub) {
return *sstart; }
162 if (estart != eend) {
return *estart; }
168 std::pair<size_t, Element**> s = (*estart)->get_subelements();
171 send = s.second + s.first;
174 }
else if (++sstart == send) {
179 sstart = send =
nullptr;
183 Branch::list_elements_t::iterator estart;
184 Branch::list_elements_t::iterator eend;
193 Branch(DomainProperty* dp) : property(*dp) {}
195 size_t get_number_of_elements()
const {
return list_all_elements.size(); }
197 size_t get_number_of_elements_and_subelements()
const {
199 for (
size_t i = 0; i != list_all_elements.size(); ++i) {
200 nb += 1 + list_all_elements[i]->get_subelements().first;
205 size_t get_number_of_nodes()
const {
return list_nodes.size(); }
207 list_elements_t list_all_elements;
209 list_nodes_t list_nodes;
210 size_t nb_node_dof{};
211 size_t nb_element_dof{};
214 Transformation3D<double> btog_transformation;
215 Transformation3D<b2000::csda<double>> btog_transformation_cs;
217 std::vector<Transformation3D<double>> ltob;
218 std::vector<Transformation3D<b2000::csda<double>>> ltob_cs;
219 std::vector<ParentNodeMapping> parent_node_mapping;
220 std::vector<ParentElementMapping> parent_element_mapping;
222 BranchProperty property;
224 ElementProperties element_properties;
226 int min_number_of_dof_by_element{std::numeric_limits<int>::max()};
227 int max_number_of_dof_by_element{};
228 int min_number_of_dof_by_node{std::numeric_limits<int>::max()};
229 int max_number_of_dof_by_node{};
232 std::vector<size_t> first_element_internal_id_of_branch;
233 std::vector<size_t> first_node_internal_id_of_branch;
235 using list_branch_t = std::vector<Branch>;
236 list_branch_t list_branch;
238 using branch_eid_to_branch_iid_t = std::map<size_t, size_t>;
239 branch_eid_to_branch_iid_t branch_eid_to_branch_iid;
241 using Materials = std::map<int, std::pair<MaterialProperty*, FortranElementProperty::type_t*>>;
243 Materials properties;
245 MaterialProperty* get_material_property_from_mid(
size_t mid) {
246 Materials::iterator i = materials.find(mid);
247 if (i == materials.end()) {
return nullptr; }
248 return i->second.first;
251 MaterialProperty* get_material_property_from_pid(
size_t pid) {
252 Materials::iterator i = properties.find(pid);
253 if (i == properties.end()) {
return nullptr; }
254 return i->second.first;
257 b2linalg::Matrix<double, b2linalg::Mcompressed_col> ltob_transformation;
258 b2linalg::Matrix<b2000::csda<double>, b2linalg::Mcompressed_col> ltob_transformation_cs;
259 b2linalg::Matrix<std::complex<double>, b2linalg::Mcompressed_col> ltob_transformation_c;
261 std::vector<const double*> nodes_local_referential;
262 std::vector<const b2000::csda<double>*> nodes_local_referential_cs;
264 ip::Transformations transformations;
266 Branch& get_branch_from_eid(
size_t eid) {
267 branch_eid_to_branch_iid_t::iterator i = branch_eid_to_branch_iid.find(eid);
268 if (i == branch_eid_to_branch_iid.end()) {
269 KeyError() <<
"Internal branch " << eid <<
" not found." <<
THROW;
271 return list_branch[i->second];
274 Branch& get_branch_from_eid(
const std::string& eid) {
275 std::istringstream s(eid);
278 return get_branch_from_eid(seid);
283 Node* next()
override {
284 while (bstart != bend) {
285 if (start != end) {
return *start++; }
287 if (bstart != bend) {
288 start = bstart->list_nodes.begin();
289 end = bstart->list_nodes.end();
296 NodeIterator(Domain& domain)
297 : bstart(domain.list_branch.begin()), bend(domain.list_branch.end()) {
298 while (bstart != bend && bstart->list_nodes.empty()) { ++bstart; }
299 if (bstart != bend) {
300 start = bstart->list_nodes.begin();
301 end = bstart->list_nodes.end();
304 friend class b2dbv3::Domain;
305 list_branch_t::iterator bstart;
306 list_branch_t::const_iterator bend;
307 Branch::list_nodes_t::iterator start;
308 Branch::list_nodes_t::const_iterator end;
324 Element* e = current();
329 ElementIterator(Domain& domain)
330 : bstart(domain.list_branch.begin()), bend(domain.list_branch.end()) {
331 assert(bstart != bend);
332 estart = bstart->list_all_elements.begin();
333 eend = bstart->list_all_elements.end();
335 sstart = send =
nullptr;
339 if (in_sub) {
return *sstart; }
340 if (estart != eend) {
return *estart; }
345 if (estart != eend) {
347 std::pair<size_t, Element**> s = (*estart)->get_subelements();
350 send = s.second + s.first;
353 }
else if (++sstart == send) {
358 if (++estart == eend) {
359 if (++bstart != bend) {
360 estart = bstart->list_all_elements.begin();
361 eend = bstart->list_all_elements.end();
364 sstart = send =
nullptr;
368 friend class b2dbv3::Domain;
370 list_branch_t::iterator bstart;
371 list_branch_t::const_iterator bend;
372 Branch::list_elements_t::iterator estart;
373 Branch::list_elements_t::iterator eend;
380 return element_iterator(
new ElementIterator(*
this));
385 for (std::vector<Branch>::iterator branch = list_branch.begin();
386 branch != list_branch.end(); ++branch) {
387 for (
size_t i = 0; i != branch->list_all_elements.size(); ++i) {
388 Element* e = branch->list_all_elements[i];
394 for (Node* n = i->next(); n !=
nullptr; n = i->next()) { n->decref_or_free(); }
397 MaterialIterator* i = get_material_iterator();
399 while ((m = i->next()) !=
nullptr) { m->decref_or_free(); }
403 MaterialIterator* i = get_property_iterator();
405 while ((m = i->next()) !=
nullptr) { m->decref_or_free(); }
410 template <
typename T>
411 void save_global_dof(
412 SetName name,
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof,
413 RTable desc = RTable());
415 template <
typename T>
416 void save_global_dof_indexed(
417 SetName name,
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof,
418 RTable desc = RTable());
421 const std::string& name,
422 const b2linalg::Vector<double, b2linalg::Vdense_constref>& dof)
override {
424 desc.
set(
"TYPE",
"NODE");
425 desc.
set(
"SYSTEM",
"BRANCH");
426 save_global_dof(name, dof, desc);
430 const std::string& name,
431 const b2linalg::Vector<b2000::csda<double>, b2linalg::Vdense_constref>& dof)
override {
433 desc.
set(
"TYPE",
"NODE");
434 desc.
set(
"SYSTEM",
"BRANCH");
435 save_global_dof(name, dof, desc);
439 const std::string& name,
440 const b2linalg::Vector<std::complex<double>, b2linalg::Vdense_constref>& dof)
override {
442 desc.
set(
"TYPE",
"NODE");
443 desc.
set(
"SYSTEM",
"BRANCH");
444 save_global_dof(name, dof, desc);
447 template <
typename T>
448 void load_global_dof(
449 SetName name, b2linalg::Vector<T, b2linalg::Vdense_ref> dof,
RTable* desc =
nullptr);
451 void load_node_set(
SetName name, std::vector<Node*>& nodes_set) {
453 for (
size_t branch = 0; branch != list_branch.size(); ++branch) {
454 name.branch(list_branch[branch].
id);
455 if (database->
has_key(name)) { s += database->
dims(name)[0]; }
458 nodes_set.reserve(s);
459 for (
size_t branch = 0; branch != list_branch.size(); ++branch) {
460 name.branch(list_branch[branch].
id);
462 std::vector<mcInt32> list_node;
463 database->
get(name, list_node);
464 for (
size_t n = 0; n != list_node.size(); ++n) {
465 const size_t nn = list_node[n];
466 if (nn < 1 || nn > list_branch[branch].list_nodes.size()) {
467 DBError() <<
"invalid internal node id " << nn <<
" in the set " << name
470 nodes_set.push_back(list_branch[branch].list_nodes[nn - 1]);
476 template <
typename T>
477 void load_nodal_values(SetName name_, b2linalg::Matrix<T>& value) {
480 size_t internal_node_id = 0;
481 for (
size_t branch = 0; branch != list_branch.size(); ++branch) {
482 const size_t internal_node_id_end =
483 internal_node_id + list_branch[branch].get_number_of_nodes();
484 name.branch(list_branch[branch].
id);
487 if (value.size1() == 0) {
488 const std::vector<size_t> dims = database->
dims(name);
490 if (dims.size() == 1) {
501 name, value(b2linalg::Interval(0, value.size1()),
502 b2linalg::Interval(internal_node_id, internal_node_id_end)));
503 }
else if (value.size1() != 0) {
504 value(b2linalg::Interval(0, value.size1()),
505 b2linalg::Interval(internal_node_id, internal_node_id_end))
509 internal_node_id = internal_node_id_end;
513 const b2linalg::Matrix<double, b2linalg::Mrectangle>& get_nodal_values_double(SetName name) {
514 b2linalg::Matrix<double, b2linalg::Mrectangle>& res = list_nodal_values[name];
515 if (res.size2() == 0) { load_nodal_values(name, res); }
519 const b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle>& get_nodal_values_csda(
521 b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle>& res =
522 list_nodal_values_cs[name];
523 if (res.size2() == 0) { load_nodal_values(name, res); }
527 template <
typename T>
528 const b2linalg::Matrix<T, b2linalg::Mrectangle>& get_nodal_values(SetName name);
531 if (state_buffers_size.first == 0 && state_buffers_size.second == 0) {
return; }
533 std::vector<int> vi(state_buffers_size.first);
534 std::vector<double> vd(state_buffers_size.second);
535 std::pair<int*, double*> bufptr(&vi[0], &vd[0]);
536 for (list_branch_t::iterator b = list_branch.begin(); b != list_branch.end(); ++b) {
537 for (Branch::list_elements_t::iterator e = b->list_all_elements.begin();
538 e != b->list_all_elements.end(); ++e) {
539 bufptr = (*e)->get_state_buffer(bufptr);
542 if (!vi.empty()) { database->
set(state_id +
".I", vi); }
543 if (!vd.empty()) { database->
set(state_id +
".F", vd); }
548 if (state_buffers_size.first == 0 && state_buffers_size.second == 0) {
return; }
550 std::vector<int> vi(state_buffers_size.first);
551 std::vector<double> vd(state_buffers_size.second);
552 if (!vi.empty()) { database->
get(state_id +
".I", vi); }
553 if (!vd.empty()) { database->
get(state_id +
".F", vd); }
554 std::pair<const int*, const double*> bufptr(&vi[0], &vd[0]);
555 for (list_branch_t::iterator b = list_branch.begin(); b != list_branch.end(); ++b) {
556 for (Branch::list_elements_t::iterator e = b->list_all_elements.begin();
557 e != b->list_all_elements.end(); ++e) {
558 bufptr = (*e)->set_state_buffer(bufptr);
565 return connectivity_type;
568 element_type_t get_element_base_type_code()
const {
569 switch (
static_cast<element_type_t
>(element_base_type_code)) {
570 case element_type_t::real_symmetric:
571 return element_type_t::real_symmetric;
572 case element_type_t::real_unsymmetric:
573 return element_type_t::real_unsymmetric;
574 case element_type_t::csda_symmetric:
575 return element_type_t::csda_symmetric;
576 case element_type_t::csda_unsymmetric:
577 return element_type_t::csda_unsymmetric;
578 case element_type_t::complex_symmetric:
579 return element_type_t::complex_symmetric;
580 case element_type_t::complex_unsymmetric:
581 return element_type_t::complex_unsymmetric;
583 return element_type_t::unknown;
587 bool is_unsymmetric()
const {
588 if (element_base_type_code ==
static_cast<int>(element_type_t::unknown)) {
589 Exception() <<
THROW;
591 return element_base_type_code &
static_cast<int>(element_type_t::real_unsymmetric);
594 bool is_csda()
const {
595 if (element_base_type_code ==
static_cast<int>(element_type_t::unknown)) {
596 Exception() <<
THROW;
598 return element_base_type_code &
static_cast<int>(element_type_t::csda_symmetric);
601 bool is_complex()
const {
602 if (element_base_type_code ==
static_cast<int>(element_type_t::unknown)) {
603 Exception() <<
THROW;
605 return element_base_type_code &
static_cast<int>(element_type_t::complex_symmetric);
609 ObjectNameToNodeMap::iterator i = object_name_to_node_map.find(node_name);
610 if (i == object_name_to_node_map.end()) {
return nullptr; }
615 ObjectNameToElementMap::iterator i = object_name_to_element_map.find(element_name);
616 if (i == object_name_to_element_map.end()) {
return nullptr; }
621 std::pair<int, const Node* const*> node_list,
622 std::vector<AdjacentElement>& adjacent_elements)
override {
623 init_node_connectivity();
625 std::map<Element*, std::vector<int>> tmp;
626 for (
const Node*
const* n = node_list.second; n != node_list.second + node_list.first;
628 size_t nid = (*n)->get_id();
629 std::vector<std::pair<Element*, int>>::const_iterator begin =
630 node_element_connectivity.begin() + node_element_connectivity_index[nid];
631 std::vector<std::pair<Element*, int>>::const_iterator end =
632 node_element_connectivity.begin() + node_element_connectivity_index[nid + 1];
633 for (; begin != end; ++begin) { tmp[begin->first].push_back(begin->second); }
635 size_t nb_adjacent_elements = 0;
636 for (std::map<
Element*, std::vector<int>>::iterator i = tmp.
begin(); i != tmp.end(); ++i) {
637 if (i->second.size() == size_t(node_list.first)) { nb_adjacent_elements += 1; }
639 adjacent_elements.resize(nb_adjacent_elements);
640 nb_adjacent_elements = 0;
641 for (std::map<
Element*, std::vector<int>>::iterator i = tmp.
begin(); i != tmp.end(); ++i) {
642 if (i->second.size() == size_t(node_list.first)) {
645 ad.internal_node_id_list.swap(i->second);
651 const Element* e,
double dist, std::vector<Element*>& element_list)
override;
653 void get_slave_node(std::vector<std::pair<const Node*, const Node*>>& slave_node)
override;
655 void set_dof(
const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>& dof)
override {
656 global_dof_array_double = dof;
657 global_dof_array_csda_double =
658 b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle_constref>::null;
659 global_dof_array_complex_double =
660 b2linalg::Matrix<std::complex<double>, b2linalg::Mrectangle_constref>::null;
661 global_dof_array_double_tmp.resize(0, dof.size2());
662 list_element_aabb_intersection.clear();
665 void set_dof(
const b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle_constref>& dof)
667 global_dof_array_double = b2linalg::Matrix<double, b2linalg::Mrectangle_constref>::null;
668 global_dof_array_csda_double = dof;
669 global_dof_array_complex_double =
670 b2linalg::Matrix<std::complex<double>, b2linalg::Mrectangle_constref>::null;
671 global_dof_array_double_tmp.resize(0, 0);
672 list_element_aabb_intersection.clear();
675 void set_dof(
const b2linalg::Matrix<std::complex<double>, b2linalg::Mrectangle_constref>& dof)
677 global_dof_array_double = b2linalg::Matrix<double, b2linalg::Mrectangle_constref>::null;
678 global_dof_array_csda_double =
679 b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle_constref>::null;
680 global_dof_array_complex_double = dof;
681 global_dof_array_double_tmp.resize(0, 0);
682 list_element_aabb_intersection.clear();
685 const b2linalg::Matrix<double, b2linalg::Mrectangle_constref>&
get_dof(
double)
override {
686 if (global_dof_array_double.is_null()) {
687 if (global_dof_array_csda_double.is_null()
688 && global_dof_array_complex_double.is_null()) {
689 return global_dof_array_double;
691 if (global_dof_array_double_tmp.size1()
692 != global_dof_array_complex_double.size1()) {
693 global_dof_array_double_tmp.copy_real(global_dof_array_complex_double);
694 global_dof_array_double_tmpref = global_dof_array_double_tmp;
696 return global_dof_array_double_tmpref;
699 return global_dof_array_double;
703 const b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle_constref>&
get_dof(
704 b2000::csda<double>)
override {
705 if (global_dof_array_csda_double.is_null()) {
706 if (global_dof_array_double.is_null() && global_dof_array_complex_double.is_null()) {
707 return global_dof_array_csda_double;
710 "Cannot obtain csda dof because the solver is "
711 "real-valued or complex-valued.")
715 return global_dof_array_csda_double;
717 return b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle_constref>::null;
720 const b2linalg::Matrix<std::complex<double>, b2linalg::Mrectangle_constref>&
get_dof(
721 std::complex<double>)
override {
722 if (global_dof_array_complex_double.is_null()) {
723 if (global_dof_array_double.is_null() && global_dof_array_csda_double.is_null()) {
724 return global_dof_array_complex_double;
727 "Cannot obtain complex dof because the solver is "
728 "real-valued or csda-valued.")
732 return global_dof_array_complex_double;
734 return b2linalg::Matrix<std::complex<double>, b2linalg::Mrectangle_constref>::null;
737 const std::pair<std::map<std::string, size_t>, b2linalg::Index>& get_dof_field()
override {
738 if (dof_field.second.size() != nb_dof) {
739 dof_field.first.clear();
740 dof_field.first[
"Unknown"] = 0;
741 dof_field.second.resize(nb_dof);
742 dof_field.second.set_zero();
743 DegreesOfFreedom::ListDofField ldf = {
749 for (Node* node = i->next(); node !=
nullptr; node = i->next()) {
750 node->add_dof_field(ldf);
755 for (Element* element = i->next(); element !=
nullptr; element = i->next()) {
756 element->add_dof_field(ldf);
763 std::pair<size_t, size_t> get_internal_branch_and_element_id(
const Element& e) {
764 const size_t eid = e.get_id();
765 const std::vector<size_t>::const_iterator i =
767 first_element_internal_id_of_branch.begin(),
768 first_element_internal_id_of_branch.end(), eid)
770 return std::pair<size_t, size_t>(i - first_element_internal_id_of_branch.begin(), eid - *i);
773 std::pair<size_t, size_t> get_internal_branch_and_node_id(
const Node& n) {
774 const size_t eid = n.get_id();
775 const std::vector<size_t>::const_iterator i =
777 first_node_internal_id_of_branch.begin(),
778 first_node_internal_id_of_branch.end(), eid)
780 return std::pair<size_t, size_t>(i - first_node_internal_id_of_branch.begin(), eid - *i);
785 b2linalg::Matrix<double>& parent_nodes_internal_coor)
override {
786 std::pair<size_t, size_t> iid = get_internal_branch_and_element_id(element);
787 if (list_branch[iid.first].parent_element_mapping.empty()) {
788 DBError() <<
"The set MULTISCALE-NODE-MAPPINGS." << list_branch[iid.first].id
789 <<
" is missing on the database." <<
THROW;
791 const Branch::ParentElementMapping& pem =
792 list_branch[iid.first].parent_element_mapping[iid.second];
793 if (!parent_nodes_internal_coor.is_null()) {
794 parent_nodes_internal_coor = pem.global_icoor;
797 if (pem.parent_internal_branch >= d.list_branch.size()) {
798 DBError() <<
"The set MULTISCALE-NODE-MAPPINGS." << list_branch[iid.first].id
799 <<
" has some wrong internal branch id." <<
THROW;
801 if (pem.parent_internal_element
802 >= d.list_branch[pem.parent_internal_branch].list_all_elements.size()) {
803 DBError() <<
"The set MULTISCALE-NODE-MAPPINGS." << list_branch[iid.first].id
804 <<
" has some wrong internal element id." <<
THROW;
806 return d.list_branch[pem.parent_internal_branch]
807 .list_all_elements[pem.parent_internal_element];
812 b2linalg::Vector<double>& parent_internal_coor)
override {
813 std::pair<size_t, size_t> iid = get_internal_branch_and_node_id(node);
814 if (list_branch[iid.first].parent_node_mapping.empty()) {
815 DBError() <<
"The set MULTISCALE-NODE-MAPPINGS." << list_branch[iid.first].id
816 <<
" is missing on the database." <<
THROW;
818 const Branch::ParentNodeMapping& pnm =
819 list_branch[iid.first].parent_node_mapping[iid.second];
820 if (!parent_internal_coor.is_null()) {
821 parent_internal_coor.assign(pnm.global_icoor, pnm.global_icoor + 3);
824 if (pnm.parent_internal_branch >= d.list_branch.size()) {
825 DBError() <<
"The set MULTISCALE-NODE-MAPPINGS." << list_branch[iid.first].id
826 <<
" has some wrong internal branch id." <<
THROW;
828 if (pnm.parent_internal_element
829 >= d.list_branch[pnm.parent_internal_branch].list_all_elements.size()) {
830 DBError() <<
"The set MULTISCALE-NODE-MAPPINGS." << list_branch[iid.first].id
831 <<
" has some wrong internal element id." <<
THROW;
833 return d.list_branch[pnm.parent_internal_branch]
834 .list_all_elements[pnm.parent_internal_element];
838 if (nodes_local_referential.empty()) {
return nullptr; }
839 assert(node.
get_id() < nodes_local_referential.size());
840 return nodes_local_referential[node.
get_id()];
844 if (nodes_local_referential_cs.empty()) {
return nullptr; }
845 assert(node.
get_id() < nodes_local_referential_cs.size());
846 return nodes_local_referential_cs[node.
get_id()];
850 class MaterialIterator {
853 if (start == end) {
return nullptr; }
854 return (*start++).second.first;
858 MaterialIterator(Materials& materials) : start(materials.begin()), end(materials.end()) {}
859 Materials::iterator start;
860 Materials::const_iterator end;
861 friend class b2dbv3::Domain;
864 MaterialIterator* get_material_iterator() {
return new MaterialIterator(materials); }
866 MaterialIterator* get_property_iterator() {
return new MaterialIterator(properties); }
871 DataBase* database{};
873 b2linalg::SparseMatrixConnectivityType connectivity_type{
874 b2linalg::sparse_matrix_connectivity_unknown};
875 DomainProperty
property{*
this};
876 std::vector<Element::VariableInfo> value_info;
877 std::pair<size_t, size_t> state_buffers_size;
878 int element_base_type_code{
static_cast<int>(element_type_t::real_symmetric)};
880 b2linalg::Matrix<double, b2linalg::Mrectangle_constref> global_dof_array_double;
881 b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle_constref>
882 global_dof_array_csda_double;
883 b2linalg::Matrix<std::complex<double>, b2linalg::Mrectangle_constref>
884 global_dof_array_complex_double;
886 b2linalg::Matrix<double, b2linalg::Mrectangle> global_dof_array_double_tmp;
887 b2linalg::Matrix<double, b2linalg::Mrectangle_constref> global_dof_array_double_tmpref;
889 std::vector<std::pair<Element*, int>> node_element_connectivity;
890 std::vector<size_t> node_element_connectivity_index;
892 std::map<std::string, b2linalg::Matrix<double, b2linalg::Mrectangle>> list_nodal_values;
893 std::map<std::string, b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle>>
894 list_nodal_values_cs;
896 std::pair<std::map<std::string, size_t>, b2linalg::Index> dof_field;
898 using merged_node_type_t = std::map<std::pair<Node::type_t*, Node::type_t*>, Node::type_t*>;
899 merged_node_type_t merged_node_type;
901 using list_one_node_pear_node_type_t = std::map<Node::type_t*, Node*>;
903 using ObjectNameToNodeMap = std::map<std::string, Node*>;
904 ObjectNameToNodeMap object_name_to_node_map;
905 using ObjectNameToElementMap = std::map<std::string, Element*>;
906 ObjectNameToElementMap object_name_to_element_map;
908 list_one_node_pear_node_type_t list_one_node_pear_node_type;
909 Node::type_t* get_merged_node_type(Node::type_t* a, Node::type_t* b) {
910 if (a == b) {
return a; }
911 if (a > b) { std::swap(a, b); }
912 Node::type_t* mnt = merged_node_type[std::pair<Node::type_t*, Node::type_t*>(a, b)];
913 if (mnt !=
nullptr) {
return mnt; }
914 if (list_one_node_pear_node_type.empty()) {
915 const std::map<std::string, ObjectType*>& node_type_list =
916 node::module.get_object_types_list();
917 for (std::map<std::string, ObjectType*>::const_iterator i = node_type_list.begin();
918 i != node_type_list.end(); ++i) {
919 Node::type_t* nt =
dynamic_cast<Node::type_t*
>(i->second);
921 Exception() <<
"Internal error: Object identified by \"" << i->first
922 <<
"\" cannot be cast to Node::type_t*." <<
THROW;
924 list_one_node_pear_node_type[nt] = nt->new_object(allocator);
927 Node* na = list_one_node_pear_node_type[a];
928 Node* nb = list_one_node_pear_node_type[b];
929 for (list_one_node_pear_node_type_t::iterator i = list_one_node_pear_node_type.begin();
930 i != list_one_node_pear_node_type.end(); ++i) {
931 if (na->is_subnode(i->second) && nb->is_subnode(i->second)) {
933 if (mnt ==
nullptr) {
938 > i->second->get_number_of_dof()) {
944 if (mnt ==
nullptr) {
945 IOError() <<
"Could not find a common node type for the nodes " << a->get_cpp_name()
946 <<
" and " << b->get_cpp_name() <<
"." <<
THROW;
948 merged_node_type[std::pair<Node::type_t*, Node::type_t*>(a, b)] = mnt;
955 void init_node_connectivity();
957 struct ElementIndex {
958 const std::type_info& type;
959 bool operator<(
const ElementIndex& e)
const {
return type.before(e.type); }
962 struct ElementIntersectionIndex {
964 const std::type_info& type;
965 bool operator<(
const ElementIntersectionIndex& e)
const {
966 if (dist == e.dist) {
return type.before(e.type); }
967 return dist < e.dist;
972 static const int ndim = 3;
977 template <
typename SET = std::set<Element*>>
978 struct PairIntersectionList {
980 size_t size,
const AABBox* start_aabb_,
981 const std::vector<std::pair<Element*, size_t>>& list_element_) {
982 start_aabb = start_aabb_;
983 list_element = &list_element_;
984 pair_list.assign(size, std::set<Element*>());
987 void add(
const AABBox* a,
const AABBox* b) {
988 size_t ai = a - start_aabb;
989 size_t bi = b - start_aabb;
990 if ((*list_element)[ai].second == (*list_element)[bi].second) {
return; }
991 if (ai > bi) { std::swap(ai, bi); }
992 if (pair_list[(*list_element)[ai].first->get_id()]
993 .insert((*list_element)[bi].first)
999 size_t get_nb_pair()
const {
return nb_pair; }
1000 std::vector<SET> pair_list;
1002 const AABBox* start_aabb;
1003 const std::vector<std::pair<Element*, size_t>>* list_element;
1006 std::map<ElementIntersectionIndex, PairIntersectionList<std::set<Element*>>>
1007 list_element_aabb_intersection;
1008 std::map<ElementIndex, std::vector<std::pair<Element*, size_t>>> list_element_abbbb;
1010 b2spin_rw_mutex list_element_aabb_intersection_mutex;
1013 using type_t = ObjectTypeComplete<Domain, b2000::Domain::type_t>;
1018inline const b2linalg::Matrix<double, b2linalg::Mrectangle>& Domain::get_nodal_values(
1020 return get_nodal_values_double(name);
1024inline const b2linalg::Matrix<b2000::csda<double>, b2linalg::Mrectangle>& Domain::get_nodal_values(
1026 return get_nodal_values_csda(name);
1031template <
typename T>
1032void b2000::b2dbv3::Domain::save_global_dof(
1033 SetName name,
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof, RTable desc) {
1034 desc.set(
"SYSTEM",
"BRANCH");
1035 desc.set(
"TYPE",
"CELL");
1038 SetName name_e = name;
1039 name_e.gname(name.get_gname() +
"_E");
1040 for (
size_t branch = 0; branch != list_branch.size(); ++branch) {
1041 name_e.branch(list_branch[branch].
id);
1042 if (list_branch[branch].max_number_of_dof_by_element == 0) {
continue; }
1043 if (list_branch[branch].min_number_of_dof_by_element
1044 < list_branch[branch].max_number_of_dof_by_element) {
1045 b2linalg::Matrix<T, b2linalg::Mrectangle> m(
1046 list_branch[branch].max_number_of_dof_by_element,
1047 list_branch[branch].list_all_elements.size());
1048 Branch::list_elements_t& le = list_branch[branch].list_all_elements;
1049 for (
size_t i = 0; i != m.size2(); ++i) {
1050 int s = le[i]->get_number_of_dof();
1051 std::copy(&dof[pos], &dof[pos + s], &m(0, i));
1054 database->set(name_e, m);
1056 b2linalg::Interval interval(pos, pos + list_branch[branch].nb_element_dof);
1058 name_e, b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(
1059 list_branch[branch].max_number_of_dof_by_element,
1060 list_branch[branch].list_all_elements.size(), dof(interval)));
1061 pos += list_branch[branch].nb_element_dof;
1063 database->set_desc(name_e, desc);
1066 desc.set(
"TYPE",
"NODE");
1067 for (
size_t branch = 0; branch != list_branch.size(); ++branch) {
1068 name.branch(list_branch[branch].
id);
1069 if (list_branch[branch].max_number_of_dof_by_node == 0) {
continue; }
1070 if (list_branch[branch].min_number_of_dof_by_node
1071 < list_branch[branch].max_number_of_dof_by_node) {
1072 b2linalg::Matrix<T, b2linalg::Mrectangle> m(
1073 list_branch[branch].max_number_of_dof_by_node,
1074 list_branch[branch].list_nodes.size());
1075 Branch::list_nodes_t& ln = list_branch[branch].list_nodes;
1076 for (
size_t i = 0; i != m.size2(); ++i) {
1077 int s = ln[i]->get_number_of_dof();
1078 std::copy(&dof[pos], &dof[pos + s], &m(0, i));
1081 database->set(name, m);
1083 b2linalg::Interval interval(pos, pos + list_branch[branch].nb_node_dof);
1085 name, b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(
1086 list_branch[branch].max_number_of_dof_by_node,
1087 list_branch[branch].list_nodes.size(), dof(interval)));
1088 pos += list_branch[branch].nb_node_dof;
1090 database->set_desc(name, desc);
1094template <
typename T>
1095void b2000::b2dbv3::Domain::save_global_dof_indexed(
1096 SetName name,
const b2linalg::Vector<T, b2linalg::Vdense_constref>& dof, RTable desc) {
1097 desc.set(
"SYSTEM",
"BRANCH");
1098 desc.set(
"TYPE",
"NODE");
1099 desc.set(
"INDEXED",
true);
1101 SetName name_e = name;
1102 name_e.gname(name.get_gname() +
"_E");
1103 for (
size_t branch = 0; branch != list_branch.size(); ++branch) {
1104 if (list_branch[branch].max_number_of_dof_by_element == 0) {
continue; }
1105 Branch::list_elements_t& le = list_branch[branch].list_all_elements;
1107 res.reserve(list_branch[branch].max_number_of_dof_by_element * le.size() * 3);
1108 for (
size_t i = 0; i != le.size(); ++i) {
1110 for (std::pair<size_t, size_t> dn = le[i]->get_global_dof_numbering();
1111 dn.first != dn.second; ++dn.first, ++dof_id) {
1112 if (dof[dn.first] != T(0)) {
1113 res.push_back(le[i]->get_id() + 1);
1114 res.push_back(dof_id);
1115 res.push_back(dof[dn.first]);
1120 name_e.branch(list_branch[branch].
id);
1123 b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(3, res.size() / 3, &res[0]));
1124 database->set_desc(name_e, desc);
1128 for (
size_t branch = 0; branch != list_branch.size(); ++branch) {
1129 name.branch(list_branch[branch].
id);
1130 if (list_branch[branch].max_number_of_dof_by_node == 0) {
continue; }
1131 Branch::list_nodes_t& ln = list_branch[branch].list_nodes;
1133 res.reserve(list_branch[branch].max_number_of_dof_by_node * ln.size() * 3);
1134 for (
size_t i = 0; i != ln.size(); ++i) {
1136 for (std::pair<size_t, size_t> dn = ln[i]->get_global_dof_numbering();
1137 dn.first != dn.second; ++dn.first, ++dof_id) {
1138 if (dof[dn.first] != T(0)) {
1139 res.push_back(ln[i]->get_id() + 1);
1140 res.push_back(dof_id);
1141 res.push_back(dof[dn.first]);
1146 name.branch(list_branch[branch].
id);
1149 b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(3, res.size() / 3, &res[0]));
1150 database->set_desc(name, desc);
1155template <
typename T>
1156void b2000::b2dbv3::Domain::load_global_dof(
1157 SetName name, b2linalg::Vector<T, b2linalg::Vdense_ref> dof, RTable* rtable) {
1159 bool zero_init =
true;
1161 SetName name_e = name;
1162 name_e.gname(name.get_gname() +
"_E");
1163 for (
size_t branch = 0; branch != list_branch.size(); ++branch) {
1164 if (list_branch[branch].max_number_of_dof_by_element == 0) {
continue; }
1165 name_e.branch(list_branch[branch].
id);
1166 if (!database->has_key(name_e)) {
1167 std::fill_n(&dof[pos], list_branch[branch].nb_element_dof, 0);
1168 pos += list_branch[branch].nb_element_dof;
1170 if (rtable) { database->get_desc(name_e, *rtable); }
1171 if (list_branch[branch].min_number_of_dof_by_element
1172 < list_branch[branch].max_number_of_dof_by_element) {
1174 b2linalg::Matrix<T, b2linalg::Mrectangle> m(
1175 list_branch[branch].max_number_of_dof_by_element,
1176 list_branch[branch].list_all_elements.size());
1177 database->get(name_e, m);
1178 Branch::list_elements_t& ln = list_branch[branch].list_all_elements;
1179 for (
size_t i = 0; i != m.size2(); ++i) {
1180 int s = ln[i]->get_number_of_dof();
1181 std::copy(&m(0, i), &m(0, i) + s, &dof[pos]);
1186 b2linalg::Interval interval(pos, pos + list_branch[branch].nb_element_dof);
1188 (
const std::string&)name_e,
1189 b2linalg::Matrix<T, b2linalg::Mrectangle_increment_ref>(
1190 b2linalg::Matrix<T, b2linalg::Mrectangle_ref>(
1191 list_branch[branch].max_number_of_dof_by_element,
1192 list_branch[branch].list_all_elements.size(), dof(interval))));
1193 pos += list_branch[branch].nb_element_dof;
1198 for (
size_t branch = 0; branch != list_branch.size(); ++branch) {
1199 name.branch(list_branch[branch].
id);
1200 if (!database->has_key(name)) {
1201 std::fill_n(&dof[pos], list_branch[branch].nb_node_dof, 0);
1202 pos += list_branch[branch].nb_node_dof;
1206 RTable desc = rtable ? *rtable : desc_;
1207 bool has_desc = database->get_desc(name, desc,
false);
1208 if (has_desc && desc.get_string(
"DOMAIN",
"") ==
"DOF" && desc.get_bool(
"INDEXED",
false)) {
1210 b2linalg::Matrix<T, b2linalg::Mrectangle> m;
1211 database->get(name, m);
1212 std::fill_n(&dof[pos], list_branch[branch].nb_node_dof, 0);
1213 for (
size_t i = 0; i != m.size2(); ++i) {
1214 size_t n = size_t(b2000::real(m(0, i))) - 1;
1215 const std::pair<size_t, size_t> node_dof =
1216 list_branch[branch].list_nodes[n]->get_global_dof_numbering();
1217 ssize_t d = ssize_t(b2000::real(m(1, i))) - 1;
1219 DBError() <<
"A dof number of a node cannot be a negative value."
1221 << name <<
", row " << i + 1 <<
"." <<
THROW;
1223 d += node_dof.first;
1224 if (d <= ssize_t(node_dof.second)) { dof[d] = m(2, i); }
1226 pos += list_branch[branch].nb_node_dof;
1227 }
else if (has_desc && desc.get_string(
"TYPE",
"") ==
"NODE-INDEXED") {
1229 b2linalg::Matrix<T, b2linalg::Mrectangle> m;
1230 database->get(name, m);
1231 std::fill_n(&dof[pos], list_branch[branch].nb_node_dof, 0);
1232 for (
size_t i = 0; i != m.size2(); ++i) {
1233 size_t n = size_t(b2000::real(m(0, i))) - 1;
1234 const std::pair<size_t, size_t> node_dof =
1235 list_branch[branch].list_nodes[n]->get_global_dof_numbering();
1236 const size_t s = std::min(node_dof.second - node_dof.first, m.size1());
1237 std::copy(&m(1, i), &m(1, i) + s, &dof[pos + node_dof.first]);
1239 pos += list_branch[branch].nb_node_dof;
1242 if (list_branch[branch].min_number_of_dof_by_node
1243 < list_branch[branch].max_number_of_dof_by_node) {
1244 b2linalg::Matrix<T, b2linalg::Mrectangle> m(
1245 list_branch[branch].max_number_of_dof_by_node,
1246 list_branch[branch].list_nodes.size());
1247 database->get(name, m);
1248 Branch::list_nodes_t& ln = list_branch[branch].list_nodes;
1249 for (
size_t i = 0; i != m.size2(); ++i) {
1250 int s = ln[i]->get_number_of_dof();
1251 std::copy(&m(0, i), &m(0, i) + s, &dof[pos]);
1255 b2linalg::Interval interval(pos, pos + list_branch[branch].nb_node_dof);
1257 (
const std::string&)name,
1258 b2linalg::Matrix<T, b2linalg::Mrectangle_increment_ref>(
1259 b2linalg::Matrix<T, b2linalg::Mrectangle_ref>(
1260 list_branch[branch].max_number_of_dof_by_node,
1261 list_branch[branch].list_nodes.size(), dof(interval))));
1262 pos += list_branch[branch].nb_node_dof;
1267 DBError() <<
"The set " << name <<
" could not be read or is empty." <<
THROW;
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
const std::vector< size_t > dims(const std::string &key) const
Definition b2database.H:389
bool has_key(const std::string &key) const
Definition b2database.H:323
void get(const std::string &key, std::vector< T > &v, const DBSlice &s1=DBSlice::all) const
Read a positional dataset.
Definition b2database.H:458
void set(const std::string &key, const std::vector< T > &v, const DBSlice &s1=DBSlice::all, bool new_set=false)
Write a positional dataset.
Definition b2database.H:888
Defines the complete interface for Element instances (C++ representations of Finite Elements).
Definition b2element.H:156
iterator begin()
Definition b2element.H:583
size_t get_id() const
Definition b2node.H:67
Definition b2rtable.H:427
void set(const std::string &key, const T &v, const bool new_key=false)
Assign a single value. If new_key is true, the key must not exist.
Definition b2rtable.H:463
MemCom dataset names according to the B2000++ conventions.
Definition b2database.H:49
A in-core implementation of the b2dbv3::Domain. All the Element, Node and ElementProperty objects are...
Definition b2domain_database.H:62
size_t get_number_of_dof() const override
Definition b2domain_database.H:89
void set_dof(const b2linalg::Matrix< double, b2linalg::Mrectangle_constref > &dof) override
Definition b2domain_database.H:655
element_iterator get_element_iterator() override
Definition b2domain_database.H:379
Element * get_element(const std::string &element_name) override
Definition b2domain_database.H:614
const b2000::csda< double > * get_node_local_referential_csda(const Node &node) const override
Definition b2domain_database.H:843
size_t get_number_of_elements() const override
Definition b2domain_database.H:91
bool have_temperature() const override
Definition b2domain_database.H:82
void get_adjacent_elements(std::pair< int, const Node *const * > node_list, std::vector< AdjacentElement > &adjacent_elements) override
Definition b2domain_database.H:620
void set_dof(const b2linalg::Matrix< b2000::csda< double >, b2linalg::Mrectangle_constref > &dof) override
Definition b2domain_database.H:665
b2linalg::SparseMatrixConnectivityType get_dof_connectivity_type() const override
Definition b2domain_database.H:564
void get_elements_of_same_type_near(const Element *e, double dist, std::vector< Element * > &element_list) override
Definition b2domain_database.C:1093
const b2linalg::Matrix< double, b2linalg::Mrectangle_constref > & get_dof(double) override
Definition b2domain_database.H:685
void set_case(b2000::Case &case_) override
Definition b2domain_database.C:835
size_t get_number_of_nodes() const override
Definition b2domain_database.H:107
Node * get_node(const std::string &node_name) override
Definition b2domain_database.H:608
void save_state(const std::string &state_id) override
Definition b2domain_database.H:530
void save_field(const std::string &name, const b2linalg::Vector< std::complex< double >, b2linalg::Vdense_constref > &dof) override
Definition b2domain_database.H:438
void set_dof(const b2linalg::Matrix< std::complex< double >, b2linalg::Mrectangle_constref > &dof) override
Definition b2domain_database.H:675
void save_field(const std::string &name, const b2linalg::Vector< double, b2linalg::Vdense_constref > &dof) override
Definition b2domain_database.H:420
size_t get_number_of_elements_and_subelements() const override
Definition b2domain_database.H:99
void set_subcase_id(const int subcase_id_) override
Definition b2domain_database.H:78
const double * get_node_local_referential_double(const Node &node) const override
Definition b2domain_database.H:837
Element * get_parent_element_mapping(b2000::Domain &parent_domain, const b2000::Node &node, b2linalg::Vector< double > &parent_internal_coor) override
Definition b2domain_database.H:810
Element * get_parent_element_and_nodes_mapping(b2000::Domain &parent_domain, const b2000::Element &element, b2linalg::Matrix< double > &parent_nodes_internal_coor) override
Definition b2domain_database.H:783
node_iterator get_node_iterator() override
Definition b2domain_database.H:311
void load_state(const std::string &state_id) override
Definition b2domain_database.H:547
void set_model(b2000::Model &model) override
Definition b2domain_database.C:95
void save_field(const std::string &name, const b2linalg::Vector< b2000::csda< double >, b2linalg::Vdense_constref > &dof) override
Definition b2domain_database.H:429
void get_slave_node(std::vector< std::pair< const Node *, const Node * > > &slave_node) override
Definition b2domain_database.C:1164
const std::vector< Element::VariableInfo > get_value_info() const override
Definition b2domain_database.H:115
Definition b2fortran_element_property.H:53
Definition b2material_property.H:30
GenericException< IOError_name > IOError
Definition b2exception.H:335
GenericException< KeyError_name > KeyError
Definition b2exception.H:320
GenericException< TypeError_name > TypeError
Definition b2exception.H:325
GenericException< DBError_name > DBError
Definition b2exception.H:340
Definition b2domain.H:105
Element * element
Definition b2domain.H:107