1 #ifndef DUNE_FEM_FUNCTION_LOCALFUNCTION_LOCALFUNCTION_HH 2 #define DUNE_FEM_FUNCTION_LOCALFUNCTION_LOCALFUNCTION_HH 3 4 #include <utility> 5 #include <type_traits> 6 #include <tuple> 7 8 #include <dune/common/deprecated.hh> 9 #include <dune/common/fvector.hh> 10 11 12 namespace Dune 13 { 14 namespace Fem { 15 // forward declaration for DenseMatVecTraits 16 template< class BasisFunctionSet, class LocalDofVector > 17 class LocalFunction; 18 } 19 20 21 // DenseMatVecTraits for LocalFunction for Discrete Functions 22 // ---------------------------------------------------------- 23 24 template< class BasisFunctionSet, class LocalDofVector > 25 struct DenseMatVecTraits< Fem::LocalFunction< BasisFunctionSet, LocalDofVector > > 26 { 27 typedef Fem::LocalFunction< BasisFunctionSet, LocalDofVector > derived_type; 28 typedef typename LocalDofVector::value_type value_type; 29 //typedef LocalDofVector container_type; 30 typedef typename LocalDofVector::size_type size_type; 31 }; 32 33 34 35 // FieldTraits for LocalContribution for Discrete Functions 36 // -------------------------------------------------------- 37 38 template< class BasisFunctionSet, class LocalDofVector > 39 struct FieldTraits< Fem::LocalFunction< BasisFunctionSet, LocalDofVector > > 40 { 41 typedef typename FieldTraits< typename LocalDofVector::value_type >::field_type field_type; 42 typedef typename FieldTraits< typename LocalDofVector::value_type >::real_type real_type; 43 }; 44 45 46 namespace Fem 47 { 48 49 /** \addtogroup LocalFunction 50 * 51 * On every element from a discrete function the local funtion can be 52 * accessed. With the local function one has access to the dof and on the 53 * other hand to the basis function set of this actual element. Therefore 54 * this is called a local function. 55 * 56 * \remarks The interface for using a LocalFunction is defined by the class 57 * LocalFunction. 58 * 59 * \{ 60 */ 61 62 63 64 // LocalFunction 65 // ------------- 66 67 /** \class LocalFunction 68 * \brief interface for local functions 69 * 70 * Local functions are used to represend a discrete function on one entity. 71 * The LocalFunctionInterface defines the functionality that can be expected 72 * from such a local function. 73 */ 74 template< class BasisFunctionSet, class LocalDofVector > 75 class LocalFunction 76 : public Dune::DenseVector< LocalFunction< BasisFunctionSet, LocalDofVector > > 77 { 78 typedef LocalFunction< BasisFunctionSet, LocalDofVector > ThisType; 79 typedef Dune::DenseVector< ThisType > BaseType; 80 public: 81 82 //! type of basis function set 83 typedef BasisFunctionSet BasisFunctionSetType; 84 85 /** \brief type of local Dof Vector */ 86 typedef LocalDofVector LocalDofVectorType; 87 88 //! type of DoF use with the discrete function 89 typedef typename LocalDofVectorType::value_type DofType; 90 91 //! type of index 92 typedef typename LocalDofVectorType::size_type SizeType; 93 94 //! type of the entity, the local function lives on is given by the space 95 typedef typename BasisFunctionSetType::EntityType EntityType; 96 97 //! type of functionspace 98 typedef typename BasisFunctionSetType::FunctionSpaceType FunctionSpaceType; 99 100 //! field type of the domain 101 typedef typename FunctionSpaceType::DomainFieldType DomainFieldType; 102 //! field type of the range 103 typedef typename FunctionSpaceType::RangeFieldType RangeFieldType; 104 //! type of domain vectors, i.e., type of coordinates 105 typedef typename FunctionSpaceType::DomainType DomainType; 106 //! type of range vectors, i.e., type of function values 107 typedef typename FunctionSpaceType::RangeType RangeType; 108 //! type of the Jacobian, i.e., type of evaluated Jacobian matrix 109 typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType; 110 //! type of the Hessian 111 typedef typename FunctionSpaceType::HessianRangeType HessianRangeType; 112 113 //! type of local coordinates 114 typedef typename EntityType::Geometry::LocalCoordinate LocalCoordinateType; 115 116 //! dimension of the domain 117 static const int dimDomain = FunctionSpaceType::dimDomain; 118 //! dimension of the range 119 static const int dimRange = FunctionSpaceType::dimRange; 120 121 //! default constructor, calls default ctor of BasisFunctionSetType and LocalDofVectorType LocalFunction()122 LocalFunction () {} 123 124 //! ctor taking a basisFunctionSet, calling default ctor for LocalDofVectorType, and resize LocalFunction(const BasisFunctionSetType & basisFunctionSet)125 explicit LocalFunction ( const BasisFunctionSetType &basisFunctionSet ) 126 : basisFunctionSet_( basisFunctionSet ) 127 { 128 localDofVector_.resize( basisFunctionSet.size() ); 129 } 130 131 //! ctor taking a localDofVector, calling default ctor for BasisFunctionSetType LocalFunction(const LocalDofVectorType & localDofVector)132 explicit LocalFunction ( const LocalDofVectorType &localDofVector ) : localDofVector_( localDofVector ) {} 133 134 //! copy given agruments LocalFunction(const BasisFunctionSetType & basisFunctionSet,const LocalDofVector & localDofVector)135 LocalFunction ( const BasisFunctionSetType &basisFunctionSet, const LocalDofVector &localDofVector ) 136 : basisFunctionSet_( basisFunctionSet ), 137 localDofVector_( localDofVector ) 138 { 139 localDofVector_.resize( basisFunctionSet.size() ); 140 } 141 142 //! half move ctor LocalFunction(LocalDofVectorType && localDofVector)143 explicit LocalFunction ( LocalDofVectorType &&localDofVector ) : localDofVector_( localDofVector ) {} 144 145 //! half move ctor LocalFunction(const BasisFunctionSetType & basisFunctionSet,LocalDofVector && localDofVector)146 LocalFunction ( const BasisFunctionSetType &basisFunctionSet, LocalDofVector &&localDofVector ) 147 : basisFunctionSet_( basisFunctionSet ), 148 localDofVector_( localDofVector ) 149 { 150 localDofVector_.resize( basisFunctionSet.size() ); 151 } 152 153 //! move constructor LocalFunction(ThisType && other)154 LocalFunction ( ThisType && other ) 155 : basisFunctionSet_( std::move( other.basisFunctionSet_ ) ), 156 localDofVector_( std::move( other.localDofVector_ ) ) 157 {} 158 159 //! copy constructor LocalFunction(const ThisType & other)160 LocalFunction ( const ThisType & other ) 161 : basisFunctionSet_( other.basisFunctionSet_ ), 162 localDofVector_( other.localDofVector_ ) 163 {} 164 165 /** \brief access to local dofs (read-only) 166 * 167 * \param[in] num local dof number 168 * \return reference to dof 169 */ operator [](SizeType num) const170 const DofType &operator[] ( SizeType num ) const { return localDofVector_[ num ]; } 171 172 /** \brief access to local dofs (read-write) 173 * 174 * \param[in] num local DoF number 175 * \return reference to DoF 176 */ operator [](SizeType num)177 DofType &operator[] ( SizeType num ) { return localDofVector_[ num ]; } 178 179 using BaseType :: operator +=; 180 using BaseType :: operator -=; 181 using BaseType :: operator *=; 182 using BaseType :: operator /=; 183 184 /** \brief assign all DoFs of this local function 185 * 186 * \param[in] lf local function to assign DoFs from 187 */ 188 template< class T > assign(const LocalFunction<BasisFunctionSet,T> & other)189 void assign ( const LocalFunction< BasisFunctionSet, T > &other ) 190 { 191 localDofVector() = other.localDofVector(); 192 } 193 194 /** \brief set all DoFs to zero */ clear()195 void clear () 196 { 197 std::fill( localDofVector().begin(), localDofVector().end(), DofType( 0 ) ); 198 } 199 200 #if 0 201 /** \brief add a multiple of another local function to this one 202 * 203 * \note The local function to add may be any implementation of a 204 * LocalFunction. 205 * 206 * \param[in] s scalar factor to scale lf with 207 * \param[in] lf local function to add 208 * 209 * \returns a reference to this local function (i.e., *this) 210 */ 211 template< class T > 212 ThisType &axpy ( const RangeFieldType s, const LocalFunction< BasisFunctionSet, T > &other ) 213 { 214 localDofVector().axpy( s, other.localDofVector() ); 215 return *this; 216 } 217 #endif 218 using BaseType :: axpy; 219 220 /** \brief axpy operation for local function 221 * 222 * Denoting the DoFs of the local function by \f$u_i\f$ and the basis 223 * functions by \f$\varphi_i\f$, this function performs the following 224 * operation: 225 * \f[ 226 * u_i = u_i + factor \cdot \varphi_i( x ) 227 * \f] 228 * 229 * \param[in] x point to evaluate basis functions in 230 * \param[in] factor axpy factor 231 */ 232 template< class PointType > axpy(const PointType & x,const RangeType & factor)233 void axpy ( const PointType &x, const RangeType &factor ) 234 { 235 basisFunctionSet().axpy( x, factor, localDofVector() ); 236 } 237 238 /** \brief axpy operation for local function 239 * 240 * Denoting the DoFs of the local function by \f$u_i\f$ and the basis 241 * functions by \f$\varphi_i\f$, this function performs the following 242 * operation: 243 * \f[ 244 * u_i = u_i + factor \cdot \nabla\varphi_i( x ) 245 * \f] 246 * 247 * \param[in] x point to evaluate jacobian of basis functions in 248 * \param[in] factor axpy factor 249 */ 250 template< class PointType > axpy(const PointType & x,const JacobianRangeType & factor)251 void axpy ( const PointType &x, const JacobianRangeType &factor) 252 { 253 basisFunctionSet().axpy( x, factor, localDofVector() ); 254 } 255 template< class PointType > axpy(const PointType & x,const HessianRangeType & factor)256 void axpy ( const PointType &x, const HessianRangeType &factor) 257 { 258 basisFunctionSet().axpy( x, factor, localDofVector() ); 259 } 260 261 /** \brief axpy operation for local function 262 * 263 * Denoting the DoFs of the local function by \f$u_i\f$ and the basis 264 * functions by \f$\varphi_i\f$, this function performs the following 265 * operation: 266 * \f[ 267 * u_i = u_i + factor1 \cdot \varphi_i( x ) + factor2 \cdot \nabla\varphi_i( x ) 268 * \f] 269 * 270 * \param[in] x point to evaluate basis functions in 271 * \param[in] factor1 axpy factor for \f$\varphi( x )\f$ 272 * \param[in] factor2 axpy factor for \f$\nabla\varphi( x )\f$ 273 */ 274 template< class PointType > axpy(const PointType & x,const RangeType & factor1,const JacobianRangeType & factor2)275 void axpy ( const PointType &x, const RangeType &factor1, const JacobianRangeType &factor2 ) 276 { 277 basisFunctionSet().axpy( x, factor1, factor2, localDofVector() ); 278 } 279 280 /** \brief obtain the order of this local function 281 * 282 * The order of a local function refers to the polynomial order required 283 * to integrate it exactly. 284 * 285 * \note It is not completely clear what this value should be, e.g., for 286 * bilinear basis functions. 287 * 288 * \returns order of the local function 289 */ order() const290 int order () const { return basisFunctionSet().order(); } 291 292 /** \brief obtain the basis function set for this local function 293 * 294 * \returns reference to the basis function set 295 */ basisFunctionSet() const296 const BasisFunctionSetType &basisFunctionSet () const { return basisFunctionSet_; } 297 298 /** \brief obtain the entity, this local function lives on 299 * 300 * \returns reference to the entity 301 */ entity() const302 const EntityType &entity () const { return basisFunctionSet().entity(); } 303 304 305 /** \brief evaluate the local function 306 * 307 * \param[in] x evaluation point in local coordinates 308 * \param[out] ret value of the function in the given point 309 */ 310 template< class PointType > evaluate(const PointType & x,RangeType & ret) const311 void evaluate ( const PointType &x, RangeType &ret ) const 312 { 313 basisFunctionSet().evaluateAll( x, localDofVector(), ret ); 314 } 315 316 /** \brief evaluate Jacobian of the local function 317 * 318 * \note Though the Jacobian is evaluated on the reference element, the 319 * return value is the Jacobian with respect to the actual entity. 320 * 321 * \param[in] x evaluation point in local coordinates 322 * \param[out] ret Jacobian of the function in the evaluation point 323 */ 324 template< class PointType > jacobian(const PointType & x,JacobianRangeType & ret) const325 void jacobian ( const PointType &x, JacobianRangeType &ret ) const 326 { 327 basisFunctionSet().jacobianAll( x, localDofVector(), ret ); 328 } 329 330 /** \brief evaluate Hessian of the local function 331 * 332 * \note Though the Hessian is evaluated on the reference element, the 333 * return value is the Hessian with respect to the actual entity. 334 * 335 * \param[in] x evaluation point in local coordinates 336 * \param[out] ret Hessian of the function in the evaluation point 337 */ 338 template< class PointType > hessian(const PointType & x,HessianRangeType & ret) const339 void hessian ( const PointType &x, HessianRangeType &ret ) const 340 { 341 basisFunctionSet().hessianAll( x, localDofVector(), ret ); 342 } 343 344 /** \brief obtain the number of local DoFs 345 * 346 * Obtain the number of local DoFs of this local function. The value is 347 * identical to the number of basis functons on the entity. 348 * 349 * \returns number of local DoFs 350 */ numDofs() const351 int numDofs () const { return localDofVector().size(); } 352 353 /** \brief obtain the number of local DoFs 354 * 355 * Obtain the number of local DoFs of this local function. The value is 356 * identical to the number of basis functons on the entity. 357 * 358 * \returns number of local DoFs 359 */ size() const360 SizeType size () const { return localDofVector().size(); } 361 362 /** \brief evaluate all basisfunctions for all quadrature points, multiply with the given factor and 363 add the result to the local coefficients */ 364 template< class QuadratureType, class ... Vectors > axpyQuadrature(const QuadratureType & quad,const Vectors &...values)365 void axpyQuadrature ( const QuadratureType &quad, const Vectors& ... values ) 366 { 367 static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." ); 368 std::ignore = 369 std::make_tuple( ( basisFunctionSet().axpy( quad, values, localDofVector() ), 1 )...); 370 } 371 372 /** \brief evaluate all basisfunctions for all quadrature points, multiply with the given factor and 373 add the result to the local coefficients */ 374 template< class QuadratureType, class RangeVectorType, class JacobianRangeVectorType > axpyQuadrature(const QuadratureType & quad,const RangeVectorType & rangeVector,const JacobianRangeVectorType & jacobianVector)375 void axpyQuadrature ( const QuadratureType &quad, 376 const RangeVectorType& rangeVector, 377 const JacobianRangeVectorType& jacobianVector ) 378 { 379 basisFunctionSet().axpy( quad, rangeVector, jacobianVector, localDofVector() ); 380 } 381 382 /** \brief evaluate all basisfunctions for all quadrature points and store the results in the result vector */ 383 template< class QuadratureType, class ... Vectors > evaluateQuadrature(const QuadratureType & quad,Vectors &...vec) const384 void evaluateQuadrature( const QuadratureType &quad, Vectors& ... vec ) const 385 { 386 static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." ); 387 std::ignore = 388 std::make_tuple( ( evaluateQuadrature( quad, vec, typename std::decay< decltype( vec[ 0 ] ) >::type() ), 1 ) 389 ... ); 390 } 391 392 /** \brief evaluate all Jacobians for all basis functions for all quadrature points and 393 * store the results in the result vector */ 394 template< class QuadratureType, class ... Vectors > jacobianQuadrature(const QuadratureType & quad,Vectors &...vec) const395 void jacobianQuadrature( const QuadratureType &quad, Vectors& ... vec ) const 396 { 397 static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." ); 398 std::ignore = 399 std::make_tuple( ( evaluateQuadrature( quad, vec, typename std::decay< decltype( vec[ 0 ] ) >::type() ), 1 ) 400 ... ); 401 } 402 403 /** \brief evaluate all hessians of all basis functions for all quadrature points and store the results in the result vector */ 404 template< class QuadratureType, class ... Vectors > hessianQuadrature(const QuadratureType & quad,Vectors &...vec) const405 void hessianQuadrature( const QuadratureType &quad, Vectors& ... vec ) const 406 { 407 // make sure vec size if large enough 408 static_assert( sizeof...( Vectors ) > 0, "evaluateQuadrature needs to be called with at least one vector." ); 409 std::ignore = 410 std::make_tuple( ( evaluateQuadrature( quad, vec, typename std::decay< decltype( vec[ 0 ] ) >::type() ), 1 ) 411 ... ); 412 } 413 414 /** \brief return const reference to local Dof Vector */ localDofVector() const415 const LocalDofVectorType &localDofVector () const { return localDofVector_; } 416 417 /** \brief return mutable reference to local Dof Vector */ localDofVector()418 LocalDofVectorType &localDofVector () { return localDofVector_; } 419 420 421 /** \brief Returns true if local function if bind or init was previously called. 422 */ valid() const423 bool valid () const 424 { 425 return basisFunctionSet_.valid(); 426 } 427 428 protected: 429 /** \brief initialize the local function for an entity 430 * 431 Binds the local function to an basisFunctionSet and entity. 432 433 \note Must be overloaded on the derived implementation class. 434 435 \param[in] entity to bind the local function to 436 */ init(const EntityType & entity)437 void init ( const EntityType& entity ) 438 { 439 DUNE_THROW(NotImplemented,"LocalFunction::init( entity ) must be overloaded on derived class!"); 440 } 441 442 /** \brief initialize the local function for an entity 443 * 444 Binds the local function to an basisFunctionSet and entity. 445 446 \note Must be overloaded on the derived implementation class. 447 448 \param[in] entity to bind the local function to 449 */ bind(const EntityType & entity)450 void bind ( const EntityType& entity ) 451 { 452 DUNE_THROW(NotImplemented,"LocalFunction::bind( entity ) must be overloaded on derived class!"); 453 } 454 455 /** \brief clears the local function by removing the basisFunctionSet 456 * 457 */ unbind()458 void unbind () 459 { 460 // basically sets entity pointer inside basis function set to nullptr 461 basisFunctionSet_ = BasisFunctionSetType(); 462 } 463 464 /** \brief initialize the local function for an basisFunctionSet 465 * 466 Binds the local function to an basisFunctionSet and entity. 467 468 \note A local function must be initialized to an entity before it can 469 be used. 470 471 \note This function can be called multiple times to use the local 472 function for more than one entity. 473 474 \param[in] basisFunctionSet to bind the local function to 475 */ init(const BasisFunctionSetType & basisFunctionSet)476 void init ( const BasisFunctionSetType &basisFunctionSet ) 477 { 478 basisFunctionSet_ = basisFunctionSet; 479 localDofVector_.resize( basisFunctionSet.size() ); 480 } 481 482 // evaluate local function and store results in vector of RangeTypes 483 // this method only helps to identify the correct method on 484 // the basis function set 485 template< class QuadratureType, class VectorType > evaluateQuadrature(const QuadratureType & quad,VectorType & result,const RangeType &) const486 void evaluateQuadrature( const QuadratureType &quad, VectorType &result, const RangeType & ) const 487 { 488 basisFunctionSet().evaluateAll( quad, localDofVector(), result ); 489 } 490 491 // evaluate jacobian of local function and store result in vector of 492 // JacobianRangeTypes, this method only helps to identify the correct method on 493 // the basis function set 494 template< class QuadratureType, class VectorType > evaluateQuadrature(const QuadratureType & quad,VectorType & result,const JacobianRangeType &) const495 void evaluateQuadrature( const QuadratureType &quad, VectorType &result, const JacobianRangeType & ) const 496 { 497 basisFunctionSet().jacobianAll( quad, localDofVector(), result ); 498 } 499 500 // evaluate jacobian of local function and store result in vector of 501 // JacobianRangeTypes, this method only helps to identify the correct method on 502 // the basis function set 503 template< class QuadratureType, class VectorType > evaluateQuadrature(const QuadratureType & quad,VectorType & result,const HessianRangeType &) const504 void evaluateQuadrature( const QuadratureType &quad, VectorType &result, const HessianRangeType & ) const 505 { 506 basisFunctionSet().hessianAll( quad, localDofVector(), result ); 507 } 508 509 BasisFunctionSetType basisFunctionSet_; 510 LocalDofVectorType localDofVector_; 511 }; 512 513 /** \} */ 514 515 } // end namespace Fem 516 517 } // end namespace Dune 518 519 #endif // #ifndef DUNE_FEM_FUNCTION_LOCALFUNCTION_LOCALFUNCTION_HH 520