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
16 bool Problem::has_boundary(const BoundaryKind kind, const int tag, const int fe_space_id)
17 {
18 (void)fe_space_id;
19 if (tag <= 0)
20 return false;
21
22 switch (kind)
23 {
25 return (!might_have_no_dirichlet() && boundary_ids_.empty())
26 || std::find(boundary_ids_.begin(), boundary_ids_.end(), -1) != boundary_ids_.end()
27 || std::find(boundary_ids_.begin(), boundary_ids_.end(), tag) != boundary_ids_.end();
29 return std::find(neumann_boundary_ids_.begin(), neumann_boundary_ids_.end(), tag) != neumann_boundary_ids_.end()
32 return is_boundary_pressure(tag);
34 return std::find(pressure_cavity_ids_.begin(), pressure_cavity_ids_.end(), tag) != pressure_cavity_ids_.end();
35 default:
36 return false;
37 }
38
39 return false;
40 }
41
43 const Mesh &mesh,
44 const BoundaryKind kind,
45 const int fe_space_id,
46 const std::vector<LocalBoundary> &local_boundary,
47 std::vector<LocalBoundary> &selected_local_boundary)
48 {
49 selected_local_boundary.clear();
50
51 for (const LocalBoundary &lb : local_boundary)
52 {
53 LocalBoundary selected_lb(lb.element_id(), lb.type());
54
55 for (int i = 0; i < lb.size(); ++i)
56 {
57 const int primitive_g_id = lb.global_primitive_id(i);
58 const int tag = mesh.get_boundary_id(primitive_g_id);
59
60 if (has_boundary(kind, tag, fe_space_id))
61 selected_lb.add_boundary_primitive(primitive_g_id, lb[i]);
62 }
63
64 if (!selected_lb.empty())
65 selected_local_boundary.emplace_back(selected_lb);
66 }
67 }
68
70 const Mesh &mesh,
71 const BoundaryKind kind,
72 const int fe_space_id,
73 const std::vector<ElementBases> &bases,
74 const std::vector<LocalBoundary> &local_boundary,
75 std::vector<LocalBoundary> &selected_local_boundary,
76 std::vector<int> &boundary_nodes,
77 const int value_dim)
78 {
79 setup_bc(mesh, kind, fe_space_id, local_boundary, selected_local_boundary);
80 boundary_nodes.clear();
81
82 if (kind != BoundaryKind::Dirichlet)
83 return;
84
85 const int dim = value_dim > 0 ? value_dim : (is_scalar() ? 1 : mesh.dimension());
86
87 for (const LocalBoundary &lb : selected_local_boundary)
88 {
89 const auto &b = bases[lb.element_id()];
90 for (int i = 0; i < lb.size(); ++i)
91 {
92 const int primitive_global_id = lb.global_primitive_id(i);
93 const auto nodes = b.local_nodes_for_primitive(primitive_global_id, mesh);
94
95 for (long n = 0; n < nodes.size(); ++n)
96 {
97 auto &bs = b.bases[nodes(n)];
98 for (size_t g = 0; g < bs.global().size(); ++g)
99 {
100 const int base_index = bs.global()[g].index * dim;
101 for (int d = 0; d < dim; ++d)
102 {
103 if (is_dimension_dirichet(mesh.get_boundary_id(primitive_global_id), d, fe_space_id))
104 boundary_nodes.push_back(base_index + d);
105 }
106 }
107 }
108 }
109 }
110
111 std::sort(boundary_nodes.begin(), boundary_nodes.end());
112 const auto end = std::unique(boundary_nodes.begin(), boundary_nodes.end());
113 boundary_nodes.resize(std::distance(boundary_nodes.begin(), end));
114 }
115
117 const Mesh &mesh,
118 const BoundaryKind kind,
119 const int fe_space_id,
120 const std::vector<LocalBoundary> &local_boundary,
121 std::unordered_map<int, std::vector<LocalBoundary>> &selected_by_tag)
122 {
123 std::vector<LocalBoundary> selected;
124 setup_bc(mesh, kind, fe_space_id, local_boundary, selected);
125 selected_by_tag.clear();
126 for (const LocalBoundary &lb : selected)
127 {
128 for (int i = 0; i < lb.size(); ++i)
129 {
130 const int primitive_id = lb.global_primitive_id(i);
131 const int tag = mesh.get_boundary_id(primitive_id);
132 LocalBoundary tagged_boundary(lb.element_id(), lb.type());
133 tagged_boundary.add_boundary_primitive(primitive_id, lb[i]);
134 selected_by_tag[tag].emplace_back(tagged_boundary);
135 }
136 }
137 }
138
140 const Mesh &mesh,
141 const BoundaryKind kind,
142 const int fe_space_id,
143 const int n_bases,
144 std::vector<int> &nodes)
145 {
146 nodes.clear();
147
148 if (kind == BoundaryKind::Dirichlet && !(mesh.has_node_ids() || has_nodal_dirichlet(fe_space_id)))
149 return;
150 if (kind == BoundaryKind::Neumann && !(mesh.has_node_ids() || has_nodal_neumann(fe_space_id)))
151 return;
152 for (int n_id = 0; n_id < n_bases; ++n_id)
153 {
154 const int tag = mesh.get_node_id(n_id);
155
156 if (kind == BoundaryKind::Dirichlet && is_nodal_dirichlet_boundary(n_id, tag, fe_space_id))
157 nodes.push_back(n_id);
158 else if (kind == BoundaryKind::Neumann
159 && !is_nodal_dirichlet_boundary(n_id, tag, fe_space_id)
160 && is_nodal_neumann_boundary(n_id, tag, fe_space_id))
161 nodes.push_back(n_id);
162 }
163 }
164 } // namespace assembler
165} // namespace polyfem
virtual bool is_dimension_dirichet(const int tag, const int dim, const int fe_space_id=-1) const
Definition Problem.hpp:75
std::vector< int > normal_aligned_neumann_boundary_ids_
Definition Problem.hpp:126
virtual bool has_boundary(const BoundaryKind kind, const int tag, const int fe_space_id)
Definition Problem.cpp:16
virtual bool is_scalar() const =0
virtual bool has_nodal_dirichlet(const int fe_space_id=-1)
Definition Problem.hpp:55
virtual bool might_have_no_dirichlet()
Definition Problem.hpp:74
Problem(const std::string &name)
Definition Problem.cpp:11
virtual bool has_nodal_neumann(const int fe_space_id=-1)
Definition Problem.hpp:56
std::vector< int > boundary_ids_
Definition Problem.hpp:124
virtual bool is_boundary_pressure(const int boundary_id) const
Definition Problem.hpp:49
void setup_nodal_bc(const mesh::Mesh &mesh, const BoundaryKind kind, const int fe_space_id, const int n_bases, std::vector< int > &nodes)
Definition Problem.cpp:139
void setup_bc(const mesh::Mesh &mesh, const BoundaryKind kind, const int fe_space_id, const std::vector< mesh::LocalBoundary > &local_boundary, std::vector< mesh::LocalBoundary > &selected_local_boundary)
virtual bool is_nodal_neumann_boundary(const int n_id, const int tag, const int fe_space_id=-1)
Definition Problem.hpp:54
std::vector< int > neumann_boundary_ids_
Definition Problem.hpp:125
std::vector< int > pressure_cavity_ids_
Definition Problem.hpp:128
virtual bool is_nodal_dirichlet_boundary(const int n_id, const int tag, const int fe_space_id=-1)
Definition Problem.hpp:53
Boundary primitive IDs for a single element.
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:50
bool has_node_ids() const
checks if points selections are available
Definition Mesh.hpp:524
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:466
virtual int get_node_id(const int node_id) const
Get the boundary selection of a node.
Definition Mesh.hpp:475
str nodes
Definition p_bases.py:399