---------------------------------------------------------------------- build a netgen mesh from the parsed model Out parameters carry the bookkeeping needed to build Region objects: vol_regions[name] : 0-based VOL region numbers carrying that elset bnd_regions[name] : 0-based BND region numbers carrying that elset mat_cells[matname] : 0-based VOL region numbers using that material id2vertex[ans
| 597 | // id2vertex[ansysid] : 0-based ngsolve vertex number (-1 if absent) |
| 598 | // ---------------------------------------------------------------------- |
| 599 | static shared_ptr<netgen::Mesh> |
| 600 | BuildAnsysMesh (const AnsysModel & m, double scale, |
| 601 | map<string,vector<int>> & vol_regions, |
| 602 | map<string,vector<int>> & bnd_regions, |
| 603 | map<string,vector<int>> & bbnd_regions, |
| 604 | map<string,vector<int>> & mat_cells, |
| 605 | map<string,vector<int>> & element_sets, |
| 606 | vector<int> & id2vertex) |
| 607 | { |
| 608 | using namespace netgen; |
| 609 | |
| 610 | const int meshdim = m.maxdim; |
| 611 | if (meshdim != 2 && meshdim != 3) |
| 612 | throw Exception("ReadAnsysInp: need a 2D or 3D mesh " |
| 613 | "(found max element dimension " + ToString(meshdim) + ")"); |
| 614 | |
| 615 | auto mesh = make_shared<Mesh>(); |
| 616 | mesh->SetDimension(meshdim); |
| 617 | |
| 618 | // ---- points + ANSYS-id -> netgen point remap ---- |
| 619 | vector<int> id2pi(m.max_node_id+1, -1); |
| 620 | id2vertex.assign(m.max_node_id+1, -1); |
| 621 | for (size_t i = 0; i < m.node_id.size(); i++) |
| 622 | { |
| 623 | const auto & c = m.node_xyz[i]; |
| 624 | PointIndex pi = mesh->AddPoint(Point3d(scale*c[0], scale*c[1], scale*c[2])); |
| 625 | id2pi[m.node_id[i]] = (int)pi; |
| 626 | id2vertex[m.node_id[i]] = (int)pi - PointIndex::BASE; // 0-based vertex nr |
| 627 | } |
| 628 | |
| 629 | // ---- reverse membership: element id -> set names containing it ---- |
| 630 | std::unordered_map<int, vector<string>> elem2sets; // all elsets |
| 631 | std::unordered_map<int, vector<string>> elem2bodies; // only *ELEMENT (body) elsets |
| 632 | for (auto & [name, ids] : m.elsets) |
| 633 | { |
| 634 | bool body = m.body_elsets.count(name) > 0; |
| 635 | for (int id : ids) |
| 636 | { |
| 637 | elem2sets[id].push_back(name); |
| 638 | if (body) elem2bodies[id].push_back(name); |
| 639 | } |
| 640 | } |
| 641 | |
| 642 | // element id -> material (from any *SECTION, resolving its elset) |
| 643 | std::unordered_map<int, string> elem_material; |
| 644 | for (auto & [es, mat] : m.sections) |
| 645 | { |
| 646 | if (mat.empty()) continue; |
| 647 | auto it = m.elsets.find(es); |
| 648 | if (it == m.elsets.end()) continue; |
| 649 | for (int id : it->second) elem_material.emplace(id, mat); |
| 650 | } |
| 651 | auto MaterialOf = [&](int elemid) -> string |
| 652 | { |
| 653 | auto it = elem_material.find(elemid); |
| 654 | return (it != elem_material.end()) ? it->second : ""; |
| 655 | }; |
| 656 |
no test coverage detected