13 const Eigen::Matrix<double, Eigen::Dynamic, 4>& coords,
double tol) {
17 const double e0lensq = (coords.col(1) - coords.col(0)).squaredNorm();
18 const double e1lensq = (coords.col(2) - coords.col(1)).squaredNorm();
19 const double e2lensq = (coords.col(3) - coords.col(2)).squaredNorm();
20 const double e3lensq = (coords.col(0) - coords.col(3)).squaredNorm();
22 const double circum = e0lensq + e1lensq + e2lensq + e3lensq;
23 LF_VERIFY_MSG(e0lensq > tol * circum,
"Collapsed edge 0");
24 LF_VERIFY_MSG(e1lensq > tol * circum,
"Collapsed edge 1");
25 LF_VERIFY_MSG(e2lensq > tol * circum,
"Collapsed edge 2");
26 LF_VERIFY_MSG(e3lensq > tol * circum,
"Collapsed edge 3");
31 ((coords(0, 1) - coords(0, 0)) * (coords(1, 2) - coords(1, 0)) -
32 (coords(1, 1) - coords(1, 0)) * (coords(0, 2) - coords(0, 0)));
34 ((coords(0, 3) - coords(0, 0)) * (coords(1, 2) - coords(1, 0)) -
35 (coords(1, 3) - coords(1, 0)) * (coords(0, 2) - coords(0, 0)));
36 const double area = std::fabs(ar1) + std::fabs(ar2);
37 LF_VERIFY_MSG(area > tol * circum,
"Degenerate 2D quad");
42 const Eigen::Matrix<double, 3, 4> c3d(coords.block<3, 4>(0, 0));
44 ((c3d.col(1) - c3d.col(0)).cross(c3d.col(2) - c3d.col(0))).norm();
46 ((c3d.col(3) - c3d.col(0)).cross(c3d.col(2) - c3d.col(0))).norm();
47 const double area = ar1 + ar2;
48 LF_VERIFY_MSG(area > tol * circum,
"Degenerate 3D quad");
53 LF_ASSERT_MSG(
false,
"Illegal world dimension" << wd);
61 : coords_(std::move(coords)) {
68 LF_ASSERT_MSG(local.rows() == 2,
"reference coords must be 2-vectors");
73 ((1 - local.array().row(0)) * (1 - local.array().row(1)))
76 (local.array().row(0) * (1 - local.array().row(1))).matrix() +
78 (local.array().row(0) * local.array().row(1)).matrix() +
80 ((1 - local.array().row(0)) * local.array().row(1)).matrix();
86 Eigen::MatrixXd result(
DimGlobal(), local.cols() * 2);
90 for (Eigen::Index i = 0; i < local.cols(); ++i) {
93 result.col(2 * i) = (
coords_.col(1) -
coords_.col(0)) * (1 - local(1, i)) +
97 result.col(2 * i + 1) =
107 const Eigen::MatrixXd& local)
const {
108 Eigen::MatrixXd result(
DimGlobal(), local.cols() * 2);
109 Eigen::MatrixXd jacobian(
DimGlobal(), 2);
112 for (Eigen::Index i = 0; i < local.cols(); ++i) {
114 jacobian.col(0) = (
coords_.col(1) -
coords_.col(0)) * (1 - local(1, i)) +
116 jacobian.col(1) = (
coords_.col(3) -
coords_.col(0)) * (1 - local(0, i)) +
123 result.block(0, 2 * i,
DimGlobal(), 2) = jacobian.transpose().inverse();
125 result.block(0, 2 * i,
DimGlobal(), 2) = (jacobian.transpose() * jacobian)
126 .colPivHouseholderQr()
127 .solve(jacobian.transpose())
137 Eigen::VectorXd result(local.cols());
138 Eigen::MatrixXd jacobian(
DimGlobal(), 2);
141 for (Eigen::Index i = 0; i < local.cols(); ++i) {
143 jacobian.col(0) = (
coords_.col(1) -
coords_.col(0)) * (1 - local(1, i)) +
145 jacobian.col(1) = (
coords_.col(3) -
coords_.col(0)) * (1 - local(0, i)) +
150 result(i) = std::abs(jacobian.determinant());
152 result(i) = std::sqrt((jacobian.transpose() * jacobian).determinant());
160 using std::make_unique;
163 LF_ASSERT_MSG(i == 0,
"i is out of bounds.");
164 return std::make_unique<QuadO1>(
coords_);
166 LF_ASSERT_MSG(i >= 0 && i < 4,
"i is out of bounds.");
167 return make_unique<SegmentO1>(
168 (Eigen::Matrix<double, Eigen::Dynamic, 2>(
DimGlobal(), 2)
169 <<
coords_.col(
RefEl().SubSubEntity2SubEntity(1, i, 1, 0)),
170 coords_.col(
RefEl().SubSubEntity2SubEntity(1, i, 1, 1)))
173 LF_ASSERT_MSG(i >= 0 && i < 4,
"i is out of bounds.");
174 return make_unique<Point>(
coords_.col(i));
176 LF_VERIFY_MSG(
false,
"codim is out of bounds.");
188 LF_VERIFY_MSG(codim < 3,
"Illegal codim " << codim);
191 const double h_lattice = 1.0 /
static_cast<double>(ref_pat.
LatticeConst());
193 std::vector<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic>>
200 "no_children = " << no_children <<
" <-> " << ref_pat.
NumChildren(codim));
203 std::vector<std::unique_ptr<Geometry>> child_geo_uptrs{};
205 for (
int l = 0; l < no_children; l++) {
209 child_polygons[l].rows() == 2,
210 "child_polygons[" << l <<
"].rows() = " << child_polygons[l].rows());
213 const Eigen::MatrixXd child_geo(
214 Global(h_lattice * child_polygons[l].cast<double>()));
218 if (child_polygons[l].cols() == 3) {
220 child_geo_uptrs.push_back(std::make_unique<TriaO1>(child_geo));
221 }
else if (child_polygons[l].cols() == 4) {
223 child_geo_uptrs.push_back(std::make_unique<QuadO1>(child_geo));
225 LF_VERIFY_MSG(
false,
"child_polygons[" << l <<
"].cols() = "
226 << child_polygons[l].cols());
233 child_polygons[l].cols() == 2,
234 "child_polygons[l].cols() = " << child_polygons[l].cols());
235 child_geo_uptrs.push_back(std::make_unique<SegmentO1>(child_geo));
240 child_polygons[l].cols() == 1,
241 "child_polygons[l].cols() = " << child_polygons[l].cols());
242 child_geo_uptrs.push_back(std::make_unique<Point>(child_geo));
246 LF_VERIFY_MSG(
false,
"Illegal co-dimension");
251 return (child_geo_uptrs);
259 : coords_(std::move(coords)),
260 jacobian_(coords_.rows(), 2),
261 jacobian_inverse_gramian_(coords_.rows(), 2),
262 integrationElement_(0) {
269 "No parallelogram!");
274 const Eigen::VectorXd& p1,
275 const Eigen::VectorXd& p2)
276 : coords_(p0.rows(), 4),
277 jacobian_(p0.rows(), 2),
278 jacobian_inverse_gramian_(p0.rows(), 2),
279 integrationElement_(0) {
280 LF_ASSERT_MSG(p0.size() == p1.size(),
"Vector length mismatch p0 <-> p1");
281 LF_ASSERT_MSG(p0.size() == p2.size(),
"Vector length mismatch p0 <-> p2");
284 coords_.col(2) = p1 + (p2 - p0);
308 (1 - local.array().row(0) - local.array().row(1)).matrix() +
313 return jacobian_.replicate(1, local.cols());
317 const Eigen::MatrixXd& local)
const {
322 const Eigen::MatrixXd& local)
const {
329 using std::make_unique;
332 LF_ASSERT_MSG(i == 0,
"i is out of bounds.");
333 return std::make_unique<Parallelogram>(
coords_);
335 LF_ASSERT_MSG(i >= 0 && i < 4,
"i is out of bounds.");
336 return make_unique<SegmentO1>(
337 (Eigen::Matrix<double, Eigen::Dynamic, 2>(
DimGlobal(), 2)
338 <<
coords_.col(
RefEl().SubSubEntity2SubEntity(1, i, 1, 0)),
339 coords_.col(
RefEl().SubSubEntity2SubEntity(1, i, 1, 1)))
342 LF_ASSERT_MSG(i >= 0 && i < 4,
"i is out of bounds.");
343 return make_unique<Point>(
coords_.col(i));
345 LF_VERIFY_MSG(
false,
"codim is out of bounds.");
358 LF_VERIFY_MSG(codim < 3,
"Illegal codim " << codim);
361 const double h_lattice = 1.0 /
static_cast<double>(ref_pat.
LatticeConst());
363 std::vector<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic>>
370 "no_children = " << no_children <<
" <-> " << ref_pat.
NumChildren(codim));
373 std::vector<std::unique_ptr<Geometry>> child_geo_uptrs{};
375 for (
int l = 0; l < no_children; l++) {
379 child_polygons[l].rows() == 2,
380 "child_polygons[" << l <<
"].rows() = " << child_polygons[l].rows());
383 const Eigen::MatrixXd child_geo(
384 Global(h_lattice * child_polygons[l].cast<double>()));
388 if (child_polygons[l].cols() == 3) {
390 child_geo_uptrs.push_back(std::make_unique<TriaO1>(child_geo));
391 }
else if (child_polygons[l].cols() == 4) {
400 child_geo_uptrs.push_back(
401 std::make_unique<Parallelogram>(child_geo));
404 child_geo_uptrs.push_back(std::make_unique<QuadO1>(child_geo));
407 LF_VERIFY_MSG(
false,
"child_polygons[" << l <<
"].cols() = "
408 << child_polygons[l].cols());
415 child_polygons[l].cols() == 2,
416 "child_polygons[l].cols() = " << child_polygons[l].cols());
417 child_geo_uptrs.push_back(std::make_unique<SegmentO1>(child_geo));
422 child_polygons[l].cols() == 1,
423 "child_polygons[l].cols() = " << child_polygons[l].cols());
424 child_geo_uptrs.push_back(std::make_unique<Point>(child_geo));
428 LF_VERIFY_MSG(
false,
"Illegal co-dimension");
433 return (child_geo_uptrs);
static constexpr RefEl kQuad()
Returns the reference quadrilateral.
std::string ToString() const
Return a string representation of this Reference element.
std::unique_ptr< Geometry > SubGeometry(dim_t codim, dim_t i) const override
Construct a new Geometry() object that describes the geometry of the i-th sub-entity with codimension...
double integrationElement_
constant Gramian determinant
Eigen::Matrix< double, Eigen::Dynamic, 2 > jacobian_inverse_gramian_
Constant matrix ( )
Eigen::MatrixXd Global(const Eigen::MatrixXd &local) const override
Map a number of points in local coordinates into the global coordinate system.
Eigen::MatrixXd JacobianInverseGramian(const Eigen::MatrixXd &local) const override
Evaluate the Jacobian * Inverse Gramian ( ) simultaneously at numPoints.
Eigen::Matrix< double, Eigen::Dynamic, 2 > jacobian_
Matrix of affine mapping generating the parallelogram, agrees with constant Jacobian.
dim_t DimGlobal() const override
Dimension of the image of this mapping.
Eigen::VectorXd IntegrationElement(const Eigen::MatrixXd &local) const override
The integration element (factor appearing in integral transformation formula, see below) at number of...
Eigen::Matrix< double, Eigen::Dynamic, 4 > coords_
Coordinates of the a four vertices, stored in matrix columns.
Parallelogram(Eigen::Matrix< double, Eigen::Dynamic, 4 > coords)
Constructor building a parallelogram from four vertex coordinates.
Eigen::MatrixXd Jacobian(const Eigen::MatrixXd &local) const override
Evaluate the jacobian of the mapping simultaneously at numPoints points.
base::RefEl RefEl() const override
The Reference element that defines the domain of this mapping.
std::vector< std::unique_ptr< Geometry > > ChildGeometry(const RefinementPattern &ref_pat, lf::base::dim_t codim) const override
Generate geometry objects for child entities created in the course of refinement.
void init()
performs initialization of data members
Eigen::MatrixXd Global(const Eigen::MatrixXd &local) const override
Map a number of points in local coordinates into the global coordinate system.
std::unique_ptr< Geometry > SubGeometry(dim_t codim, dim_t i) const override
Construct a new Geometry() object that describes the geometry of the i-th sub-entity with codimension...
Eigen::VectorXd IntegrationElement(const Eigen::MatrixXd &local) const override
The integration element (factor appearing in integral transformation formula, see below) at number of...
QuadO1(Eigen::Matrix< double, Eigen::Dynamic, 4 > coords)
Constructor building quadrilateral from vertex coordinates.
Eigen::MatrixXd JacobianInverseGramian(const Eigen::MatrixXd &local) const override
Evaluate the Jacobian * Inverse Gramian ( ) simultaneously at numPoints.
Eigen::MatrixXd Jacobian(const Eigen::MatrixXd &local) const override
Evaluate the jacobian of the mapping simultaneously at numPoints points.
dim_t DimGlobal() const override
Dimension of the image of this mapping.
std::vector< std::unique_ptr< Geometry > > ChildGeometry(const RefinementPattern &ref_pat, lf::base::dim_t codim) const override
Generate geometry objects for child entities created in the course of refinement.
base::RefEl RefEl() const override
The Reference element that defines the domain of this mapping.
Eigen::Matrix< double, Eigen::Dynamic, 4 > coords_
Coordinates of the a four vertices, stored in matrix columns.
Abstract interface class for encoding topological local refinement
lf::base::size_type LatticeConst() const
Provides information about lattice constant used.
virtual lf::base::size_type NumChildren(lf::base::dim_t codim) const =0
provide number of child entities of a given co-dimension to be created by refinement
virtual std::vector< Eigen::Matrix< int, Eigen::Dynamic, Eigen::Dynamic > > ChildPolygons(lf::base::dim_t codim) const =0
provide lattice reference coordinates of vertices of child polygons
lf::base::RefEl RefEl() const
Returns topological type of entity for which the current object is set up.
unsigned int size_type
general type for variables related to size of arrays
unsigned int dim_t
type for dimensions and co-dimensions and numbers derived from them
Defines the Geometry interface and provides a number of classes that implement this interface + addit...
bool assertNonDegenerateQuad(const Eigen::Matrix< double, Eigen::Dynamic, 4 > &coords, double tol)
Asserting a non-degenerate bilinear quadrilateral.
bool isParallelogram(const Eigen::Matrix< int, Eigen::Dynamic, Eigen::Dynamic > &polygon)
Test whether a lattice polygon describes a logical parallelogram.