PolyFEM
Loading...
Searching...
No Matches
Obstacle.cpp
Go to the documentation of this file.
2
7
8#include <igl/edges.h>
9#include <ipc/utils/eigen_ext.hpp>
10
11namespace polyfem
12{
13 using namespace utils;
14
15 namespace mesh
16 {
18 {
19 clear();
20 }
21
23 {
24 dim_ = 0;
25 v_.resize(0, 0);
26 f_.resize(0, 0);
27 e_.resize(0, 0);
28 tets_.resize(0, 0);
29
30 in_f_.resize(0, 0);
31 in_e_.resize(0, 0);
32 in_v_.resize(0);
33 in_tets_.resize(0, 0);
34
35 displacements_.clear();
36
37 endings_.clear();
38
39 planes_.clear();
40 }
41
43 const Eigen::MatrixXd &vertices,
44 const Eigen::VectorXi &codim_vertices,
45 const Eigen::MatrixXi &codim_edges,
46 const Eigen::MatrixXi &faces,
47 const Eigen::MatrixXi &tets)
48 {
49 if (vertices.size() == 0)
50 return;
51
52 if (tets.size() && (tets.cols() == 3 || tets.cols() == 4))
53 {
54 const int tc = tets.cols();
55 tets_.conservativeResize(tets_.rows() + tets.rows(), tc);
56 tets_.bottomRows(tets.rows()) = tets.array() + v_.rows();
57
58 in_tets_.conservativeResize(in_tets_.rows() + tets.rows(), tc);
59 in_tets_.bottomRows(tets.rows()) = tets.array() + v_.rows();
60 }
61 else if (tets.size())
62 {
63 log_and_throw_error("Obstacle volumetric cells must be triangles (2D) or tetrahedra (3D)!");
64 }
65
66 if (dim_ == 0)
67 dim_ = vertices.cols();
68 assert(dim_ == vertices.cols());
69
70 if (codim_vertices.size())
71 {
72 codim_v_.conservativeResize(codim_v_.size() + codim_vertices.size());
73 codim_v_.tail(codim_vertices.size()) = codim_vertices.array() + v_.rows();
74
75 in_v_.conservativeResize(in_v_.size() + codim_vertices.size());
76 in_v_.tail(codim_vertices.size()) = codim_vertices.array() + v_.rows();
77 }
78
79 if (codim_edges.size())
80 {
81 e_.conservativeResize(e_.rows() + codim_edges.rows(), 2);
82 e_.bottomRows(codim_edges.rows()) = codim_edges.array() + v_.rows();
83
84 in_e_.conservativeResize(in_e_.rows() + codim_edges.rows(), 2);
85 in_e_.bottomRows(codim_edges.rows()) = codim_edges.array() + v_.rows();
86 }
87
88 if (faces.size() && faces.cols() == 3)
89 {
90 f_.conservativeResize(f_.rows() + faces.rows(), 3);
91 f_.bottomRows(faces.rows()) = faces.array() + v_.rows();
92
93 in_f_.conservativeResize(in_f_.rows() + faces.rows(), 3);
94 in_f_.bottomRows(faces.rows()) = faces.array() + v_.rows();
95
96 Eigen::MatrixXi edges;
97 igl::edges(faces, edges);
98
99 e_.conservativeResize(e_.rows() + edges.rows(), 2);
100 e_.bottomRows(edges.rows()) = edges.array() + v_.rows();
101 }
102 else if (faces.size())
103 {
104 log_and_throw_error("Obstacle supports only segments and triangles!");
105 }
106
107 v_.conservativeResize(v_.rows() + vertices.rows(), dim_);
108 v_.bottomRows(vertices.rows()) = vertices;
109
110 endings_.push_back(v_.rows());
111 }
112
114 const Eigen::MatrixXd &vertices,
115 const Eigen::VectorXi &codim_vertices,
116 const Eigen::MatrixXi &codim_edges,
117 const Eigen::MatrixXi &faces,
118 const json &displacement,
119 const io::ResourceIO &resources,
120 const Eigen::MatrixXi &tets)
121 {
122 append_mesh(vertices, codim_vertices, codim_edges, faces, tets);
123
124 displacements_.emplace_back();
125 for (size_t d = 0; d < dim_; ++d)
126 {
127 assert(displacement["value"].is_array());
128 displacements_.back().value[d].init(displacement["value"][d], resources);
129 }
130
131 if (displacement.contains("interpolation"))
132 {
133 if (displacement["interpolation"].is_array())
134 {
135 for (int ii = 0; ii < displacement["interpolation"].size(); ++ii)
136 displacements_.back().interpolation.emplace_back(Interpolation::build(displacement["interpolation"][ii]));
137 }
138 else
139 displacements_.back().interpolation.emplace_back(Interpolation::build(displacement["interpolation"]));
140 }
141 }
142
144 const std::vector<Eigen::MatrixXd> &vertices,
145 const Eigen::VectorXi &codim_vertices,
146 const Eigen::MatrixXi &codim_edges,
147 const Eigen::MatrixXi &faces,
148 const int fps,
149 const Eigen::MatrixXi &tets)
150 {
151 if (vertices.size() == 0 || vertices[0].size() == 0)
152 return;
153
154 append_mesh(vertices[0], codim_vertices, codim_edges, faces, tets);
155
156 std::array<std::vector<Eigen::MatrixXd>, 3> displacements_xyz;
157 for (size_t i = 0; i < vertices.size(); ++i)
158 {
159 Eigen::MatrixXd displacement = vertices[i] - vertices[0];
160 for (size_t d = 0; d < dim_; ++d)
161 displacements_xyz[d].push_back(displacement.col(d));
162 }
163
164 displacements_.emplace_back();
165 for (size_t d = 0; d < dim_; ++d)
166 {
167 const std::vector<Eigen::MatrixXd> displacements = displacements_xyz[d];
168 displacements_.back().value[d].init(
169 [displacements, fps](double x, double y, double z, double t, int index) -> double {
170 const double frame = t * fps;
171 const double interp = frame - floor(frame);
172 const int frame0 = (int)floor(frame);
173 const int frame1 = (int)ceil(frame);
174 if (frame1 >= displacements.size())
175 return displacements.back()(index);
176 const double u0 = displacements[frame0](index);
177 const double u1 = displacements[frame1](index);
178 return (u1 - u0) * interp + u0;
179 });
180 }
181 }
182
183 void Obstacle::append_plane(const VectorNd &origin, const VectorNd &normal)
184 {
185 if (dim_ == 0)
186 dim_ = origin.size();
187 assert(normal.size() >= dim_);
188 assert(origin.size() >= dim_);
189 planes_.emplace_back(origin.head(dim_), normal.head(dim_).normalized());
190 }
191
192 void Obstacle::change_displacement(const int oid, const Eigen::RowVector3d &val, const std::string &interp)
193 {
194 change_displacement(oid, val, interp.empty() ? std::make_shared<NoInterpolation>() : Interpolation::build(interp));
195 }
196 void Obstacle::change_displacement(const int oid, const std::function<Eigen::MatrixXd(double x, double y, double z, double t)> &func, const std::string &interp)
197 {
198 change_displacement(oid, func, interp.empty() ? std::make_shared<NoInterpolation>() : Interpolation::build(interp));
199 }
200 void Obstacle::change_displacement(const int oid, const json &val, const io::ResourceIO &resources, const std::string &interp)
201 {
202 change_displacement(oid, val, interp.empty() ? std::make_shared<NoInterpolation>() : Interpolation::build(interp), resources);
203 }
204
205 void Obstacle::change_displacement(const int oid, const Eigen::RowVector3d &val, const std::shared_ptr<Interpolation> &interp)
206 {
207 for (size_t k = 0; k < val.size(); ++k)
208 displacements_[oid].value[k].init(val[k]);
209
210 displacements_[oid].interpolation.clear();
211 displacements_[oid].interpolation.push_back(interp);
212 }
213
214 void Obstacle::change_displacement(const int oid, const std::function<Eigen::MatrixXd(double x, double y, double z, double t)> &func, const std::shared_ptr<Interpolation> &interp)
215 {
216 for (size_t k = 0; k < displacements_.back().value.size(); ++k)
217 displacements_[oid].value[k].init(func, k);
218
219 displacements_[oid].interpolation.clear();
220 displacements_[oid].interpolation.push_back(interp);
221 }
222
223 void Obstacle::change_displacement(const int oid, const json &val, const io::ResourceIO &resources, const std::shared_ptr<Interpolation> &interp)
224 {
225 change_displacement(oid, val, interp, resources);
226 }
227 void Obstacle::change_displacement(const int oid, const json &val, const std::shared_ptr<Interpolation> &interp, const io::ResourceIO &resources)
228 {
229 for (size_t k = 0; k < val.size(); ++k)
230 displacements_[oid].value[k].init(val[k], resources);
231
232 displacements_[oid].interpolation.clear();
233 displacements_[oid].interpolation.push_back(interp);
234 }
235
236 void Obstacle::update_displacement(const double t, Eigen::MatrixXd &sol) const
237 {
238 // NOTE: assumes obstacle displacements is stored at the bottom of sol
239 const int offset = sol.rows() - v_.rows() * (sol.cols() == 1 ? dim_ : 1);
240
241 int start = 0;
242
243 for (int k = 0; k < endings_.size(); ++k)
244 {
245 const int to = endings_[k];
246 const auto &disp = displacements_[k];
247
248 for (int i = start; i < to; ++i)
249 {
250 for (int d = 0; d < dim_; ++d)
251 {
252 const int sol_row = sol.cols() == 1 ? (offset + i * dim_ + d) : (offset + i);
253 const int sol_col = sol.cols() == 1 ? 0 : d;
254 sol(sol_row, sol_col) = disp.eval(v_.row(i), d, t, i - start);
255 }
256 }
257
258 start = to;
259 }
260 assert(endings_.empty() || (start * (sol.cols() == 1 ? dim_ : 1) + offset) == sol.rows());
261 }
262
263 void Obstacle::set_zero(Eigen::MatrixXd &sol) const
264 {
265 // NOTE: assumes obstacle displacements is stored at the bottom of sol
266 sol.bottomRows(v_.rows() * (sol.cols() == 1 ? dim_ : 1)).setZero();
267 }
268
269 void Obstacle::set_units(const Units &units)
270 {
271 for (auto &d : displacements_)
272 {
273 d.set_unit_type(units.length());
274 }
275 }
276
278 {
279 constexpr int size_x = 10;
280 constexpr int size_y = 10;
281
282 if (dim_ == 2)
283 {
284 Eigen::Vector2d tangent(normal().y(), -normal().x());
285
286 vis_v_.resize(size_x + 1, 2);
287 for (int x = 0; x <= size_x; ++x)
288 {
289 vis_v_.row(x) = (x - size_x / 2.0) * tangent;
290 }
291
292 vis_e_.resize(size_x, 2);
293 for (int x = 0; x < size_x; ++x)
294 {
295 vis_e_.row(x) << x, x + 1;
296 }
297 }
298 else
299 {
300 assert(dim_ == 3);
301
302 const Eigen::Vector3d normal = this->normal();
303
304 const Eigen::Vector3d cross_x = Eigen::Vector3d::UnitX().cross(normal);
305 const Eigen::Vector3d cross_y = Eigen::Vector3d::UnitY().cross(normal);
306
307 Eigen::Vector3d tangent_x, tangent_y;
308 if (cross_x.squaredNorm() > cross_y.squaredNorm())
309 {
310 tangent_x = cross_x.normalized();
311 tangent_y = normal.cross(cross_x).normalized();
312 }
313 else
314 {
315 tangent_x = cross_y.normalized();
316 tangent_y = normal.cross(cross_y).normalized();
317 }
318
319 vis_v_.resize((size_x + 1) * (size_y + 1), 3);
320 for (int x = 0; x <= size_x; ++x)
321 {
322 for (int y = 0; y <= size_y; ++y)
323 {
324 vis_v_.row(x * size_y + y) = (x - size_x / 2.0) * tangent_x + (y - size_y / 2.0) * tangent_y;
325 }
326 }
327
328 vis_f_.resize(2 * size_x * size_y, 3);
329 for (int x = 0; x < size_x; ++x)
330 {
331 for (int y = 0; y < size_y; ++y)
332 {
333 vis_f_.row(2 * (x * size_x + y)) << x * size_x + y, x * size_x + y + 1, (x + 1) * size_x + y;
334 vis_f_.row(2 * (x * size_x + y) + 1) << x * size_x + y + 1, (x + 1) * size_x + (y + 1), (x + 1) * size_x + y;
335 }
336 }
337
338 igl::edges(vis_f_, vis_e_);
339 }
340 }
341
342 } // namespace mesh
343} // namespace polyfem
double val
Definition Assembler.cpp:90
std::vector< Eigen::VectorXi > faces
int y
int z
int x
const std::string & length() const
Definition Units.hpp:19
Read-only interface to a hierarchical collection of simulation resources.
const VectorNd & normal() const
Definition Obstacle.hpp:119
std::vector< Plane > planes_
Definition Obstacle.hpp:103
void change_displacement(const int oid, const Eigen::RowVector3d &val, const std::shared_ptr< utils::Interpolation > &interp=std::make_shared< utils::NoInterpolation >())
Eigen::MatrixXi f_
Definition Obstacle.hpp:90
Eigen::MatrixXi e_
Definition Obstacle.hpp:91
void append_mesh(const Eigen::MatrixXd &vertices, const Eigen::VectorXi &codim_vertices, const Eigen::MatrixXi &codim_edges, const Eigen::MatrixXi &faces, const json &displacement, const io::ResourceIO &resources, const Eigen::MatrixXi &tets=Eigen::MatrixXi())
Definition Obstacle.cpp:113
void append_mesh_sequence(const std::vector< Eigen::MatrixXd > &vertices, const Eigen::VectorXi &codim_vertices, const Eigen::MatrixXi &codim_edges, const Eigen::MatrixXi &faces, const int fps, const Eigen::MatrixXi &tets=Eigen::MatrixXi())
Definition Obstacle.cpp:143
const Eigen::MatrixXi & tets() const
Definition Obstacle.hpp:49
void append_plane(const VectorNd &point, const VectorNd &normal)
Definition Obstacle.cpp:183
Eigen::MatrixXi in_f_
Definition Obstacle.hpp:95
Eigen::MatrixXi in_tets_
Definition Obstacle.hpp:97
Eigen::MatrixXd v_
Definition Obstacle.hpp:88
void set_zero(Eigen::MatrixXd &sol) const
Definition Obstacle.cpp:263
Eigen::VectorXi codim_v_
Definition Obstacle.hpp:89
void update_displacement(const double t, Eigen::MatrixXd &sol) const
Definition Obstacle.cpp:236
void set_units(const Units &units)
Definition Obstacle.cpp:269
Eigen::MatrixXi tets_
Definition Obstacle.hpp:92
Eigen::MatrixXi in_e_
Definition Obstacle.hpp:96
Eigen::VectorXi in_v_
Definition Obstacle.hpp:94
std::vector< assembler::TensorBCValue > displacements_
Definition Obstacle.hpp:99
std::vector< int > endings_
Definition Obstacle.hpp:101
static std::shared_ptr< Interpolation > build(const json &params)
Eigen::Matrix< double, Eigen::Dynamic, 1, 0, 3, 1 > VectorNd
Definition Types.hpp:11
nlohmann::json json
Definition Common.hpp:9
void log_and_throw_error(const std::string &msg)
Definition Logger.cpp:73