Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
MeshBindingsImplementation.h
Go to the documentation of this file.
1/* This file is part of MoDELib, distributed under GNU GPL v2. */
2#pragma once
3#include "MeshBindings.h"
4#include <pybind11/eigen.h>
5#include <pybind11/stl.h>
6#include <MeshModule.h>
7#include <PolyhedralMesh.h>
8namespace mesh_python
9{
10 namespace py = pybind11;
11 using namespace model;
12
13 template <class Key> py::object keyObject(const Key &key)
14 {
15 if constexpr (std::is_integral_v<Key>)
16 {
17 return py::int_(key);
18 }
19 else
20 {
21 py::tuple result(key.size());
22 for (size_t k = 0; k < key.size(); ++k)
23 {
24 result[k] = py::int_(key[k]);
25 }
26 return result;
27 }
28 }
29 // Keep the complete owning mesh alive, rather than making Python parent/child
30 // references retain each other in cycles. Dynamic attributes participate in GC.
31 template <class T> py::object retained(const T &value, const py::object &owner)
32 {
33 auto result = py::cast(value, py::return_value_policy::reference);
34 if (!result.is_none() && !result.is(owner))
35 {
36 result.attr("_mesh_owner") = py::hasattr(owner, "_mesh_owner") ? owner.attr("_mesh_owner") : owner;
37 }
38 return result;
39 }
40 template <class Map> py::dict retainedMap(const Map &map, const py::object &owner)
41 {
42 py::dict result;
43 for (const auto &entry : map)
44 {
45 result[keyObject(entry.first)] = retained(entry.second, owner);
46 }
47 return result;
48 }
49 template <int dim, int order> void bindSimplex(py::module_ &module)
50 {
51 using S = Simplex<dim, order>;
52 const auto name = "Simplex" + std::to_string(dim) + std::to_string(order);
53 auto b = py::class_<S, std::shared_ptr<S>>(module, name.c_str(), py::dynamic_attr())
54 .def_property_readonly_static("dim",
55 [](py::object)
56 {
57 return dim;
58 })
59 .def_property_readonly_static("order",
60 [](py::object)
61 {
62 return order;
63 })
64 .def_property_readonly("xID",
65 [](const S &s)
66 {
67 return keyObject(s.xID);
68 })
69 .def_property_readonly("sID",
70 [](const S &s)
71 {
72 return s.sID;
73 })
74 .def("center",
75 [](const S &s)
76 {
77 return s.center().eval();
78 })
79 .def("isBoundarySimplex", &S::isBoundarySimplex)
80 .def("isRegionBoundarySimplex", &S::isRegionBoundarySimplex)
81 .def("regionIDs", &S::regionIDs)
82 .def("vertices",
83 [](py::object self)
84 {
85 py::list result;
86 for (const auto *v : self.cast<const S &>().vertices())
87 {
88 result.append(retained(v, self));
89 }
90 return result;
91 });
92 if constexpr (order > 0)
93 {
94 b.def_property_readonly("vol0",
95 [](const S &s)
96 {
97 return s.vol0;
98 })
99 .def("vertexPositionMatrix", &S::vertexPositionMatrix)
100 .def("bary2pos", &S::bary2pos)
101 .def("children",
102 [](py::object self)
103 {
104 py::list result;
105 for (const auto &child : self.cast<const S &>().children())
106 {
107 result.append(retained(child, self));
108 }
109 return result;
110 });
111 }
112 else
113 {
114 b.def_readonly("P0", &S::P0);
115 }
116 if constexpr (order < dim)
117 {
118 b.def("parents",
119 [](py::object self)
120 {
121 return retainedMap(self.cast<const S &>().parents(), self);
122 })
123 .def("outNormal",
124 [](const S &s)
125 {
126 return s.outNormal();
127 })
128 .def("outNormal",
129 [](const S &s, size_t id)
130 {
131 return s.outNormal(id);
132 });
133 }
134 else
135 {
136 b.def_property_readonly("region",
137 [](py::object self)
138 {
139 return retained(self.cast<const S &>().region, self);
140 })
141 .def("pos2bary", &S::pos2bary);
142 }
143 }
144 template <int dim, int order> void bindPolyhedron(py::module_ &module)
145 {
146 using C = Polyhedron<dim, order>;
147 const auto name = "Polyhedron" + std::to_string(dim) + std::to_string(order);
148 auto b = py::class_<C, std::shared_ptr<C>>(module, name.c_str(), py::dynamic_attr())
149 .def_property_readonly_static("dim",
150 [](py::object)
151 {
152 return dim;
153 })
154 .def_property_readonly_static("order",
155 [](py::object)
156 {
157 return order;
158 })
159 .def_property_readonly("key",
160 [](const C &c)
161 {
162 return keyObject(c.key);
163 })
164 .def("simplexIDs",
165 [](const C &c)
166 {
167 py::list result;
168 for (const auto *s : c.simplices())
169 {
170 result.append(keyObject(s->xID));
171 }
172 return result;
173 })
174 .def("simplices",
175 [](py::object self)
176 {
177 py::list result;
178 for (const auto *s : self.cast<const C &>().simplices())
179 {
180 result.append(retained(s, self));
181 }
182 return result;
183 });
184 if constexpr (order > 0)
185 {
186 b.def_property_readonly("children",
187 [](py::object self)
188 {
189 return retainedMap(self.cast<const C &>().children, self);
190 });
191 }
192 if constexpr (order < dim)
193 {
194 b.def_property_readonly("parents",
195 [](py::object self)
196 {
197 py::dict result;
198 for (const auto &entry : self.cast<const C &>().parents)
199 {
200 if (const auto p = entry.second.lock())
201 {
202 result[keyObject(entry.first)] = retained(p, self);
203 }
204 }
205 return result;
206 });
207 }
208 if constexpr (order == dim)
209 {
210 b.def_readonly("regionID", &C::regionID)
211 .def("faces",
212 [](py::object self)
213 {
214 return retainedMap(self.cast<const C &>().faces(), self);
215 });
216 }
217 if constexpr (order == dim - 1)
218 {
219 b.def_readonly("sID", &C::sID)
220 .def_readonly("regionIDs", &C::regionIDs)
221 .def("isExternal", &C::isExternal)
222 .def("center", &C::center)
223 .def("outNormal",
224 [](const C &c)
225 {
226 return c.outNormal();
227 })
228 .def("outNormal",
229 [](const C &c, int id)
230 {
231 return c.outNormal(id);
232 })
233 .def_property_readonly("periodicShift",
234 [](const C &c)
235 {
236 return c.periodicFacePair.first;
237 })
238 .def_property_readonly("periodicPartner",
239 [](py::object self)
240 {
241 return retained(self.cast<const C &>().periodicFacePair.second, self);
242 });
243 }
244 if constexpr (order == 0)
245 {
246 b.def_readonly("position", &C::position);
247 }
248 }
249 template <int dim, int order> void bindOrders(py::module_ &module)
250 {
253 if constexpr (order > 0)
254 {
255 bindOrders<dim, order - 1>(module);
256 }
257 }
258 template <int dim, int order = dim>
259 py::dict simplicesAt(const SimplicialMesh<dim> &mesh, int requested, const py::object &owner)
260 {
261 if (requested == order)
262 {
263 return retainedMap(mesh.template simplexFactory<order>().liveSimplices(), owner);
264 }
265 if constexpr (order > 0)
266 {
267 return simplicesAt<dim, order - 1>(mesh, requested, owner);
268 }
269 throw py::value_error("Simplex order must be between zero and dim");
270 }
271 template <int dim, int order = dim>
272 py::dict cellsAt(const PolyhedralMesh<dim> &mesh, int requested, const py::object &owner)
273 {
274 if (requested == order)
275 {
276 return retainedMap(mesh.template factory<order>(), owner);
277 }
278 if constexpr (order > 0)
279 {
280 return cellsAt<dim, order - 1>(mesh, requested, owner);
281 }
282 throw py::value_error("Polyhedron order must be between zero and dim");
283 }
284 template <int dim> void bindMesh(py::module_ &module)
285 {
286 using M = SimplicialMesh<dim>;
287 using P = PolyhedralMesh<dim>;
288 using R = SimplexReader<dim>;
289 using V = Eigen::Matrix<double, dim, 1>;
290 using A = Eigen::Matrix<double, dim, dim>;
291 bindOrders<dim, dim>(module);
292 const auto suffix = std::to_string(dim);
293 py::class_<R>(module, ("SimplexReader" + suffix).c_str())
294 .def(py::init<>())
295 .def(
296 "read",
297 [](R &reader, const std::string &file, const A &transform, const V &origin)
298 {
299 reader.read(file, transform, origin);
300 },
301 py::arg("filename"), py::arg("A") = A::Identity().eval(), py::arg("x0") = V::Zero().eval())
302 .def("nodes",
303 [](const R &reader)
304 {
305 return reader.nodes();
306 })
307 .def("elements",
308 [](const R &reader)
309 {
310 py::dict result;
311 for (const auto &entry : reader.elements())
312 {
313 result[py::int_(entry.first)] =
314 py::make_tuple(keyObject(entry.second.first), entry.second.second);
315 }
316 return result;
317 });
318 using Boundary = MeshRegionBoundary<dim>;
319 py::class_<Boundary>(module, ("MeshRegionBoundary" + suffix).c_str(), py::dynamic_attr())
320 .def_readonly("regionBndID", &Boundary::regionBndID)
321 .def("faces",
322 [](py::object self)
323 {
324 return retainedMap(self.cast<const Boundary &>().faces(), self);
325 })
326 .def("simplices",
327 [](py::object self)
328 {
329 py::list result;
330 for (const auto *simplex : self.cast<const Boundary &>().simplices())
331 {
332 result.append(retained(simplex, self));
333 }
334 return result;
335 });
336 py::class_<P, std::shared_ptr<P>>(module, ("PolyhedralMesh" + suffix).c_str(), py::dynamic_attr())
337 .def(
338 "cells",
339 [](py::object self, int order)
340 {
341 return cellsAt(self.cast<const P &>(), order, self);
342 },
343 py::arg("order") = dim)
344 .def("region",
345 [](py::object self, size_t id)
346 {
347 return retained(&self.cast<const P &>().region(id), self);
348 })
349 .def("face",
350 [](py::object self, size_t id)
351 {
352 return retained(&self.cast<const P &>().face(id), self);
353 })
354 .def("validate", &P::validate);
355 py::class_<M, std::shared_ptr<M>>(module, ("SimplicialMesh" + suffix).c_str(), py::dynamic_attr())
356 .def(py::init<>())
357 .def(py::init<const std::string &, const A &, const V &, const std::set<int> &>(), py::arg("filename"),
358 py::arg("A") = A::Identity().eval(), py::arg("x0") = V::Zero().eval(),
359 py::arg("periodicFaceIDs") = std::set<int>{})
360 .def_property_readonly_static("dim",
361 [](py::object)
362 {
363 return dim;
364 })
365 .def("xMin",
366 [](const M &mesh)
367 {
368 return mesh.xMin().eval();
369 })
370 .def("xMax",
371 [](const M &mesh)
372 {
373 return mesh.xMax().eval();
374 })
375 .def("xCenter", &M::xCenter)
376 .def("volume", &M::volume)
377 .def("periodicBasis",
378 [](const M &mesh)
379 {
380 return Eigen::MatrixXd(mesh.periodicBasis());
381 })
382 .def("identifyParallelFaces", &M::identifyParallelFaces, py::arg("periodicFaceIDs"))
383 .def("region",
384 [](py::object self, size_t id)
385 {
386 return retained(self.cast<const M &>().regions().at(id), self);
387 })
388 .def("regions",
389 [](py::object self)
390 {
391 return retainedMap(self.cast<const M &>().regions(), self);
392 })
393 .def(
394 "simplices",
395 [](py::object self, int order)
396 {
397 return simplicesAt(self.cast<const M &>(), order, self);
398 },
399 py::arg("order") = dim)
400 .def("regionBoundaries",
401 [](py::object self)
402 {
403 py::dict result;
404 for (const auto &entry : self.cast<const M &>().regionBoundaries())
405 {
406 result[py::make_tuple(entry.first.first, entry.first.second)] = retained(&entry.second, self);
407 }
408 return result;
409 })
410 .def("polyhedralMesh",
411 [](py::object self)
412 {
413 return retained(&self.cast<const M &>().polyhedralMesh(), self);
414 })
415 .def("search",
416 [](py::object self, const V &point)
417 {
418 if (self.cast<const M &>().simplices().empty())
419 {
420 return py::object(py::none());
421 }
422 const auto found = self.cast<const M &>().search(point);
423 return found.first ? retained(found.second, self) : py::none();
424 })
425 .def("periodicSimplexPairs",
426 [](py::object self)
427 {
428 py::dict result;
429 for (const auto &entry : self.cast<const M &>().periodicSimplexPairs())
430 {
431 result[keyObject(entry.first->xID)] = py::make_tuple(
432 retained(entry.second.partner, self), entry.second.shift, entry.second.vertexPermutation);
433 }
434 return result;
435 });
436 }
437} // namespace mesh_python
Eigen::Matrix3d M
Eigen::Vector3d V
the tangent vector S
function infiniteDisplacement syms Ax Ay Az Bx By Bz qx qy qz u L x y z real A
c
Definition int_R.m:15
b
Definition int_R.m:16
void bindMesh(py::module_ &module)
void bindPolyhedron(py::module_ &module)
py::object keyObject(const Key &key)
py::dict simplicesAt(const SimplicialMesh< dim > &mesh, int requested, const py::object &owner)
void bindSimplex(py::module_ &module)
py::dict retainedMap(const Map &map, const py::object &owner)
py::dict cellsAt(const PolyhedralMesh< dim > &mesh, int requested, const py::object &owner)
void bindOrders(py::module_ &module)
py::object retained(const T &value, const py::object &owner)
auto def(const std::shared_ptr< T > &x)
Definition TrialDef.h:64
auto eval(const std::shared_ptr< T > &t)
b order
vertex p[3]
int k
newbad key
result
REAL v[4]