14#ifdef MFEM_USE_MOONOLITH
20#include "moonolith_build_quadrature.hpp"
22using namespace mfem::internal;
29template <
class Polytope>
class CutGeneric :
public Cut
32 using Point =
typename Polytope::Point;
33 static const int Dim = Point::n_dims;
34 using Quadrature_t = moonolith::Quadrature<double, Dim>;
35 using BuildQuadrature_t = moonolith::BuildQuadrature<Polytope>;
38 const int from_elem_idx,
43 void Describe()
const override;
46 inline Quadrature_t &GetQRule() {
return q_rule_; }
47 inline int GetOrder()
const {
return order_; }
49 inline void SetOrder(
const int order) { order_ = order; }
51 virtual void MakePolytope(
Mesh &mesh,
const int elem_idx,
52 Polytope &polygon) = 0;
54 bool IsValidPhysicalPoint(
const Vector &p_mfem)
const
58 for (
int d = 0; d < Dim; ++d)
63 moonolith::HPolytope<double, Dim> poly;
66 if (!poly.contains(
p, 1e-8)) {
return false; }
70 return poly.contains(
p, 1e-8);
83 assert(
p.x <= 1 + 1e-8);
84 assert(
p.y <= 1 + 1e-8);
85 assert(
p.z <= 1 + 1e-8);
89 ok = ok && (
p.x ==
p.x);
90 ok = ok && (
p.y ==
p.y);
91 ok = ok && (
p.z ==
p.z);
93 ok = ok && (
p.x >= -1e-8);
94 ok = ok && (
p.y >= -1e-8);
95 ok = ok && (
p.z >= -1e-8);
97 ok = ok && (
p.x <= 1 + 1e-8);
98 ok = ok && (
p.y <= 1 + 1e-8);
99 ok = ok && (
p.z <= 1 + 1e-8);
103 static void ConvertQRule(
const IntegrationRule &ir, Quadrature_t &result)
105 const int size = ir.
Size();
109 for (
int k = 0; k < size; ++k)
112 result.points[k][0] = qp.x;
113 result.points[k][1] = qp.y;
114 if constexpr (Dim == 3)
116 result.points[k][12] = qp.z;
119 result.weights[k] = qp.weight;
123 inline const Polytope & from()
const {
return from_; }
124 inline const Polytope & to()
const {
return to_; }
128 Quadrature_t q_rule_;
129 Quadrature_t physical_quadrature_;
130 BuildQuadrature_t builder_;
132 double intersection_measure_{0};
135class Cut2D :
public CutGeneric<moonolith::Polygon<double, 2>>
138 using Polygon_t = moonolith::Polygon<double, 2>;
139 using Quadrature_t = moonolith::Quadrature<double, 2>;
140 using BuildQuadrature_t = moonolith::BuildQuadrature<Polygon_t>;
142 void SetIntegrationOrder(
const int order)
override;
146 void MakePolytope(
Mesh &mesh,
const int elem_idx,
147 Polygon_t &polygon)
override;
153class Cut3D :
public CutGeneric<moonolith::Polyhedron<double>>
156 using Polyhedron_t = moonolith::Polyhedron<double>;
157 using Quadrature_t = moonolith::Quadrature<double, 3>;
158 using BuildQuadrature_t = moonolith::BuildQuadrature<Polyhedron_t>;
160 void SetIntegrationOrder(
const int order)
override;
164 void MakePolytope(
Mesh &mesh,
const int elem_idx,
165 Polyhedron_t &polyhedron)
override;
174 const Vector &physical_p,
const double &w,
181 assert(ref_p.
x >= -1e-8);
182 assert(ref_p.
y >= -1e-8);
183 assert(ref_p.
z >= -1e-8);
185 assert(ref_p.
x <= 1 + 1e-8);
186 assert(ref_p.
y <= 1 + 1e-8);
187 assert(ref_p.
z <= 1 + 1e-8);
189#ifdef MFEM_DEBUG_MOONOLITH
194 physical_test_p -= physical_p;
196 assert(physical_test_p.
Norml2() < 1e-10);
212 assert(
dim == 2 ||
dim == 3);
216template <
class Polytope>
218 const int from_elem_idx,
220 const int to_elem_idx,
225 MakePolytope(*from_space.
GetMesh(), from_elem_idx, from_);
226 MakePolytope(*to_space.
GetMesh(), to_elem_idx, to_);
228 if (!builder_.apply(q_rule_, from_, to_, physical_quadrature_))
234#ifdef MFEM_DEBUG_MOONOLITH
237 static int counter = 0;
239 moonolith::MatlabScripter script;
241 script.plot(from_,
"\'g-\'");
242 script.plot(from_,
"\'g.\'");
243 script.plot(to_,
"\'r-\'");
244 script.plot(to_,
"\'r.\'");
245 script.plot(physical_quadrature_.points,
"\'*b\'");
247 mfem::out <<
"measure(" << counter <<
"): " << moonolith::measure(
248 physical_quadrature_) <<
"\n";
250 script.save(
"out_" + std::to_string(counter++) +
".m");
258 const int n_qp = physical_quadrature_.n_points();
274 if (!from_is_linear || !to_is_linear)
276 MFEM_ABORT(
"CutGeneric::BuildQuadrature() detected high-order element geometries."
277 "Moonolith only supports elements with affine faces.\n");
280 double from_measure = moonolith::measure(from_);
281 double to_measure = moonolith::measure(to_);
284 for (
int qp = 0; qp < n_qp; ++qp)
287 for (
int d = 0; d < Dim; ++d)
289 p(d) = physical_quadrature_.points[qp][d];
292 double w = physical_quadrature_.weights[qp];
293 intersection_measure_ += w;
295 assert(IsValidPhysicalPoint(
p));
298 from_quadrature[qp]);
304 assert(IsValidQPoint(from_quadrature[qp]));
305 assert(IsValidQPoint(to_quadrature[qp]));
311template <
class Polytope>
void CutGeneric<Polytope>::Describe()
const
313 mfem::out <<
"Cut measure " << intersection_measure_ <<
'\n';
316template class CutGeneric<::moonolith::Polygon<double, 2>>;
317template class CutGeneric<::moonolith::Polyhedron<double>>;
319void Cut2D::MakePolytope(
Mesh &mesh,
const int elem_idx, Polygon_t &polygon)
324 const int n_points = buffer_pts.
Width();
325 polygon.resize(n_points);
327 for (
int k = 0; k < n_points; ++k)
329 for (
int d = 0; d < 2; ++d)
331 polygon.points[k][d] = buffer_pts(d, k);
335 assert(polygon.check_convexity());
336 assert(::moonolith::measure(polygon) > 0.0);
343 const int size = ir.
Size();
344 auto &q_rule = this->GetQRule();
349 for (
int k = 0; k < size; ++k)
352 q_rule.points[k][0] = qp.x;
353 q_rule.points[k][1] = qp.y;
354 q_rule.weights[k] = qp.weight;
362void Cut2D::SetIntegrationOrder(
const int order)
364 if (this->GetOrder() != order)
368 SetQuadratureRule(ir);
372void Cut3D::SetIntegrationOrder(
const int order)
374 if (this->GetOrder() != order)
378 SetQuadratureRule(ir);
382void Cut3D::MakePolytope(
Mesh &mesh,
const int elem_idx,
383 Polyhedron_t &polyhedron)
391 const int e_type = e.
GetType();
397 const int n_faces = buffer_faces.
Size();
399 polyhedron.el_ptr.resize(n_faces + 1);
400 polyhedron.points.resize(buffer_vertices.
Size());
401 polyhedron.el_index.resize(MaxVertsXFace(e_type) * n_faces);
402 polyhedron.el_ptr[0] = 0;
404 for (
int i = 0; i < buffer_vertices.
Size(); ++i)
406 for (
int j = 0; j <
dim; ++j)
408 polyhedron.points[i][j] = buffer_pts(j, i);
413 for (
int i = 0; i < buffer_faces.
Size(); ++i)
416 const int eptr = polyhedron.el_ptr[i];
418 for (
int j = 0; j < f2v.
Size(); ++j)
420 const int v_offset = buffer_vertices.
Find(f2v[j]);
421 polyhedron.el_index[eptr + j] = v_offset;
424 polyhedron.el_ptr[i + 1] = polyhedron.el_ptr[i] + f2v.
Size();
427 polyhedron.fix_ordering();
433 const int size = ir.
Size();
435 auto &q_rule = this->GetQRule();
441 for (
int k = 0; k < size; ++k)
444 q_rule.points[k][0] = qp.x;
445 q_rule.points[k][1] = qp.y;
446 q_rule.points[k][2] = qp.z;
447 q_rule.weights[k] = qp.weight;
459 return std::make_shared<Cut2D>();
463 return std::make_shared<Cut3D>();
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
All subclasses of Cut will implement intersection routines and quadrature point generation within the...
Data type dense matrix using column-major storage.
Abstract data type element.
virtual Type GetType() const =0
Returns element's type.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
ElementTransformation * GetElementTransformation(int i) const
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Mesh * GetMesh() const
Returns the mesh.
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Class for integration point with weight.
Class for an integration rule - an Array of IntegrationPoint.
int GetOrder() const
Returns the order of the integration rule.
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
const Element * GetElement(int i) const
Return pointer to the i'th element object.
int Dimension() const
Dimension of the reference space used within the elements.
void GetElementFaces(int i, Array< int > &faces, Array< int > &ori) const
Return the indices and the orientations of all faces of element i.
void GetFaceVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of face i.
void GetPointMatrix(int i, DenseMatrix &pointmat) const
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
real_t Norml2() const
Returns the l2 norm of the vector.
int Size() const
Returns the size of the vector.
std::shared_ptr< Cut > NewCut(const int dim)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void TransformToReference(ElementTransformation &Trans, int type, const Vector &physical_p, const double &w, IntegrationPoint &ref_p)
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
real_t p(const Vector &x, real_t t)