PolyFEM
Loading...
Searching...
No Matches
PointBasedProblem.cpp
Go to the documentation of this file.
2#include <iostream>
3#include <string>
4
5namespace polyfem
6{
7 using namespace io;
8 using namespace utils;
9
10 namespace problem
11 {
13 {
14 Eigen::Matrix<bool, 3, 1> dd;
15 dd.setConstant(true);
16 bool all_dimensions_dirichlet = true;
17
18 if (data.is_array())
19 {
20 assert(data.size() == 3);
21 init((double)data[0], (double)data[1], (double)data[2], dd);
22 // TODO add dimension
23 }
24 else if (data.is_object())
25 {
26 Eigen::MatrixXd fun, pts;
27 Eigen::MatrixXi tri;
28
29 std::string rbf = "multiquadric";
30 double eps = 0.1;
31
32 fun = resources.read_matrix(data["function"].get<std::string>());
33 pts = resources.read_matrix(data["points"].get<std::string>());
34
35 int coord = -1;
36 if (data.contains("coordinate"))
37 coord = data["coordinate"];
38
39 if (coord >= 0)
40 pts = pts.block(0, 0, pts.rows(), 2).eval();
41
42 is_tri = data.contains("triangles");
43 if (is_tri)
44 tri = resources.read_int_matrix(data["triangles"].get<std::string>());
45 else
46 {
47 if (data.contains("rbf"))
48 {
49 const std::string tmp = data["rbf"];
50 rbf = tmp;
51 }
52 if (data.contains("epsilon"))
53 eps = data["epsilon"];
54 }
55
56 if (data.contains("dimension"))
57 {
59 auto &tmp = data["dimension"];
60 assert(tmp.is_array());
61 for (size_t k = 0; k < tmp.size(); ++k)
62 dd(k) = tmp[k];
63 }
64
65 if (is_tri)
66 init(pts, tri, fun, coord, dd);
67 else
68 init(pts, fun, rbf, eps, coord, dd);
69 }
70 else
71 {
72 init(0, 0, 0, dd);
73 }
74
76 }
77
78 Eigen::RowVector3d PointBasedTensorProblem::BCValue::operator()(const Eigen::RowVector3d &pt) const
79 {
80 if (is_val)
81 {
82 return val.transpose();
83 }
84 Eigen::RowVector3d res;
85
86 if (coordiante_0 >= 0)
87 {
88 Eigen::RowVector2d pt2;
89 pt2 << pt(coordiante_0), pt(coordiante_1);
90
91 if (is_tri)
92 res = tri_func.interpolate(pt2);
93 else
94 res = rbf_func.interpolate(pt2);
95 }
96 else
97 {
98 if (is_tri)
99 res = tri_func.interpolate(pt);
100 else
101 res = rbf_func.interpolate(pt);
102 }
103
104 return res;
105 }
106
108 : Problem(name), rhs_(0), scaling_(1)
109 {
110 translation_.setZero();
111 }
112
113 void PointBasedTensorProblem::rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val, const int) const
114 {
115 val = Eigen::MatrixXd::Constant(pts.rows(), pts.cols(), rhs_);
116 }
117
118 void PointBasedTensorProblem::dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val, const int) const
119 {
120 val = Eigen::MatrixXd::Zero(pts.rows(), mesh.dimension());
121
122 for (long i = 0; i < pts.rows(); ++i)
123 {
124 const int id = mesh.get_boundary_id(global_ids(i));
125 const auto &pt3d = (pts.row(i) + translation_.transpose()) / scaling_;
126
127 for (size_t b = 0; b < boundary_ids_.size(); ++b)
128 {
129 if (id == boundary_ids_[b])
130 {
131 val.row(i) = bc_[b](pt3d) * scaling_;
132 }
133 }
134 }
135 }
136
137 void PointBasedTensorProblem::neumann_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &normals, const double t, Eigen::MatrixXd &val, const int) const
138 {
139 val = Eigen::MatrixXd::Zero(pts.rows(), mesh.dimension());
140
141 for (long i = 0; i < pts.rows(); ++i)
142 {
143 const int id = mesh.get_boundary_id(global_ids(i));
144 const auto &pt3d = (pts.row(i) + translation_.transpose()) / scaling_;
145
146 for (size_t b = 0; b < neumann_boundary_ids_.size(); ++b)
147 {
148 if (id == neumann_boundary_ids_[b])
149 {
150 val.row(i) = neumann_bc_[b](pt3d) * scaling_;
151 }
152 }
153 }
154 }
155
156 void PointBasedTensorProblem::add_constant(const int bc_tag, const Eigen::Vector3d &value, const Eigen::Matrix<bool, 3, 1> &dd, const bool is_neumann)
157 {
158 if (is_neumann)
159 {
160 neumann_boundary_ids_.push_back(bc_tag);
161 neumann_bc_.emplace_back();
162 neumann_bc_.back().init(value, dd);
163 }
164 else
165 {
166 all_dimensions_dirichlet_ = all_dimensions_dirichlet_ && dd(0) && dd(1) && dd(2);
167 boundary_ids_.push_back(bc_tag);
168 bc_.emplace_back();
169 bc_.back().init(value, dd);
170 }
171 }
172
173 void PointBasedTensorProblem::add_function(const int bc_tag, const Eigen::MatrixXd &func, const Eigen::MatrixXd &pts, const Eigen::MatrixXi &tri, const int coord, const Eigen::Matrix<bool, 3, 1> &dd, const bool is_neumann)
174 {
175 if (is_neumann)
176 {
177 neumann_boundary_ids_.push_back(bc_tag);
178 neumann_bc_.emplace_back();
179 neumann_bc_.back().init(pts.block(0, 0, pts.rows(), 2), tri, func, coord, dd);
180 }
181 else
182 {
183 all_dimensions_dirichlet_ = all_dimensions_dirichlet_ && dd(0) && dd(1) && dd(2);
184
185 boundary_ids_.push_back(bc_tag);
186 bc_.emplace_back();
187 bc_.back().init(pts.block(0, 0, pts.rows(), 2), tri, func, coord, dd);
188 }
189 }
190
191 void PointBasedTensorProblem::add_function(const int bc_tag, const Eigen::MatrixXd &func, const Eigen::MatrixXd &pts, const std::string &rbf, const double eps, const int coord, const Eigen::Matrix<bool, 3, 1> &dd, const bool is_neumann)
192 {
193 if (is_neumann)
194 {
195 neumann_boundary_ids_.push_back(bc_tag);
196 neumann_bc_.emplace_back();
197 if (coord >= 0)
198 neumann_bc_.back().init(pts.block(0, 0, pts.rows(), 2), func, rbf, eps, coord, dd);
199 else
200 neumann_bc_.back().init(pts, func, rbf, eps, coord, dd);
201 }
202 else
203 {
204 all_dimensions_dirichlet_ = all_dimensions_dirichlet_ && dd(0) && dd(1) && dd(2);
205
206 boundary_ids_.push_back(bc_tag);
207 bc_.emplace_back();
208 if (coord >= 0)
209 bc_.back().init(pts.block(0, 0, pts.rows(), 2), func, rbf, eps, coord, dd);
210 else
211 bc_.back().init(pts, func, rbf, eps, coord, dd);
212 }
213 }
214
215 bool PointBasedTensorProblem::is_dimension_dirichet(const int tag, const int dim, const int fe_space_id) const
216 {
217 if (all_dimensions_dirichlet(fe_space_id))
218 return true;
219
220 for (size_t b = 0; b < boundary_ids_.size(); ++b)
221 {
222 if (tag == boundary_ids_[b])
223 {
224 return bc_[b].is_dirichet_dim(dim);
225 }
226 }
227
228 assert(false);
229 return true;
230 }
231
232 void PointBasedTensorProblem::set_parameters(const json &params, const io::ResourceIO &resources)
233 {
234 if (initialized_)
235 return;
236
237 if (params.contains("scaling"))
238 {
239 scaling_ = params["scaling"];
240 }
241
242 if (params.contains("rhs"))
243 {
244 rhs_ = params["rhs"];
245 }
246
247 if (params.contains("translation"))
248 {
249 const auto &j_translation = params["translation"];
250
251 assert(j_translation.is_array());
252 assert(j_translation.size() == 3);
253
254 for (int k = 0; k < 3; ++k)
255 translation_(k) = j_translation[k];
256 }
257
258 if (params.contains("boundary_ids"))
259 {
260 boundary_ids_.clear();
261 auto j_boundary = params["boundary_ids"];
262
263 boundary_ids_.resize(j_boundary.size());
264 bc_.resize(boundary_ids_.size());
265
266 for (size_t i = 0; i < boundary_ids_.size(); ++i)
267 {
268 boundary_ids_[i] = j_boundary[i]["id"];
269 const auto ff = j_boundary[i]["value"];
270 const bool all_d = bc_[i].init(ff, resources);
272 }
273 }
274
275 if (params.contains("neumann_boundary_ids"))
276 {
277 neumann_boundary_ids_.clear();
278 auto j_boundary = params["neumann_boundary_ids"];
279
280 neumann_boundary_ids_.resize(j_boundary.size());
281 neumann_bc_.resize(neumann_boundary_ids_.size());
282
283 for (size_t i = 0; i < neumann_boundary_ids_.size(); ++i)
284 {
285 neumann_boundary_ids_[i] = j_boundary[i]["id"];
286 const auto ff = j_boundary[i]["value"];
287 neumann_bc_[i].init(ff, resources);
288 }
289 }
290 }
291 } // namespace problem
292} // namespace polyfem
double val
Definition Assembler.cpp:90
const std::string & name() const
Definition Problem.hpp:29
std::vector< int > boundary_ids_
Definition Problem.hpp:126
std::vector< int > neumann_boundary_ids_
Definition Problem.hpp:127
Read-only interface to a hierarchical collection of simulation resources.
virtual Eigen::MatrixXi read_int_matrix(const std::string &path) const =0
virtual Eigen::MatrixXd read_matrix(const std::string &path) const =0
Abstract mesh class to capture 2d/3d conforming and non-conforming meshes.
Definition Mesh.hpp:50
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
int dimension() const
utily for dimension
Definition Mesh.hpp:138
bool init(const json &data, const io::ResourceIO &resources)
Eigen::RowVector3d operator()(const Eigen::RowVector3d &pt) const
void dirichlet_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val, const int fe_space_id=-1) const override
void rhs(const assembler::Assembler &assembler, const Eigen::MatrixXd &pts, const double t, Eigen::MatrixXd &val, const int fe_space_id=-1) const override
void add_constant(const int bc_tag, const Eigen::Vector3d &value)
bool all_dimensions_dirichlet(const int fe_space_id) const override
void neumann_bc(const mesh::Mesh &mesh, const Eigen::MatrixXi &global_ids, const Eigen::MatrixXd &uv, const Eigen::MatrixXd &pts, const Eigen::MatrixXd &normals, const double t, Eigen::MatrixXd &val, const int fe_space_id=-1) const override
void set_parameters(const json &params, const io::ResourceIO &resources) override
void add_function(const int bc_tag, const Eigen::MatrixXd &func, const Eigen::MatrixXd &pts, const Eigen::MatrixXi &tri, const int coord)
bool is_dimension_dirichet(const int tag, const int dim, const int fe_space_id=-1) const override
nlohmann::json json
Definition Common.hpp:9