PolyFEM
Loading...
Searching...
No Matches
Problem.cpp
Go to the documentation of this file.
1#include "Problem.hpp"
2
3namespace polyfem
4{
5 using namespace basis;
6 using namespace mesh;
7 using namespace utils;
8
9 namespace assembler
10 {
11 Problem::Problem(const std::string &name)
12 : name_(name)
13 {
14 }
15
17 const Mesh &mesh,
18 const int n_bases,
19 const std::vector<ElementBases> &bases,
20 const std::vector<ElementBases> &geom_bases,
21 const std::vector<ElementBases> &pressure_bases,
22 std::vector<LocalBoundary> &local_boundary,
23 std::vector<int> &boundary_nodes,
24 std::vector<LocalBoundary> &local_neumann_boundary,
25 std::vector<LocalBoundary> &local_pressure_boundary,
26 std::unordered_map<int, std::vector<LocalBoundary>> &local_pressure_cavity,
27 std::vector<int> &pressure_boundary_nodes,
28 std::vector<int> &dirichlet_nodes,
29 std::vector<int> &neumann_nodes)
30 {
31 std::vector<LocalBoundary> new_local_boundary;
32 std::vector<LocalBoundary> new_local_pressure_dirichlet_boundary;
33 local_neumann_boundary.clear();
34 local_pressure_boundary.clear();
35 local_pressure_cavity.clear();
36
37 for (auto it = local_boundary.begin(); it != local_boundary.end(); ++it)
38 {
39 const auto &lb = *it;
40 LocalBoundary new_lb(lb.element_id(), lb.type());
41 LocalBoundary new_neumann_lb(lb.element_id(), lb.type());
42 LocalBoundary new_pressure_lb(lb.element_id(), lb.type());
43 LocalBoundary new_pressure_dirichlet_lb(lb.element_id(), lb.type());
44 for (int i = 0; i < lb.size(); ++i)
45 {
46 LocalBoundary new_pressure_cavity_lb(lb.element_id(), lb.type());
47
48 const int primitive_g_id = lb.global_primitive_id(i);
49 const int tag = mesh.get_boundary_id(primitive_g_id);
50
51 if (tag <= 0)
52 continue;
53
54 if ((!might_have_no_dirichlet() && boundary_ids_.empty()) || std::find(boundary_ids_.begin(), boundary_ids_.end(), tag) != boundary_ids_.end())
55 new_lb.add_boundary_primitive(lb.global_primitive_id(i), lb[i]);
56 if (std::find(neumann_boundary_ids_.begin(), neumann_boundary_ids_.end(), tag) != neumann_boundary_ids_.end())
57 new_neumann_lb.add_boundary_primitive(lb.global_primitive_id(i), lb[i]);
59 new_neumann_lb.add_boundary_primitive(lb.global_primitive_id(i), lb[i]);
60 if (std::find(pressure_boundary_ids_.begin(), pressure_boundary_ids_.end(), tag) != pressure_boundary_ids_.end())
61 new_pressure_lb.add_boundary_primitive(lb.global_primitive_id(i), lb[i]);
62 if (std::find(pressure_cavity_ids_.begin(), pressure_cavity_ids_.end(), tag) != pressure_cavity_ids_.end())
63 new_pressure_cavity_lb.add_boundary_primitive(lb.global_primitive_id(i), lb[i]);
65 new_pressure_dirichlet_lb.add_boundary_primitive(lb.global_primitive_id(i), lb[i]);
66
67 if (!new_pressure_cavity_lb.empty())
68 {
69 if (local_pressure_cavity.find(tag) == local_pressure_cavity.end())
70 local_pressure_cavity[tag] = std::vector<LocalBoundary>();
71 local_pressure_cavity[tag].emplace_back(new_pressure_cavity_lb);
72 }
73 }
74
75 if (!new_lb.empty())
76 new_local_boundary.emplace_back(new_lb);
77 if (!new_neumann_lb.empty())
78 local_neumann_boundary.emplace_back(new_neumann_lb);
79 if (!new_pressure_lb.empty())
80 local_pressure_boundary.emplace_back(new_pressure_lb);
81 if (!new_pressure_dirichlet_lb.empty())
82 new_local_pressure_dirichlet_boundary.emplace_back(new_pressure_dirichlet_lb);
83 }
84 local_boundary.clear();
85 std::swap(local_boundary, new_local_boundary);
86
87 boundary_nodes.clear();
88 pressure_boundary_nodes.clear();
89
90 const int dim = is_scalar() ? 1 : mesh.dimension();
91
92 for (auto it = local_boundary.begin(); it != local_boundary.end(); ++it)
93 {
94 const auto &lb = *it;
95 const auto &b = bases[lb.element_id()];
96 for (int i = 0; i < lb.size(); ++i)
97 {
98 const int primitive_global_id = lb.global_primitive_id(i);
99 const auto nodes = b.local_nodes_for_primitive(primitive_global_id, mesh);
100
101 for (long n = 0; n < nodes.size(); ++n)
102 {
103 auto &bs = b.bases[nodes(n)];
104 for (size_t g = 0; g < bs.global().size(); ++g)
105 {
106 const int base_index = bs.global()[g].index * dim;
107 for (int d = 0; d < dim; ++d)
108 {
109 if (is_dimension_dirichet(mesh.get_boundary_id(primitive_global_id), d))
110 boundary_nodes.push_back(base_index + d);
111 }
112 }
113 }
114 }
115 }
116
117 for (auto it = new_local_pressure_dirichlet_boundary.begin(); it != new_local_pressure_dirichlet_boundary.end(); ++it)
118 {
119 const auto &lb = *it;
120 const auto &b = pressure_bases[lb.element_id()];
121 for (int i = 0; i < lb.size(); ++i)
122 {
123 const int primitive_global_id = lb.global_primitive_id(i);
124 const auto nodes = b.local_nodes_for_primitive(primitive_global_id, mesh);
125
126 for (long n = 0; n < nodes.size(); ++n)
127 {
128 auto &bs = b.bases[nodes(n)];
129 for (size_t g = 0; g < bs.global().size(); ++g)
130 {
131 const int base_index = bs.global()[g].index;
132 pressure_boundary_nodes.push_back(base_index);
133 }
134 }
135 }
136 }
137
139 {
140 for (int n_id = 0; n_id < n_bases; ++n_id)
141 {
142 const int tag = mesh.get_node_id(n_id);
143
144 if (is_nodal_dirichlet_boundary(n_id, tag))
145 {
146 dirichlet_nodes.push_back(n_id);
147
148 for (int d = 0; d < dim; ++d)
149 {
150 if (is_nodal_dimension_dirichlet(n_id, tag, d))
151 boundary_nodes.push_back(n_id * dim + d);
152 }
153 }
154 else if (is_nodal_neumann_boundary(n_id, tag))
155 {
156 neumann_nodes.push_back(n_id);
157 }
158 }
159 }
160
161 std::sort(boundary_nodes.begin(), boundary_nodes.end());
162 auto it = std::unique(boundary_nodes.begin(), boundary_nodes.end());
163 boundary_nodes.resize(std::distance(boundary_nodes.begin(), it));
164
165 std::sort(pressure_boundary_nodes.begin(), pressure_boundary_nodes.end());
166 auto it_ = std::unique(pressure_boundary_nodes.begin(), pressure_boundary_nodes.end());
167 pressure_boundary_nodes.resize(std::distance(pressure_boundary_nodes.begin(), it_));
168 }
169 } // namespace assembler
170} // namespace polyfem
void setup_bc(const mesh::Mesh &mesh, const int n_bases, const std::vector< basis::ElementBases > &bases, const std::vector< basis::ElementBases > &geom_bases, const std::vector< basis::ElementBases > &pressure_bases, std::vector< mesh::LocalBoundary > &local_boundary, std::vector< int > &boundary_nodes, std::vector< mesh::LocalBoundary > &local_neumann_boundary, std::vector< mesh::LocalBoundary > &local_pressure_boundary, std::unordered_map< int, std::vector< mesh::LocalBoundary > > &local_pressure_cavity, std::vector< int > &pressure_boundary_nodes, std::vector< int > &dirichlet_nodes, std::vector< int > &neumann_nodes)
Definition Problem.cpp:16
virtual bool has_nodal_neumann()
Definition Problem.hpp:42
std::vector< int > normal_aligned_neumann_boundary_ids_
Definition Problem.hpp:80
virtual bool is_dimension_dirichet(const int tag, const int dim) const
Definition Problem.hpp:61
virtual bool is_scalar() const =0
std::vector< int > pressure_boundary_ids_
Definition Problem.hpp:81
virtual bool is_nodal_neumann_boundary(const int n_id, const int tag)
Definition Problem.hpp:40
virtual bool might_have_no_dirichlet()
Definition Problem.hpp:60
Problem(const std::string &name)
Definition Problem.cpp:11
std::vector< int > splitting_pressure_boundary_ids_
Definition Problem.hpp:83
std::vector< int > boundary_ids_
Definition Problem.hpp:78
virtual bool is_nodal_dirichlet_boundary(const int n_id, const int tag)
Definition Problem.hpp:39
virtual bool is_nodal_dimension_dirichlet(const int n_id, const int tag, const int dim) const
Definition Problem.hpp:62
std::vector< int > neumann_boundary_ids_
Definition Problem.hpp:79
std::vector< int > pressure_cavity_ids_
Definition Problem.hpp:82
virtual bool has_nodal_dirichlet()
Definition Problem.hpp:41
Boundary primitive IDs for a single element.
bool empty() const
Check if the element has any boundary primitives.
void add_boundary_primitive(const int global_index, const int local_index)
Mark a boundary primitive as a part of the global boundary.
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:39
bool has_node_ids() const
checks if points selections are available
Definition Mesh.hpp:517
virtual int get_boundary_id(const int primitive) const
Get the boundary selection of an element (face in 3d, edge in 2d)
Definition Mesh.hpp:475
int dimension() const
utily for dimension
Definition Mesh.hpp:151
virtual int get_node_id(const int node_id) const
Get the boundary selection of a node.
Definition Mesh.hpp:484