21 #ifndef bempp_concrete_geometry_hpp
22 #define bempp_concrete_geometry_hpp
24 #include "../common/common.hpp"
26 #include "geometry.hpp"
30 #include "../common/not_implemented_error.hpp"
31 #include "../fiber/geometrical_data.hpp"
32 #include <dune/common/fvector.hh>
33 #include <dune/common/fmatrix.hh>
34 #include <dune/common/static_assert.hh>
35 #include <dune/grid/common/grid.hh>
37 #include "../common/armadillo_fwd.hpp"
44 template <
typename DuneGeometry>
class ConcreteGeometryFactory;
50 template <
typename DuneGeometry>
51 DuneGeometry setupDuneGeometry(
53 const std::vector<Dune::FieldVector<double, DuneGeometry::dimensionworld> >& corners)
55 throw std::runtime_error(
"setupDuneGeometry() is only supported for a "
56 "small number of Dune geometry classes");
60 Default2dIn3dDuneGrid::Codim<0>::Geometry
61 setupDuneGeometry<Default2dIn3dDuneGrid::Codim<0>::Geometry>(
63 const std::vector<Dune::FieldVector<double, 3> >& corners)
65 return Default2dIn3dDuneGrid::Codim<0>::Geometry(
66 Dune::FoamGridGeometry<2, 3,
const Dune::FoamGrid<3> >(type, corners));
71 template <
typename DuneGeometry>
74 dune_static_assert((
int)DuneGeometry::coorddimension ==
75 (
int)DuneGeometry::dimensionworld,
76 "ConcreteGeometry: world dimension does not agree with "
77 "number of coordinates");
80 std::auto_ptr<DuneGeometry> m_dune_geometry;
82 void setDuneGeometry(
const DuneGeometry& dune_geometry) {
83 m_dune_geometry.reset(
new DuneGeometry(dune_geometry));
88 template<
int codim,
typename DuneEntity>
friend class ConcreteEntity;
94 m_dune_geometry(new DuneGeometry(dune_geometry)) {}
98 return m_dune_geometry;
104 return m_dune_geometry.get();
109 m_dune_geometry.reset();
113 return DuneGeometry::mydimension;
117 return DuneGeometry::coorddimension;
120 virtual void setupImpl(
const arma::Mat<double>& corners,
121 const arma::Col<char>& auxData) {
122 const int dimWorld = DuneGeometry::coorddimension;
124 assert((
int)corners.n_rows == dimWorld);
127 if (DuneGeometry::mydimension == 0) {
128 assert(cornerCount == 1);
131 else if (DuneGeometry::mydimension == 1) {
132 assert(cornerCount == 2);
135 else if (DuneGeometry::mydimension == 2) {
136 assert (cornerCount == 3 || cornerCount == 4);
137 if (cornerCount == 3)
140 type.makeQuadrilateral();
143 throw NotImplementedError(
"ConcreteGeometry::setup(): "
144 "not implemented yet for 3D entities");
146 std::vector<Dune::FieldVector<double, dimWorld> > duneCorners(cornerCount);
147 for (
size_t i = 0; i < corners.n_cols; ++i)
149 duneCorners[i][j] = corners(j, i);
151 typedef Dune::MakeableInterfaceObject<DuneGeometry> DuneMakeableGeometry;
152 typedef typename DuneMakeableGeometry::ImplementationType DuneGeometryImp;
154 m_dune_geometry.reset(
156 setupDuneGeometry<DuneGeometry>(type, duneCorners)));
160 return m_dune_geometry->type();
164 return m_dune_geometry->affine();
168 return m_dune_geometry->corners();
171 virtual void getCornersImpl(arma::Mat<double>& c)
const {
172 const int cdim = DuneGeometry::dimensionworld;
173 const int n = m_dune_geometry->corners();
179 typename DuneGeometry::GlobalCoordinate g;
180 for (
int j = 0; j < n; ++j) {
181 g = m_dune_geometry->corner(j);
182 for (
int i = 0; i < cdim; ++i)
187 virtual void local2globalImpl(
const arma::Mat<double>& local,
188 arma::Mat<double>& global)
const {
189 const int mdim = DuneGeometry::mydimension;
190 const int cdim = DuneGeometry::coorddimension;
192 if ((
int)local.n_rows != mdim)
193 throw std::invalid_argument(
"Geometry::local2global(): invalid "
194 "dimensions of the 'local' array");
196 const size_t n = local.n_cols;
197 global.set_size(cdim, n);
200 typename DuneGeometry::GlobalCoordinate g;
201 typename DuneGeometry::LocalCoordinate l;
202 for (
size_t j = 0; j < n; ++j) {
203 for (
int i = 0; i < mdim; ++i)
205 g = m_dune_geometry->global(l);
206 for (
int i = 0; i < cdim; ++i)
211 virtual void global2localImpl(
const arma::Mat<double>& global,
212 arma::Mat<double>& local)
const {
213 const int mdim = DuneGeometry::mydimension;
214 const int cdim = DuneGeometry::coorddimension;
216 if ((
int)global.n_rows != cdim)
217 throw std::invalid_argument(
"Geometry::global2local(): invalid "
218 "dimensions of the 'global' array");
220 const size_t n = global.n_cols;
221 local.set_size(mdim, n);
224 typename DuneGeometry::GlobalCoordinate g;
225 typename DuneGeometry::LocalCoordinate l;
226 for (
size_t j = 0; j < n; ++j) {
227 for (
int i = 0; i < cdim; ++i)
229 l = m_dune_geometry->local(g);
230 for (
int i = 0; i < mdim; ++i)
235 virtual void getIntegrationElementsImpl(
const arma::Mat<double>& local,
236 arma::Row<double>& int_element)
const {
237 const int mdim = DuneGeometry::mydimension;
239 if ((
int)local.n_rows != mdim)
240 throw std::invalid_argument(
"Geometry::local2global(): invalid "
241 "dimensions of the 'local' array");
243 const size_t n = local.n_cols;
244 int_element.set_size(n);
247 typename DuneGeometry::LocalCoordinate l;
248 for (
size_t j = 0; j < n; ++j) {
249 for (
int i = 0; i < mdim; ++i)
251 double ie = m_dune_geometry->integrationElement(l);
257 return m_dune_geometry->volume();
260 virtual void getCenterImpl(arma::Col<double>& c)
const {
261 const int cdim = DuneGeometry::coorddimension;
265 typename DuneGeometry::GlobalCoordinate g = m_dune_geometry->center();
266 for (
int i = 0; i < cdim; ++i)
270 virtual void getJacobiansTransposedImpl(
const arma::Mat<double>& local,
272 const int mdim = DuneGeometry::mydimension;
273 const int cdim = DuneGeometry::coorddimension;
275 if ((
int)local.n_rows != mdim)
276 throw std::invalid_argument(
"Geometry::getJacobiansTransposed(): "
277 "invalid dimensions of the 'local' array");
279 const size_t n = local.n_cols;
280 jacobian_t.set_size(mdim, cdim, n);
286 typename DuneGeometry::JacobianTransposed j_t;
287 typename DuneGeometry::LocalCoordinate l;
288 for (
size_t k = 0; k < n; ++k) {
290 for (
int i = 0; i < mdim; ++i)
292 j_t = m_dune_geometry->jacobianTransposed(l);
293 for (
int j = 0; j < cdim; ++j)
294 for (
int i = 0; i < mdim; ++i)
295 jacobian_t(i,j,k) = j_t[i][j];
300 const arma::Mat<double>& local,
302 const int mdim = DuneGeometry::mydimension;
303 const int cdim = DuneGeometry::coorddimension;
305 if ((
int)local.n_rows != mdim)
306 throw std::invalid_argument(
"Geometry::getJacobianInversesTransposed(): "
307 "invalid dimensions of the 'local' array");
309 const size_t n = local.n_cols;
310 jacobian_inv_t.set_size(cdim, mdim, n);
316 typename DuneGeometry::Jacobian j_inv_t;
317 typename DuneGeometry::LocalCoordinate l;
318 for (
size_t k = 0; k < n; ++k) {
320 for (
int i = 0; i < mdim; ++i)
322 j_inv_t = m_dune_geometry->jacobianInverseTransposed(l);
323 for (
int j = 0; j < mdim; ++j)
324 for (
int i = 0; i < cdim; ++i)
325 jacobian_inv_t(i,j,k) = j_inv_t[i][j];
329 virtual void getNormalsImpl(
const arma::Mat<double>& local,
330 arma::Mat<double>& normal)
const {
333 calculateNormals(jacobian_t, normal);
336 virtual void getDataImpl(
size_t what,
const arma::Mat<double>& local,
342 typedef ConcreteGeometry<DuneGeometry> This;
344 if (what & Fiber::GLOBALS)
345 This::local2global(local, data.globals);
346 if (what & Fiber::INTEGRATION_ELEMENTS)
347 This::getIntegrationElements(local, data.integrationElements);
348 if (what & Fiber::JACOBIANS_TRANSPOSED || what & Fiber::NORMALS)
349 This::getJacobiansTransposed(local, data.jacobiansTransposed);
350 if (what & Fiber::JACOBIAN_INVERSES_TRANSPOSED)
351 This::getJacobianInversesTransposed(
352 local, data.jacobianInversesTransposed);
353 if (what & Fiber::NORMALS)
354 calculateNormals(data.jacobiansTransposed, data.normals);
359 arma::Mat<double>& normals)
const {
360 const int mdim = DuneGeometry::mydimension;
361 const int cdim = DuneGeometry::coorddimension;
363 if (mdim != cdim - 1)
364 throw std::logic_error(
"ConcreteGeometry::calculateNormals(): "
365 "normal vectors are defined only for "
366 "entities of dimension (worldDimension - 1)");
368 const size_t pointCount = jt.extent(2);
369 normals.set_size(cdim, pointCount);
375 for (
size_t i = 0; i < pointCount; ++i) {
376 normals(0,i) = jt(0,1,i) * jt(1,2,i) - jt(0,2,i) * jt(1,1,i);
377 normals(1,i) = jt(0,2,i) * jt(1,0,i) - jt(0,0,i) * jt(1,2,i);
378 normals(2,i) = jt(0,0,i) * jt(1,1,i) - jt(0,1,i) * jt(1,0,i);
381 for (
size_t i = 0; i < pointCount; ++i) {
382 normals(0,i) = jt(0,1,i);
383 normals(1,i) = jt(0,0,i);
386 for (
size_t i = 0; i < pointCount; ++i)
389 throw std::runtime_error(
"ConcreteGeometry::calculateNormals(): "
390 "Normal vector is not defined for "
391 "zero-dimensional space");
395 for (
size_t i = 0; i < pointCount; ++i) {
398 sum += normals(
dim, i) * normals(
dim, i);
399 double invLength = 1. / sqrt(sum);
400 for (
size_t j = 0; j < cdim; ++j)
401 normals(j, i) *= invLength;
virtual int dimWorld() const
Dimension of the space containing the geometry.
Definition: concrete_geometry.hpp:116
Wrapper of a Dune geometry of type DuneGeometry.
Definition: concrete_geometry.hpp:72
Dune::GeometryType GeometryType
Identifier of geometry type.
Definition: geometry_type.hpp:34
void getJacobiansTransposed(const arma::Mat< double > &local, arma::Cube< double > &jacobian_t) const
Get transposed Jacobian matrices at specified points.
Definition: geometry_imp.hpp:118
virtual int dim() const
Dimension of the geometry.
Definition: concrete_geometry.hpp:112
Wrapper of a Dune entity of type DuneEntity and codimension codim.
Definition: concrete_entity_decl.hpp:46
virtual double volume() const
Volume of geometry.
Definition: concrete_geometry.hpp:256
Storage of geometrical data.
Definition: geometrical_data.hpp:54
virtual void getJacobianInversesTransposedImpl(const arma::Mat< double > &local, Fiber::_3dArray< double > &jacobian_inv_t) const
Definition: concrete_geometry.hpp:299
Factory able to construct an "empty" geometry wrapping a Dune geometry of type DuneGeometry.
Definition: concrete_geometry_factory.hpp:38
const DuneGeometry & duneGeometry() const
Read-only access to the underlying Dune geometry object.
Definition: concrete_geometry.hpp:97
ConcreteGeometry(const DuneGeometry &dune_geometry)
Constructor from a DuneGeometry object.
Definition: concrete_geometry.hpp:93
virtual bool affine() const
True if the geometry mapping is affine and false otherwise.
Definition: concrete_geometry.hpp:163
bool isInitialized() const
Return true if the Dune geometry object has already been set, false otherwise.
Definition: concrete_geometry.hpp:103
virtual GeometryType type() const
Type of the reference element.
Definition: concrete_geometry.hpp:159
void uninitialize()
Uninitialize the Dune geometry object.
Definition: concrete_geometry.hpp:108
virtual int cornerCount() const
Number of corners of the reference element.
Definition: concrete_geometry.hpp:167
Simple implementation of a 3D Fortran-ordered array.
Definition: _3d_array.hpp:48
Abstract wrapper of a geometry.
Definition: geometry.hpp:45