1 // Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced 2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files 3 // LICENSE and NOTICE for details. LLNL-CODE-806117. 4 // 5 // This file is part of the MFEM library. For more information and source code 6 // availability visit https://mfem.org. 7 // 8 // MFEM is free software; you can redistribute it and/or modify it under the 9 // terms of the BSD-3 license. We welcome feedback and contributions, see file 10 // CONTRIBUTING.md for details. 11 12 #ifndef MFEM_FE 13 #define MFEM_FE 14 15 #include "../config/config.hpp" 16 #include "../general/array.hpp" 17 #include "../linalg/linalg.hpp" 18 #include "intrules.hpp" 19 #include "geom.hpp" 20 21 #include <map> 22 23 namespace mfem 24 { 25 26 /// Possible basis types. Note that not all elements can use all BasisType(s). 27 class BasisType 28 { 29 public: 30 enum 31 { 32 Invalid = -1, 33 GaussLegendre = 0, ///< Open type 34 GaussLobatto = 1, ///< Closed type 35 Positive = 2, ///< Bernstein polynomials 36 OpenUniform = 3, ///< Nodes: x_i = (i+1)/(n+1), i=0,...,n-1 37 ClosedUniform = 4, ///< Nodes: x_i = i/(n-1), i=0,...,n-1 38 OpenHalfUniform = 5, ///< Nodes: x_i = (i+1/2)/n, i=0,...,n-1 39 Serendipity = 6, ///< Serendipity basis (squares / cubes) 40 ClosedGL = 7, ///< Closed GaussLegendre 41 IntegratedGLL = 8, ///< Integrated GLL indicator functions 42 NumBasisTypes = 9 /**< Keep track of maximum types to prevent 43 hard-coding */ 44 }; 45 /** @brief If the input does not represents a valid BasisType, abort with an 46 error; otherwise return the input. */ Check(int b_type)47 static int Check(int b_type) 48 { 49 MFEM_VERIFY(0 <= b_type && b_type < NumBasisTypes, 50 "unknown BasisType: " << b_type); 51 return b_type; 52 } 53 /** @brief If the input does not represents a valid nodal BasisType, abort 54 with an error; otherwise return the input. */ CheckNodal(int b_type)55 static int CheckNodal(int b_type) 56 { 57 MFEM_VERIFY(Check(b_type) != Positive && b_type != IntegratedGLL, 58 "invalid nodal BasisType: " << Name(b_type)); 59 return b_type; 60 } 61 /** @brief Get the corresponding Quadrature1D constant, when that makes 62 sense; otherwise return Quadrature1D::Invalid. */ GetQuadrature1D(int b_type)63 static int GetQuadrature1D(int b_type) 64 { 65 switch (b_type) 66 { 67 case GaussLegendre: return Quadrature1D::GaussLegendre; 68 case GaussLobatto: return Quadrature1D::GaussLobatto; 69 case Positive: return Quadrature1D::ClosedUniform; // <----- 70 case OpenUniform: return Quadrature1D::OpenUniform; 71 case ClosedUniform: return Quadrature1D::ClosedUniform; 72 case OpenHalfUniform: return Quadrature1D::OpenHalfUniform; 73 case Serendipity: return Quadrature1D::GaussLobatto; 74 case ClosedGL: return Quadrature1D::ClosedGL; 75 case IntegratedGLL: return Quadrature1D::GaussLegendre; 76 } 77 return Quadrature1D::Invalid; 78 } 79 /// Return the nodal BasisType corresponding to the Quadrature1D type. GetNodalBasis(int qpt_type)80 static int GetNodalBasis(int qpt_type) 81 { 82 switch (qpt_type) 83 { 84 case Quadrature1D::GaussLegendre: return GaussLegendre; 85 case Quadrature1D::GaussLobatto: return GaussLobatto; 86 case Quadrature1D::OpenUniform: return OpenUniform; 87 case Quadrature1D::ClosedUniform: return ClosedUniform; 88 case Quadrature1D::OpenHalfUniform: return OpenHalfUniform; 89 case Quadrature1D::ClosedGL: return ClosedGL; 90 } 91 return Invalid; 92 } 93 /// Check and convert a BasisType constant to a string identifier. Name(int b_type)94 static const char *Name(int b_type) 95 { 96 static const char *name[] = 97 { 98 "Gauss-Legendre", "Gauss-Lobatto", "Positive (Bernstein)", 99 "Open uniform", "Closed uniform", "Open half uniform", 100 "Serendipity", "Closed Gauss-Legendre", 101 "Integrated Gauss-Lobatto indicator" 102 }; 103 return name[Check(b_type)]; 104 } 105 /// Check and convert a BasisType constant to a char basis identifier. GetChar(int b_type)106 static char GetChar(int b_type) 107 { 108 static const char ident[] 109 = { 'g', 'G', 'P', 'u', 'U', 'o', 'S', 'c', 'i' }; 110 return ident[Check(b_type)]; 111 } 112 /// Convert char basis identifier to a BasisType constant. GetType(char b_ident)113 static int GetType(char b_ident) 114 { 115 switch (b_ident) 116 { 117 case 'g': return GaussLegendre; 118 case 'G': return GaussLobatto; 119 case 's': return GaussLobatto; 120 case 'P': return Positive; 121 case 'u': return OpenUniform; 122 case 'U': return ClosedUniform; 123 case 'o': return OpenHalfUniform; 124 case 'S': return Serendipity; 125 case 'c': return ClosedGL; 126 case 'i': return IntegratedGLL; 127 } 128 MFEM_ABORT("unknown BasisType identifier"); 129 return -1; 130 } 131 }; 132 133 134 /** @brief Structure representing the matrices/tensors needed to evaluate (in 135 reference space) the values, gradients, divergences, or curls of a 136 FiniteElement at a the quadrature points of a given IntegrationRule. */ 137 /** Object of this type are typically created and owned by the respective 138 FiniteElement object. */ 139 class DofToQuad 140 { 141 public: 142 /// The FiniteElement that created and owns this object. 143 /** This pointer is not owned. */ 144 const class FiniteElement *FE; 145 146 /** @brief IntegrationRule that defines the quadrature points at which the 147 basis functions of the #FE are evaluated. */ 148 /** This pointer is not owned. */ 149 const IntegrationRule *IntRule; 150 151 /// Type of data stored in the arrays #B, #Bt, #G, and #Gt. 152 enum Mode 153 { 154 /** @brief Full multidimensional representation which does not use tensor 155 product structure. The ordering of the degrees of freedom is as 156 defined by #FE */ 157 FULL, 158 159 /** @brief Tensor product representation using 1D matrices/tensors with 160 dimensions using 1D number of quadrature points and degrees of 161 freedom. */ 162 /** When representing a vector-valued FiniteElement, two DofToQuad objects 163 are used to describe the "closed" and "open" 1D basis functions 164 (TODO). */ 165 TENSOR 166 }; 167 168 /// Describes the contents of the #B, #Bt, #G, and #Gt arrays, see #Mode. 169 Mode mode; 170 171 /** @brief Number of degrees of freedom = number of basis functions. When 172 #mode is TENSOR, this is the 1D number. */ 173 int ndof; 174 175 /** @brief Number of quadrature points. When #mode is TENSOR, this is the 1D 176 number. */ 177 int nqpt; 178 179 /// Basis functions evaluated at quadrature points. 180 /** The storage layout is column-major with dimensions: 181 - #nqpt x #ndof, for scalar elements, or 182 - #nqpt x dim x #ndof, for vector elements, (TODO) 183 184 where 185 186 - dim = dimension of the finite element reference space when #mode is 187 FULL, and dim = 1 when #mode is TENSOR. */ 188 Array<double> B; 189 190 /// Transpose of #B. 191 /** The storage layout is column-major with dimensions: 192 - #ndof x #nqpt, for scalar elements, or 193 - #ndof x #nqpt x dim, for vector elements (TODO). */ 194 Array<double> Bt; 195 196 /** @brief Gradients/divergences/curls of basis functions evaluated at 197 quadrature points. */ 198 /** The storage layout is column-major with dimensions: 199 - #nqpt x dim x #ndof, for scalar elements, or 200 - #nqpt x #ndof, for H(div) vector elements (TODO), or 201 - #nqpt x cdim x #ndof, for H(curl) vector elements (TODO), 202 203 where 204 205 - dim = dimension of the finite element reference space when #mode is 206 FULL, and 1 when #mode is TENSOR, 207 - cdim = 1/1/3 in 1D/2D/3D, respectively, when #mode is FULL, and cdim = 208 1 when #mode is TENSOR. */ 209 Array<double> G; 210 211 /// Transpose of #G. 212 /** The storage layout is column-major with dimensions: 213 - #ndof x #nqpt x dim, for scalar elements, or 214 - #ndof x #nqpt, for H(div) vector elements (TODO), or 215 - #ndof x #nqpt x cdim, for H(curl) vector elements (TODO). */ 216 Array<double> Gt; 217 }; 218 219 220 /// Describes the function space on each element 221 class FunctionSpace 222 { 223 public: 224 enum 225 { 226 Pk, ///< Polynomials of order k 227 Qk, ///< Tensor products of polynomials of order k 228 rQk ///< Refined tensor products of polynomials of order k 229 }; 230 }; 231 232 class ElementTransformation; 233 class Coefficient; 234 class VectorCoefficient; 235 class MatrixCoefficient; 236 class KnotVector; 237 238 239 // Base and derived classes for finite elements 240 241 242 /// Abstract class for all finite elements. 243 class FiniteElement 244 { 245 protected: 246 int dim; ///< Dimension of reference space 247 Geometry::Type geom_type; ///< Geometry::Type of the reference element 248 int func_space, range_type, map_type, 249 deriv_type, deriv_range_type, deriv_map_type; 250 mutable 251 int dof, ///< Number of degrees of freedom 252 order; ///< Order/degree of the shape functions 253 mutable int orders[Geometry::MaxDim]; ///< Anisotropic orders 254 IntegrationRule Nodes; 255 #ifndef MFEM_THREAD_SAFE 256 mutable DenseMatrix vshape; // Dof x Dim 257 #endif 258 /// Container for all DofToQuad objects created by the FiniteElement. 259 /** Multiple DofToQuad objects may be needed when different quadrature rules 260 or different DofToQuad::Mode are used. */ 261 mutable Array<DofToQuad*> dof2quad_array; 262 263 public: 264 /// Enumeration for range_type and deriv_range_type 265 enum RangeType { SCALAR, VECTOR }; 266 267 /** @brief Enumeration for MapType: defines how reference functions are 268 mapped to physical space. 269 270 A reference function \f$ \hat u(\hat x) \f$ can be mapped to a function 271 \f$ u(x) \f$ on a general physical element in following ways: 272 - \f$ x = T(\hat x) \f$ is the image of the reference point \f$ \hat x \f$ 273 - \f$ J = J(\hat x) \f$ is the Jacobian matrix of the transformation T 274 - \f$ w = w(\hat x) = det(J) \f$ is the transformation weight factor for square J 275 - \f$ w = w(\hat x) = det(J^t J)^{1/2} \f$ is the transformation weight factor in general 276 */ 277 enum MapType 278 { 279 VALUE, /**< For scalar fields; preserves point values 280 \f$ u(x) = \hat u(\hat x) \f$ */ 281 INTEGRAL, /**< For scalar fields; preserves volume integrals 282 \f$ u(x) = (1/w) \hat u(\hat x) \f$ */ 283 H_DIV, /**< For vector fields; preserves surface integrals of the 284 normal component \f$ u(x) = (J/w) \hat u(\hat x) \f$ */ 285 H_CURL /**< For vector fields; preserves line integrals of the 286 tangential component 287 \f$ u(x) = J^{-t} \hat u(\hat x) \f$ (square J), 288 \f$ u(x) = J(J^t J)^{-1} \hat u(\hat x) \f$ (general J) */ 289 }; 290 291 /** @brief Enumeration for DerivType: defines which derivative method 292 is implemented. 293 294 Each FiniteElement class implements up to one type of derivative. The 295 value returned by GetDerivType() indicates which derivative method is 296 implemented. 297 */ 298 enum DerivType 299 { 300 NONE, ///< No derivatives implemented 301 GRAD, ///< Implements CalcDShape methods 302 DIV, ///< Implements CalcDivShape methods 303 CURL ///< Implements CalcCurlShape methods 304 }; 305 306 /** @brief Construct FiniteElement with given 307 @param D Reference space dimension 308 @param G Geometry type (of type Geometry::Type) 309 @param Do Number of degrees of freedom in the FiniteElement 310 @param O Order/degree of the FiniteElement 311 @param F FunctionSpace type of the FiniteElement 312 */ 313 FiniteElement(int D, Geometry::Type G, int Do, int O, 314 int F = FunctionSpace::Pk); 315 316 /// Returns the reference space dimension for the finite element GetDim() const317 int GetDim() const { return dim; } 318 319 /// Returns the Geometry::Type of the reference element GetGeomType() const320 Geometry::Type GetGeomType() const { return geom_type; } 321 322 /// Returns the number of degrees of freedom in the finite element GetDof() const323 int GetDof() const { return dof; } 324 325 /** @brief Returns the order of the finite element. In the case of 326 anisotropic orders, returns the maximum order. */ GetOrder() const327 int GetOrder() const { return order; } 328 329 /** @brief Returns true if the FiniteElement basis *may be using* different 330 orders/degrees in different spatial directions. */ HasAnisotropicOrders() const331 bool HasAnisotropicOrders() const { return orders[0] != -1; } 332 333 /// Returns an array containing the anisotropic orders/degrees. GetAnisotropicOrders() const334 const int *GetAnisotropicOrders() const { return orders; } 335 336 /// Returns the type of FunctionSpace on the element. Space() const337 int Space() const { return func_space; } 338 339 /// Returns the FiniteElement::RangeType of the element, one of {SCALAR, VECTOR}. GetRangeType() const340 int GetRangeType() const { return range_type; } 341 342 /** @brief Returns the FiniteElement::RangeType of the element derivative, either 343 SCALAR or VECTOR. */ GetDerivRangeType() const344 int GetDerivRangeType() const { return deriv_range_type; } 345 346 /** @brief Returns the FiniteElement::MapType of the element describing how reference 347 functions are mapped to physical space, one of {VALUE, INTEGRAL 348 H_DIV, H_CURL}. */ GetMapType() const349 int GetMapType() const { return map_type; } 350 351 352 /** @brief Returns the FiniteElement::DerivType of the element describing the 353 spatial derivative method implemented, one of {NONE, GRAD, 354 DIV, CURL}. */ GetDerivType() const355 int GetDerivType() const { return deriv_type; } 356 357 /** @brief Returns the FiniteElement::DerivType of the element describing how 358 reference function derivatives are mapped to physical space, one of {VALUE, 359 INTEGRAL, H_DIV, H_CURL}. */ GetDerivMapType() const360 int GetDerivMapType() const { return deriv_map_type; } 361 362 /** @brief Evaluate the values of all shape functions of a scalar finite 363 element in reference space at the given point @a ip. */ 364 /** The size (#dof) of the result Vector @a shape must be set in advance. */ 365 virtual void CalcShape(const IntegrationPoint &ip, 366 Vector &shape) const = 0; 367 368 /** @brief Evaluate the values of all shape functions of a scalar finite 369 element in physical space at the point described by @a Trans. */ 370 /** The size (#dof) of the result Vector @a shape must be set in advance. */ 371 void CalcPhysShape(ElementTransformation &Trans, Vector &shape) const; 372 373 /** @brief Evaluate the gradients of all shape functions of a scalar finite 374 element in reference space at the given point @a ip. */ 375 /** Each row of the result DenseMatrix @a dshape contains the derivatives of 376 one shape function. The size (#dof x #dim) of @a dshape must be set in 377 advance. */ 378 virtual void CalcDShape(const IntegrationPoint &ip, 379 DenseMatrix &dshape) const = 0; 380 381 /** @brief Evaluate the gradients of all shape functions of a scalar finite 382 element in physical space at the point described by @a Trans. */ 383 /** Each row of the result DenseMatrix @a dshape contains the derivatives of 384 one shape function. The size (#dof x SDim) of @a dshape must be set in 385 advance, where SDim >= #dim is the physical space dimension as described 386 by @a Trans. */ 387 void CalcPhysDShape(ElementTransformation &Trans, DenseMatrix &dshape) const; 388 389 /// Get a const reference to the nodes of the element GetNodes() const390 const IntegrationRule & GetNodes() const { return Nodes; } 391 392 // virtual functions for finite elements on vector spaces 393 394 /** @brief Evaluate the values of all shape functions of a *vector* finite 395 element in reference space at the given point @a ip. */ 396 /** Each row of the result DenseMatrix @a shape contains the components of 397 one vector shape function. The size (#dof x #dim) of @a shape must be set 398 in advance. */ 399 virtual void CalcVShape(const IntegrationPoint &ip, 400 DenseMatrix &shape) const; 401 402 /** @brief Evaluate the values of all shape functions of a *vector* finite 403 element in physical space at the point described by @a Trans. */ 404 /** Each row of the result DenseMatrix @a shape contains the components of 405 one vector shape function. The size (#dof x SDim) of @a shape must be set 406 in advance, where SDim >= #dim is the physical space dimension as 407 described by @a Trans. */ 408 virtual void CalcVShape(ElementTransformation &Trans, 409 DenseMatrix &shape) const; 410 411 /// Equivalent to the CalcVShape() method with the same arguments. CalcPhysVShape(ElementTransformation & Trans,DenseMatrix & shape) const412 void CalcPhysVShape(ElementTransformation &Trans, DenseMatrix &shape) const 413 { CalcVShape(Trans, shape); } 414 415 /** @brief Evaluate the divergence of all shape functions of a *vector* 416 finite element in reference space at the given point @a ip. */ 417 /** The size (#dof) of the result Vector @a divshape must be set in advance. 418 */ 419 virtual void CalcDivShape(const IntegrationPoint &ip, 420 Vector &divshape) const; 421 422 /** @brief Evaluate the divergence of all shape functions of a *vector* 423 finite element in physical space at the point described by @a Trans. */ 424 /** The size (#dof) of the result Vector @a divshape must be set in advance. 425 */ 426 void CalcPhysDivShape(ElementTransformation &Trans, Vector &divshape) const; 427 428 /** @brief Evaluate the curl of all shape functions of a *vector* finite 429 element in reference space at the given point @a ip. */ 430 /** Each row of the result DenseMatrix @a curl_shape contains the components 431 of the curl of one vector shape function. The size (#dof x CDim) of 432 @a curl_shape must be set in advance, where CDim = 3 for #dim = 3 and 433 CDim = 1 for #dim = 2. */ 434 virtual void CalcCurlShape(const IntegrationPoint &ip, 435 DenseMatrix &curl_shape) const; 436 437 /** @brief Evaluate the curl of all shape functions of a *vector* finite 438 element in physical space at the point described by @a Trans. */ 439 /** Each row of the result DenseMatrix @a curl_shape contains the components 440 of the curl of one vector shape function. The size (#dof x CDim) of 441 @a curl_shape must be set in advance, where CDim = 3 for #dim = 3 and 442 CDim = 1 for #dim = 2. */ 443 void CalcPhysCurlShape(ElementTransformation &Trans, 444 DenseMatrix &curl_shape) const; 445 446 /** @brief Get the dofs associated with the given @a face. 447 @a *dofs is set to an internal array of the local dofc on the 448 face, while *ndofs is set to the number of dofs on that face. 449 */ 450 virtual void GetFaceDofs(int face, int **dofs, int *ndofs) const; 451 452 /** @brief Evaluate the Hessians of all shape functions of a scalar finite 453 element in reference space at the given point @a ip. */ 454 /** Each row of the result DenseMatrix @a Hessian contains upper triangular 455 part of the Hessian of one shape function. 456 The order in 2D is {u_xx, u_xy, u_yy}. 457 The size (#dof x (#dim (#dim+1)/2) of @a Hessian must be set in advance.*/ 458 virtual void CalcHessian (const IntegrationPoint &ip, 459 DenseMatrix &Hessian) const; 460 461 /** @brief Evaluate the Hessian of all shape functions of a scalar finite 462 element in reference space at the given point @a ip. */ 463 /** The size (#dof, #dim*(#dim+1)/2) of @a Hessian must be set in advance. */ 464 virtual void CalcPhysHessian(ElementTransformation &Trans, 465 DenseMatrix& Hessian) const; 466 467 /** @brief Evaluate the Laplacian of all shape functions of a scalar finite 468 element in reference space at the given point @a ip. */ 469 /** The size (#dof) of @a Laplacian must be set in advance. */ 470 virtual void CalcPhysLaplacian(ElementTransformation &Trans, 471 Vector& Laplacian) const; 472 473 virtual void CalcPhysLinLaplacian(ElementTransformation &Trans, 474 Vector& Laplacian) const; 475 476 /** @brief Return the local interpolation matrix @a I (Dof x Dof) where the 477 fine element is the image of the base geometry under the given 478 transformation. */ 479 virtual void GetLocalInterpolation(ElementTransformation &Trans, 480 DenseMatrix &I) const; 481 482 /** @brief Return a local restriction matrix @a R (Dof x Dof) mapping fine 483 dofs to coarse dofs. 484 485 The fine element is the image of the base geometry under the given 486 transformation, @a Trans. 487 488 The assumption in this method is that a subset of the coarse dofs can be 489 expressed only in terms of the dofs of the given fine element. 490 491 Rows in @a R corresponding to coarse dofs that cannot be expressed in 492 terms of the fine dofs will be marked as invalid by setting the first 493 entry (column 0) in the row to infinity(). 494 495 This method assumes that the dimensions of @a R are set before it is 496 called. */ 497 virtual void GetLocalRestriction(ElementTransformation &Trans, 498 DenseMatrix &R) const; 499 500 /** @brief Return interpolation matrix, @a I, which maps dofs from a coarse 501 element, @a fe, to the fine dofs on @a this finite element. */ 502 /** @a Trans represents the mapping from the reference element of @a this 503 element into a subset of the reference space of the element @a fe, thus 504 allowing the "coarse" FiniteElement to be different from the "fine" 505 FiniteElement as when h-refinement is combined with p-refinement or 506 p-derefinement. It is assumed that both finite elements use the same 507 FiniteElement::MapType. */ 508 virtual void GetTransferMatrix(const FiniteElement &fe, 509 ElementTransformation &Trans, 510 DenseMatrix &I) const; 511 512 /** @brief Given a coefficient and a transformation, compute its projection 513 (approximation) in the local finite dimensional space in terms 514 of the degrees of freedom. */ 515 /** The approximation used to project is usually local interpolation of 516 degrees of freedom. The derived class could use other methods not 517 implemented yet, e.g. local L2 projection. */ 518 virtual void Project(Coefficient &coeff, 519 ElementTransformation &Trans, Vector &dofs) const; 520 521 /** @brief Given a vector coefficient and a transformation, compute its 522 projection (approximation) in the local finite dimensional space 523 in terms of the degrees of freedom. (VectorFiniteElements) */ 524 /** The approximation used to project is usually local interpolation of 525 degrees of freedom. The derived class could use other methods not 526 implemented yet, e.g. local L2 projection. */ 527 virtual void Project(VectorCoefficient &vc, 528 ElementTransformation &Trans, Vector &dofs) const; 529 530 /** @brief Given a vector of values at the finite element nodes and a 531 transformation, compute its projection (approximation) in the local 532 finite dimensional space in terms of the degrees of freedom. Valid for 533 VectorFiniteElements. */ 534 virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, 535 Vector &dofs) const; 536 537 /** @brief Given a matrix coefficient and a transformation, compute an 538 approximation ("projection") in the local finite dimensional space in 539 terms of the degrees of freedom. For VectorFiniteElements, the rows of 540 the coefficient are projected in the vector space. */ 541 virtual void ProjectMatrixCoefficient( 542 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const; 543 544 /** @brief Project a delta function centered on the given @a vertex in 545 the local finite dimensional space represented by the @a dofs. */ 546 virtual void ProjectDelta(int vertex, Vector &dofs) const; 547 548 /** @brief Compute the embedding/projection matrix from the given 549 FiniteElement onto 'this' FiniteElement. The ElementTransformation is 550 included to support cases when the projection depends on it. */ 551 virtual void Project(const FiniteElement &fe, ElementTransformation &Trans, 552 DenseMatrix &I) const; 553 554 /** @brief Compute the discrete gradient matrix from the given FiniteElement 555 onto 'this' FiniteElement. The ElementTransformation is included to 556 support cases when the matrix depends on it. */ 557 virtual void ProjectGrad(const FiniteElement &fe, 558 ElementTransformation &Trans, 559 DenseMatrix &grad) const; 560 561 /** @brief Compute the discrete curl matrix from the given FiniteElement onto 562 'this' FiniteElement. The ElementTransformation is included to support 563 cases when the matrix depends on it. */ 564 virtual void ProjectCurl(const FiniteElement &fe, 565 ElementTransformation &Trans, 566 DenseMatrix &curl) const; 567 568 /** @brief Compute the discrete divergence matrix from the given 569 FiniteElement onto 'this' FiniteElement. The ElementTransformation is 570 included to support cases when the matrix depends on it. */ 571 virtual void ProjectDiv(const FiniteElement &fe, 572 ElementTransformation &Trans, 573 DenseMatrix &div) const; 574 575 /** @brief Return a DofToQuad structure corresponding to the given 576 IntegrationRule using the given DofToQuad::Mode. */ 577 /** See the documentation for DofToQuad for more details. */ 578 virtual const DofToQuad &GetDofToQuad(const IntegrationRule &ir, 579 DofToQuad::Mode mode) const; 580 /// Deconstruct the FiniteElement 581 virtual ~FiniteElement(); 582 583 /** @brief Return true if the BasisType of @a b_type is closed 584 (has Quadrature1D points on the boundary). */ IsClosedType(int b_type)585 static bool IsClosedType(int b_type) 586 { 587 const int q_type = BasisType::GetQuadrature1D(b_type); 588 return ((q_type != Quadrature1D::Invalid) && 589 (Quadrature1D::CheckClosed(q_type) != Quadrature1D::Invalid)); 590 } 591 592 /** @brief Return true if the BasisType of @a b_type is open 593 (doesn't have Quadrature1D points on the boundary). */ IsOpenType(int b_type)594 static bool IsOpenType(int b_type) 595 { 596 const int q_type = BasisType::GetQuadrature1D(b_type); 597 return ((q_type != Quadrature1D::Invalid) && 598 (Quadrature1D::CheckOpen(q_type) != Quadrature1D::Invalid)); 599 } 600 601 /** @brief Ensure that the BasisType of @a b_type is closed 602 (has Quadrature1D points on the boundary). */ VerifyClosed(int b_type)603 static int VerifyClosed(int b_type) 604 { 605 MFEM_VERIFY(IsClosedType(b_type), 606 "invalid closed basis type: " << b_type); 607 return b_type; 608 } 609 610 /** @brief Ensure that the BasisType of @a b_type is open 611 (doesn't have Quadrature1D points on the boundary). */ VerifyOpen(int b_type)612 static int VerifyOpen(int b_type) 613 { 614 MFEM_VERIFY(IsOpenType(b_type), "invalid open basis type: " << b_type); 615 return b_type; 616 } 617 618 /** @brief Ensure that the BasisType of @a b_type nodal 619 (satisfies the interpolation property). */ VerifyNodal(int b_type)620 static int VerifyNodal(int b_type) 621 { 622 return BasisType::CheckNodal(b_type); 623 } 624 }; 625 626 627 /** @brief Class for finite elements with basis functions 628 that return scalar values. */ 629 class ScalarFiniteElement : public FiniteElement 630 { 631 protected: 632 #ifndef MFEM_THREAD_SAFE 633 mutable Vector c_shape; 634 #endif 635 CheckScalarFE(const FiniteElement & fe)636 static const ScalarFiniteElement &CheckScalarFE(const FiniteElement &fe) 637 { 638 MFEM_VERIFY(fe.GetRangeType() == SCALAR, 639 "'fe' must be a ScalarFiniteElement"); 640 return static_cast<const ScalarFiniteElement &>(fe); 641 } 642 643 const DofToQuad &GetTensorDofToQuad(const class TensorBasisElement &tb, 644 const IntegrationRule &ir, 645 DofToQuad::Mode mode) const; 646 647 public: 648 /** @brief Construct ScalarFiniteElement with given 649 @param D Reference space dimension 650 @param G Geometry type (of type Geometry::Type) 651 @param Do Number of degrees of freedom in the FiniteElement 652 @param O Order/degree of the FiniteElement 653 @param F FunctionSpace type of the FiniteElement 654 */ ScalarFiniteElement(int D,Geometry::Type G,int Do,int O,int F=FunctionSpace::Pk)655 ScalarFiniteElement(int D, Geometry::Type G, int Do, int O, 656 int F = FunctionSpace::Pk) 657 #ifdef MFEM_THREAD_SAFE 658 : FiniteElement(D, G, Do, O, F) 659 { deriv_type = GRAD; deriv_range_type = VECTOR; deriv_map_type = H_CURL; } 660 #else 661 : FiniteElement(D, G, Do, O, F), c_shape(dof) 662 { deriv_type = GRAD; deriv_range_type = VECTOR; deriv_map_type = H_CURL; } 663 #endif 664 665 /** @brief Set the FiniteElement::MapType of the element to either VALUE or 666 INTEGRAL. Also sets the FiniteElement::DerivType to GRAD if the 667 FiniteElement::MapType is VALUE. */ SetMapType(int M)668 void SetMapType(int M) 669 { 670 MFEM_VERIFY(M == VALUE || M == INTEGRAL, "unknown MapType"); 671 map_type = M; 672 deriv_type = (M == VALUE) ? GRAD : NONE; 673 } 674 675 676 /** @brief Get the matrix @a I that defines nodal interpolation 677 @a between this element and the refined element @a fine_fe. */ 678 void NodalLocalInterpolation(ElementTransformation &Trans, 679 DenseMatrix &I, 680 const ScalarFiniteElement &fine_fe) const; 681 682 /** @brief Get matrix @a I "Interpolation" defined through local 683 L2-projection in the space defined by the @a fine_fe. */ 684 /** If the "fine" elements cannot represent all basis functions of the 685 "coarse" element, then boundary values from different sub-elements are 686 generally different. */ 687 void ScalarLocalInterpolation(ElementTransformation &Trans, 688 DenseMatrix &I, 689 const ScalarFiniteElement &fine_fe) const; 690 691 /** @brief Get restriction matrix @a R defined through local L2-projection 692 in the space defined by the @a coarse_fe. */ 693 /** If the "fine" elements cannot represent all basis functions of the 694 "coarse" element, then boundary values from different sub-elements are 695 generally different. */ 696 void ScalarLocalRestriction(ElementTransformation &Trans, 697 DenseMatrix &R, 698 const ScalarFiniteElement &coarse_fe) const; 699 700 virtual const DofToQuad &GetDofToQuad(const IntegrationRule &ir, 701 DofToQuad::Mode mode) const; 702 }; 703 704 705 /// Class for standard nodal finite elements. 706 class NodalFiniteElement : public ScalarFiniteElement 707 { 708 protected: 709 Array<int> lex_ordering; 710 void ProjectCurl_2D(const FiniteElement &fe, 711 ElementTransformation &Trans, 712 DenseMatrix &curl) const; 713 714 public: 715 /** @brief Construct NodalFiniteElement with given 716 @param D Reference space dimension 717 @param G Geometry type (of type Geometry::Type) 718 @param Do Number of degrees of freedom in the FiniteElement 719 @param O Order/degree of the FiniteElement 720 @param F FunctionSpace type of the FiniteElement 721 */ NodalFiniteElement(int D,Geometry::Type G,int Do,int O,int F=FunctionSpace::Pk)722 NodalFiniteElement(int D, Geometry::Type G, int Do, int O, 723 int F = FunctionSpace::Pk) 724 : ScalarFiniteElement(D, G, Do, O, F) { } 725 GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const726 virtual void GetLocalInterpolation(ElementTransformation &Trans, 727 DenseMatrix &I) const 728 { NodalLocalInterpolation(Trans, I, *this); } 729 730 virtual void GetLocalRestriction(ElementTransformation &Trans, 731 DenseMatrix &R) const; 732 GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const733 virtual void GetTransferMatrix(const FiniteElement &fe, 734 ElementTransformation &Trans, 735 DenseMatrix &I) const 736 { CheckScalarFE(fe).NodalLocalInterpolation(Trans, I, *this); } 737 738 virtual void Project (Coefficient &coeff, 739 ElementTransformation &Trans, Vector &dofs) const; 740 741 virtual void Project (VectorCoefficient &vc, 742 ElementTransformation &Trans, Vector &dofs) const; 743 744 // (mc.height x mc.width) @ DOFs -> (Dof x mc.width x mc.height) in dofs 745 virtual void ProjectMatrixCoefficient( 746 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const; 747 748 virtual void Project(const FiniteElement &fe, ElementTransformation &Trans, 749 DenseMatrix &I) const; 750 751 virtual void ProjectGrad(const FiniteElement &fe, 752 ElementTransformation &Trans, 753 DenseMatrix &grad) const; 754 755 virtual void ProjectDiv(const FiniteElement &fe, 756 ElementTransformation &Trans, 757 DenseMatrix &div) const; 758 759 /** @brief Get an Array<int> that maps lexicographically ordered indices to 760 the indices of the respective nodes/dofs/basis functions. Lexicographic 761 ordering of nodes is defined in terms of reference-space coordinates 762 (x,y,z). Lexicographically ordered nodes are listed first in order of 763 increasing x-coordinate, and then in order of increasing y-coordinate, 764 and finally in order of increasing z-coordinate. 765 766 For example, the six nodes of a quadratic triangle are lexicographically 767 ordered as follows: 768 769 5 770 |\ 771 3 4 772 | \ 773 0-1-2 774 775 The resulting array may be empty if the DOFs are already ordered 776 lexicographically, or if the finite element does not support creating 777 this permutation. The array returned is the same as the array given by 778 TensorBasisElement::GetDofMap, but it is also available for non-tensor 779 elements. */ GetLexicographicOrdering() const780 const Array<int> &GetLexicographicOrdering() const { return lex_ordering; } 781 }; 782 783 /** @brief Class for finite elements utilizing the 784 always positive Bernstein basis. */ 785 class PositiveFiniteElement : public ScalarFiniteElement 786 { 787 public: 788 /** @brief Construct PositiveFiniteElement with given 789 @param D Reference space dimension 790 @param G Geometry type (of type Geometry::Type) 791 @param Do Number of degrees of freedom in the FiniteElement 792 @param O Order/degree of the FiniteElement 793 @param F FunctionSpace type of the FiniteElement 794 */ PositiveFiniteElement(int D,Geometry::Type G,int Do,int O,int F=FunctionSpace::Pk)795 PositiveFiniteElement(int D, Geometry::Type G, int Do, int O, 796 int F = FunctionSpace::Pk) : 797 ScalarFiniteElement(D, G, Do, O, F) 798 { } 799 GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const800 virtual void GetLocalInterpolation(ElementTransformation &Trans, 801 DenseMatrix &I) const 802 { ScalarLocalInterpolation(Trans, I, *this); } 803 GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const804 virtual void GetLocalRestriction(ElementTransformation &Trans, 805 DenseMatrix &R) const 806 { ScalarLocalRestriction(Trans, R, *this); } 807 GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const808 virtual void GetTransferMatrix(const FiniteElement &fe, 809 ElementTransformation &Trans, 810 DenseMatrix &I) const 811 { CheckScalarFE(fe).ScalarLocalInterpolation(Trans, I, *this); } 812 813 using FiniteElement::Project; 814 815 // Low-order monotone "projection" (actually it is not a projection): the 816 // dofs are set to be the Coefficient values at the nodes. 817 virtual void Project(Coefficient &coeff, 818 ElementTransformation &Trans, Vector &dofs) const; 819 820 virtual void Project (VectorCoefficient &vc, 821 ElementTransformation &Trans, Vector &dofs) const; 822 823 virtual void Project(const FiniteElement &fe, ElementTransformation &Trans, 824 DenseMatrix &I) const; 825 }; 826 827 /** @brief Intermediate class for finite elements whose basis functions return 828 vector values. */ 829 class VectorFiniteElement : public FiniteElement 830 { 831 // Hide the scalar functions CalcShape and CalcDShape. 832 private: 833 /// Overrides the scalar CalcShape function to print an error. 834 virtual void CalcShape(const IntegrationPoint &ip, 835 Vector &shape) const; 836 837 /// Overrides the scalar CalcDShape function to print an error. 838 virtual void CalcDShape(const IntegrationPoint &ip, 839 DenseMatrix &dshape) const; 840 841 protected: 842 bool is_nodal; 843 #ifndef MFEM_THREAD_SAFE 844 mutable DenseMatrix J, Jinv; 845 mutable DenseMatrix curlshape, curlshape_J; 846 #endif 847 void SetDerivMembers(); 848 849 void CalcVShape_RT(ElementTransformation &Trans, 850 DenseMatrix &shape) const; 851 852 void CalcVShape_ND(ElementTransformation &Trans, 853 DenseMatrix &shape) const; 854 855 /** @brief Project a vector coefficient onto the RT basis functions 856 @param nk Face normal vectors for this element type 857 @param d2n Offset into nk for each degree of freedom 858 @param vc Vector coefficient to be projected 859 @param Trans Transformation from reference to physical coordinates 860 @param dofs Expansion coefficients for the approximation of vc 861 */ 862 void Project_RT(const double *nk, const Array<int> &d2n, 863 VectorCoefficient &vc, ElementTransformation &Trans, 864 Vector &dofs) const; 865 866 /// Projects the vector of values given at FE nodes to RT space 867 /** Project vector values onto the RT basis functions 868 @param nk Face normal vectors for this element type 869 @param d2n Offset into nk for each degree of freedom 870 @param vc Vector values at each interpolation point 871 @param Trans Transformation from reference to physical coordinates 872 @param dofs Expansion coefficients for the approximation of vc 873 */ 874 void Project_RT(const double *nk, const Array<int> &d2n, 875 Vector &vc, ElementTransformation &Trans, 876 Vector &dofs) const; 877 878 /// Project the rows of the matrix coefficient in an RT space 879 void ProjectMatrixCoefficient_RT( 880 const double *nk, const Array<int> &d2n, 881 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const; 882 883 /** @brief Project vector-valued basis functions onto the RT basis functions 884 @param nk Face normal vectors for this element type 885 @param d2n Offset into nk for each degree of freedom 886 @param fe Vector-valued finite element basis 887 @param Trans Transformation from reference to physical coordinates 888 @param I Expansion coefficients for the approximation of each basis 889 function 890 891 Note: If the FiniteElement, fe, is scalar-valued the projection will 892 assume that a FiniteElementSpace is being used to define a vector 893 field using the scalar basis functions for each component of the 894 vector field. 895 */ 896 void Project_RT(const double *nk, const Array<int> &d2n, 897 const FiniteElement &fe, ElementTransformation &Trans, 898 DenseMatrix &I) const; 899 900 // rotated gradient in 2D 901 void ProjectGrad_RT(const double *nk, const Array<int> &d2n, 902 const FiniteElement &fe, ElementTransformation &Trans, 903 DenseMatrix &grad) const; 904 905 // Compute the curl as a discrete operator from ND FE (fe) to ND FE (this). 906 // The natural FE for the range is RT, so this is an approximation. 907 void ProjectCurl_ND(const double *tk, const Array<int> &d2t, 908 const FiniteElement &fe, ElementTransformation &Trans, 909 DenseMatrix &curl) const; 910 911 void ProjectCurl_RT(const double *nk, const Array<int> &d2n, 912 const FiniteElement &fe, ElementTransformation &Trans, 913 DenseMatrix &curl) const; 914 915 /** @brief Project a vector coefficient onto the ND basis functions 916 @param tk Edge tangent vectors for this element type 917 @param d2t Offset into tk for each degree of freedom 918 @param vc Vector coefficient to be projected 919 @param Trans Transformation from reference to physical coordinates 920 @param dofs Expansion coefficients for the approximation of vc 921 */ 922 void Project_ND(const double *tk, const Array<int> &d2t, 923 VectorCoefficient &vc, ElementTransformation &Trans, 924 Vector &dofs) const; 925 926 /// Projects the vector of values given at FE nodes to ND space 927 /** Project vector values onto the ND basis functions 928 @param tk Edge tangent vectors for this element type 929 @param d2t Offset into tk for each degree of freedom 930 @param vc Vector values at each interpolation point 931 @param Trans Transformation from reference to physical coordinates 932 @param dofs Expansion coefficients for the approximation of vc 933 */ 934 void Project_ND(const double *tk, const Array<int> &d2t, 935 Vector &vc, ElementTransformation &Trans, 936 Vector &dofs) const; 937 938 /// Project the rows of the matrix coefficient in an ND space 939 void ProjectMatrixCoefficient_ND( 940 const double *tk, const Array<int> &d2t, 941 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const; 942 943 /** @brief Project vector-valued basis functions onto the ND basis functions 944 @param tk Edge tangent vectors for this element type 945 @param d2t Offset into tk for each degree of freedom 946 @param fe Vector-valued finite element basis 947 @param Trans Transformation from reference to physical coordinates 948 @param I Expansion coefficients for the approximation of each basis 949 function 950 951 Note: If the FiniteElement, fe, is scalar-valued the projection will 952 assume that a FiniteElementSpace is being used to define a vector 953 field using the scalar basis functions for each component of the 954 vector field. 955 */ 956 void Project_ND(const double *tk, const Array<int> &d2t, 957 const FiniteElement &fe, ElementTransformation &Trans, 958 DenseMatrix &I) const; 959 960 void ProjectGrad_ND(const double *tk, const Array<int> &d2t, 961 const FiniteElement &fe, ElementTransformation &Trans, 962 DenseMatrix &grad) const; 963 964 void LocalL2Projection_RT(const VectorFiniteElement &cfe, 965 ElementTransformation &Trans, 966 DenseMatrix &I) const; 967 968 void LocalInterpolation_RT(const VectorFiniteElement &cfe, 969 const double *nk, const Array<int> &d2n, 970 ElementTransformation &Trans, 971 DenseMatrix &I) const; 972 973 void LocalL2Projection_ND(const VectorFiniteElement &cfe, 974 ElementTransformation &Trans, 975 DenseMatrix &I) const; 976 977 void LocalInterpolation_ND(const VectorFiniteElement &cfe, 978 const double *tk, const Array<int> &d2t, 979 ElementTransformation &Trans, 980 DenseMatrix &I) const; 981 982 void LocalRestriction_RT(const double *nk, const Array<int> &d2n, 983 ElementTransformation &Trans, 984 DenseMatrix &R) const; 985 986 void LocalRestriction_ND(const double *tk, const Array<int> &d2t, 987 ElementTransformation &Trans, 988 DenseMatrix &R) const; 989 CheckVectorFE(const FiniteElement & fe)990 static const VectorFiniteElement &CheckVectorFE(const FiniteElement &fe) 991 { 992 if (fe.GetRangeType() != VECTOR) 993 { mfem_error("'fe' must be a VectorFiniteElement"); } 994 return static_cast<const VectorFiniteElement &>(fe); 995 } 996 997 public: VectorFiniteElement(int D,Geometry::Type G,int Do,int O,int M,int F=FunctionSpace::Pk)998 VectorFiniteElement (int D, Geometry::Type G, int Do, int O, int M, 999 int F = FunctionSpace::Pk) : 1000 #ifdef MFEM_THREAD_SAFE 1001 FiniteElement(D, G, Do, O, F) 1002 { range_type = VECTOR; map_type = M; SetDerivMembers(); is_nodal = true; } 1003 #else 1004 FiniteElement(D, G, Do, O, F), Jinv(D) 1005 { range_type = VECTOR; map_type = M; SetDerivMembers(); is_nodal = true; } 1006 #endif 1007 }; 1008 1009 /// A 0D point finite element 1010 class PointFiniteElement : public NodalFiniteElement 1011 { 1012 public: 1013 /// Construct the PointFiniteElement 1014 PointFiniteElement(); 1015 1016 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1017 1018 virtual void CalcDShape(const IntegrationPoint &ip, 1019 DenseMatrix &dshape) const; 1020 }; 1021 1022 /// A 1D linear element with nodes on the endpoints 1023 class Linear1DFiniteElement : public NodalFiniteElement 1024 { 1025 public: 1026 /// Construct the Linear1DFiniteElement 1027 Linear1DFiniteElement(); 1028 1029 /** virtual function which evaluates the values of all 1030 shape functions at a given point ip and stores 1031 them in the vector shape of dimension Dof (2) */ 1032 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1033 1034 /** virtual function which evaluates the derivatives of all 1035 shape functions at a given point ip and stores them in 1036 the matrix dshape (Dof x Dim) (2 x 1) so that each row 1037 contains the derivative of one shape function */ 1038 virtual void CalcDShape(const IntegrationPoint &ip, 1039 DenseMatrix &dshape) const; 1040 }; 1041 1042 /// A 2D linear element on triangle with nodes at the vertices of the triangle 1043 class Linear2DFiniteElement : public NodalFiniteElement 1044 { 1045 public: 1046 /// Construct the Linear2DFiniteElement 1047 Linear2DFiniteElement(); 1048 1049 /** virtual function which evaluates the values of all 1050 shape functions at a given point ip and stores 1051 them in the vector shape of dimension Dof (3) */ 1052 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1053 1054 /** virtual function which evaluates the values of all 1055 partial derivatives of all shape functions at a given 1056 point ip and stores them in the matrix dshape (Dof x Dim) (3 x 2) 1057 so that each row contains the derivatives of one shape function */ 1058 virtual void CalcDShape(const IntegrationPoint &ip, 1059 DenseMatrix &dshape) const; ProjectDelta(int vertex,Vector & dofs) const1060 virtual void ProjectDelta(int vertex, Vector &dofs) const 1061 { dofs = 0.0; dofs(vertex) = 1.0; } 1062 }; 1063 1064 /// A 2D bi-linear element on a square with nodes at the vertices of the square 1065 class BiLinear2DFiniteElement : public NodalFiniteElement 1066 { 1067 public: 1068 /// Construct the BiLinear2DFiniteElement 1069 BiLinear2DFiniteElement(); 1070 1071 /** virtual function which evaluates the values of all 1072 shape functions at a given point ip and stores 1073 them in the vector shape of dimension Dof (4) */ 1074 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1075 1076 /** virtual function which evaluates the values of all 1077 partial derivatives of all shape functions at a given 1078 point ip and stores them in the matrix dshape (Dof x Dim) (4 x 2) 1079 so that each row contains the derivatives of one shape function */ 1080 virtual void CalcDShape(const IntegrationPoint &ip, 1081 DenseMatrix &dshape) const; 1082 virtual void CalcHessian (const IntegrationPoint &ip, 1083 DenseMatrix &h) const; ProjectDelta(int vertex,Vector & dofs) const1084 virtual void ProjectDelta(int vertex, Vector &dofs) const 1085 { dofs = 0.0; dofs(vertex) = 1.0; } // { dofs = 1.0; } 1086 }; 1087 1088 /// A linear element on a triangle with nodes at the 3 "Gaussian" points 1089 class GaussLinear2DFiniteElement : public NodalFiniteElement 1090 { 1091 public: 1092 /// Construct the GaussLinear2DFiniteElement 1093 GaussLinear2DFiniteElement(); 1094 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1095 virtual void CalcDShape(const IntegrationPoint &ip, 1096 DenseMatrix &dshape) const; 1097 virtual void ProjectDelta(int vertex, Vector &dofs) const; 1098 }; 1099 1100 /// A 2D bi-linear element on a square with nodes at the "Gaussian" points 1101 class GaussBiLinear2DFiniteElement : public NodalFiniteElement 1102 { 1103 private: 1104 static const double p[2]; 1105 1106 public: 1107 /// Construct the FiniteElement 1108 GaussBiLinear2DFiniteElement(); 1109 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1110 virtual void CalcDShape(const IntegrationPoint &ip, 1111 DenseMatrix &dshape) const; 1112 virtual void ProjectDelta(int vertex, Vector &dofs) const; 1113 }; 1114 1115 /** @brief A 2D linear element on a square with 3 nodes at the 1116 vertices of the lower left triangle */ 1117 class P1OnQuadFiniteElement : public NodalFiniteElement 1118 { 1119 public: 1120 /// Construct the P1OnQuadFiniteElement 1121 P1OnQuadFiniteElement(); 1122 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1123 virtual void CalcDShape(const IntegrationPoint &ip, 1124 DenseMatrix &dshape) const; ProjectDelta(int vertex,Vector & dofs) const1125 virtual void ProjectDelta(int vertex, Vector &dofs) const 1126 { dofs = 1.0; } 1127 }; 1128 1129 /// A 1D quadratic finite element with uniformly spaced nodes 1130 class Quad1DFiniteElement : public NodalFiniteElement 1131 { 1132 public: 1133 /// Construct the Quad1DFiniteElement 1134 Quad1DFiniteElement(); 1135 1136 /** virtual function which evaluates the values of all 1137 shape functions at a given point ip and stores 1138 them in the vector shape of dimension Dof (3) */ 1139 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1140 1141 /** virtual function which evaluates the derivatives of all 1142 shape functions at a given point ip and stores them in 1143 the matrix dshape (Dof x Dim) (3 x 1) so that each row 1144 contains the derivative of one shape function */ 1145 virtual void CalcDShape(const IntegrationPoint &ip, 1146 DenseMatrix &dshape) const; 1147 }; 1148 1149 /// A 1D quadratic positive element utilizing the 2nd order Bernstein basis 1150 class QuadPos1DFiniteElement : public PositiveFiniteElement 1151 { 1152 public: 1153 /// Construct the QuadPos1DFiniteElement 1154 QuadPos1DFiniteElement(); 1155 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1156 virtual void CalcDShape(const IntegrationPoint &ip, 1157 DenseMatrix &dshape) const; 1158 }; 1159 1160 /** @brief A 2D quadratic element on triangle with nodes at the 1161 vertices and midpoints of the triangle. */ 1162 class Quad2DFiniteElement : public NodalFiniteElement 1163 { 1164 public: 1165 /// Construct the Quad2DFiniteElement 1166 Quad2DFiniteElement(); 1167 1168 /** virtual function which evaluates the values of all 1169 shape functions at a given point ip and stores 1170 them in the vector shape of dimension Dof (6) */ 1171 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1172 1173 /** virtual function which evaluates the values of all 1174 partial derivatives of all shape functions at a given 1175 point ip and stores them in the matrix dshape (Dof x Dim) (6 x 2) 1176 so that each row contains the derivatives of one shape function */ 1177 virtual void CalcDShape(const IntegrationPoint &ip, 1178 DenseMatrix &dshape) const; 1179 1180 virtual void CalcHessian (const IntegrationPoint &ip, 1181 DenseMatrix &h) const; 1182 virtual void ProjectDelta(int vertex, Vector &dofs) const; 1183 }; 1184 1185 /// A quadratic element on triangle with nodes at the "Gaussian" points 1186 class GaussQuad2DFiniteElement : public NodalFiniteElement 1187 { 1188 private: 1189 static const double p[2]; 1190 DenseMatrix A; 1191 mutable DenseMatrix D; 1192 mutable Vector pol; 1193 public: 1194 /// Construct the GaussQuad2DFiniteElement 1195 GaussQuad2DFiniteElement(); 1196 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1197 virtual void CalcDShape(const IntegrationPoint &ip, 1198 DenseMatrix &dshape) const; 1199 // virtual void ProjectDelta(int vertex, Vector &dofs) const; 1200 }; 1201 1202 /// A 2D bi-quadratic element on a square with uniformly spaced nodes 1203 class BiQuad2DFiniteElement : public NodalFiniteElement 1204 { 1205 public: 1206 /// Construct the BiQuad2DFiniteElement 1207 BiQuad2DFiniteElement(); 1208 1209 /** virtual function which evaluates the values of all 1210 shape functions at a given point ip and stores 1211 them in the vector shape of dimension Dof (9) */ 1212 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1213 1214 /** virtual function which evaluates the values of all 1215 partial derivatives of all shape functions at a given 1216 point ip and stores them in the matrix dshape (Dof x Dim) (9 x 2) 1217 so that each row contains the derivatives of one shape function */ 1218 virtual void CalcDShape(const IntegrationPoint &ip, 1219 DenseMatrix &dshape) const; 1220 virtual void ProjectDelta(int vertex, Vector &dofs) const; 1221 }; 1222 1223 1224 /// A 2D positive bi-quadratic element on a square utilizing the 2nd order 1225 /// Bernstein basis 1226 class BiQuadPos2DFiniteElement : public PositiveFiniteElement 1227 { 1228 public: 1229 /// Construct the BiQuadPos2DFiniteElement 1230 BiQuadPos2DFiniteElement(); 1231 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1232 virtual void CalcDShape(const IntegrationPoint &ip, 1233 DenseMatrix &dshape) const; 1234 virtual void GetLocalInterpolation(ElementTransformation &Trans, 1235 DenseMatrix &I) const; 1236 using FiniteElement::Project; 1237 virtual void Project(Coefficient &coeff, ElementTransformation &Trans, 1238 Vector &dofs) const; 1239 virtual void Project(VectorCoefficient &vc, ElementTransformation &Trans, 1240 Vector &dofs) const; ProjectDelta(int vertex,Vector & dofs) const1241 virtual void ProjectDelta(int vertex, Vector &dofs) const 1242 { dofs = 0.; dofs(vertex) = 1.; } 1243 }; 1244 1245 /// A 2D bi-quadratic element on a square with nodes at the 9 "Gaussian" points 1246 class GaussBiQuad2DFiniteElement : public NodalFiniteElement 1247 { 1248 public: 1249 /// Construct the GaussBiQuad2DFiniteElement 1250 GaussBiQuad2DFiniteElement(); 1251 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1252 virtual void CalcDShape(const IntegrationPoint &ip, 1253 DenseMatrix &dshape) const; 1254 // virtual void ProjectDelta(int vertex, Vector &dofs) const { dofs = 1.; } 1255 }; 1256 1257 1258 /// A 2D bi-cubic element on a square with uniformly spaces nodes 1259 class BiCubic2DFiniteElement : public NodalFiniteElement 1260 { 1261 public: 1262 /// Construct the BiCubic2DFiniteElement 1263 BiCubic2DFiniteElement(); 1264 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1265 virtual void CalcDShape(const IntegrationPoint &ip, 1266 DenseMatrix &dshape) const; 1267 1268 /// Compute the Hessian of second order partial derivatives at @a ip. 1269 virtual void CalcHessian (const IntegrationPoint &ip, 1270 DenseMatrix &h) const; 1271 }; 1272 1273 /// A 1D cubic element with uniformly spaced nodes 1274 class Cubic1DFiniteElement : public NodalFiniteElement 1275 { 1276 public: 1277 /// Construct the Cubic1DFiniteElement 1278 Cubic1DFiniteElement(); 1279 1280 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1281 1282 virtual void CalcDShape(const IntegrationPoint &ip, 1283 DenseMatrix &dshape) const; 1284 }; 1285 1286 /// A 2D cubic element on a triangle with uniformly spaced nodes 1287 class Cubic2DFiniteElement : public NodalFiniteElement 1288 { 1289 public: 1290 /// Construct the Cubic2DFiniteElement 1291 Cubic2DFiniteElement(); 1292 1293 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1294 1295 virtual void CalcDShape(const IntegrationPoint &ip, 1296 DenseMatrix &dshape) const; 1297 1298 virtual void CalcHessian (const IntegrationPoint &ip, 1299 DenseMatrix &h) const; 1300 }; 1301 1302 /// A 3D cubic element on a tetrahedron with 20 nodes at the thirds of the 1303 /// tetrahedron 1304 class Cubic3DFiniteElement : public NodalFiniteElement 1305 { 1306 public: 1307 /// Construct the Cubic3DFiniteElement 1308 Cubic3DFiniteElement(); 1309 1310 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1311 1312 virtual void CalcDShape(const IntegrationPoint &ip, 1313 DenseMatrix &dshape) const; 1314 }; 1315 1316 /// A 2D constant element on a triangle 1317 class P0TriangleFiniteElement : public NodalFiniteElement 1318 { 1319 public: 1320 /// Construct the P0TriangleFiniteElement 1321 P0TriangleFiniteElement(); 1322 1323 /// evaluate shape function - constant 1 1324 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1325 1326 /// evaluate derivatives of shape function - constant 0 1327 virtual void CalcDShape(const IntegrationPoint &ip, 1328 DenseMatrix &dshape) const; ProjectDelta(int vertex,Vector & dofs) const1329 virtual void ProjectDelta(int vertex, Vector &dofs) const 1330 { dofs(0) = 1.0; } 1331 }; 1332 1333 1334 /// A 2D constant element on a square 1335 class P0QuadFiniteElement : public NodalFiniteElement 1336 { 1337 public: 1338 /// Construct the P0QuadFiniteElement 1339 P0QuadFiniteElement(); 1340 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1341 virtual void CalcDShape(const IntegrationPoint &ip, 1342 DenseMatrix &dshape) const; ProjectDelta(int vertex,Vector & dofs) const1343 virtual void ProjectDelta(int vertex, Vector &dofs) const 1344 { dofs(0) = 1.0; } 1345 }; 1346 1347 1348 /** @brief A 3D linear element on a tetrahedron with nodes at the 1349 vertices of the tetrahedron */ 1350 class Linear3DFiniteElement : public NodalFiniteElement 1351 { 1352 public: 1353 /// Construct the Linear3DFiniteElement 1354 Linear3DFiniteElement(); 1355 1356 /** @brief virtual function which evaluates the values of all 1357 shape functions at a given point ip and stores 1358 them in the vector shape of dimension Dof (4) */ 1359 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1360 1361 /** @brief virtual function which evaluates the values of all 1362 partial derivatives of all shape functions at a given 1363 point ip and stores them in the matrix dshape (Dof x Dim) (4 x 3) 1364 so that each row contains the derivatives of one shape function */ 1365 virtual void CalcDShape(const IntegrationPoint &ip, 1366 DenseMatrix &dshape) const; 1367 ProjectDelta(int vertex,Vector & dofs) const1368 virtual void ProjectDelta(int vertex, Vector &dofs) const 1369 { dofs = 0.0; dofs(vertex) = 1.0; } 1370 1371 /** @brief Get the dofs associated with the given @a face. 1372 @a *dofs is set to an internal array of the local dofc on the 1373 face, while *ndofs is set to the number of dofs on that face. 1374 */ 1375 virtual void GetFaceDofs(int face, int **dofs, int *ndofs) const; 1376 }; 1377 1378 /// A 3D quadratic element on a tetrahedron with uniformly spaced nodes 1379 class Quadratic3DFiniteElement : public NodalFiniteElement 1380 { 1381 public: 1382 /// Construct the Quadratic3DFiniteElement 1383 Quadratic3DFiniteElement(); 1384 1385 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1386 1387 virtual void CalcDShape(const IntegrationPoint &ip, 1388 DenseMatrix &dshape) const; 1389 }; 1390 1391 /// A 3D tri-linear element on a cube with nodes at the vertices of the cube 1392 class TriLinear3DFiniteElement : public NodalFiniteElement 1393 { 1394 public: 1395 /// Construct the TriLinear3DFiniteElement 1396 TriLinear3DFiniteElement(); 1397 1398 /** virtual function which evaluates the values of all 1399 shape functions at a given point ip and stores 1400 them in the vector shape of dimension Dof (8) */ 1401 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1402 1403 /** virtual function which evaluates the values of all 1404 partial derivatives of all shape functions at a given 1405 point ip and stores them in the matrix dshape (Dof x Dim) (8 x 3) 1406 so that each row contains the derivatives of one shape function */ 1407 virtual void CalcDShape(const IntegrationPoint &ip, 1408 DenseMatrix &dshape) const; 1409 ProjectDelta(int vertex,Vector & dofs) const1410 virtual void ProjectDelta(int vertex, Vector &dofs) const 1411 { dofs = 0.0; dofs(vertex) = 1.0; } 1412 }; 1413 1414 1415 /// A 2D Crouzeix-Raviart element on triangle 1416 class CrouzeixRaviartFiniteElement : public NodalFiniteElement 1417 { 1418 public: 1419 /// Construct the CrouzeixRaviartFiniteElement 1420 CrouzeixRaviartFiniteElement(); 1421 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1422 virtual void CalcDShape(const IntegrationPoint &ip, 1423 DenseMatrix &dshape) const; ProjectDelta(int vertex,Vector & dofs) const1424 virtual void ProjectDelta(int vertex, Vector &dofs) const 1425 { dofs = 1.0; } 1426 }; 1427 1428 /// A 2D Crouzeix-Raviart finite element on square 1429 class CrouzeixRaviartQuadFiniteElement : public NodalFiniteElement 1430 { 1431 public: 1432 /// Construct the CrouzeixRaviartQuadFiniteElement 1433 CrouzeixRaviartQuadFiniteElement(); 1434 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1435 virtual void CalcDShape(const IntegrationPoint &ip, 1436 DenseMatrix &dshape) const; 1437 }; 1438 1439 1440 /// A 1D constant element on a segment 1441 class P0SegmentFiniteElement : public NodalFiniteElement 1442 { 1443 public: 1444 /// Construct the P0SegmentFiniteElement with dummy order @a Ord 1445 P0SegmentFiniteElement(int Ord = 0); 1446 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1447 virtual void CalcDShape(const IntegrationPoint &ip, 1448 DenseMatrix &dshape) const; 1449 }; 1450 1451 /** @brief A 2D 1st order Raviart-Thomas vector element on a triangle */ 1452 class RT0TriangleFiniteElement : public VectorFiniteElement 1453 { 1454 private: 1455 static const double nk[3][2]; 1456 1457 public: 1458 /// Construct the RT0TriangleFiniteElement 1459 RT0TriangleFiniteElement(); 1460 1461 virtual void CalcVShape(const IntegrationPoint &ip, 1462 DenseMatrix &shape) const; 1463 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1464 virtual void CalcVShape(ElementTransformation &Trans, 1465 DenseMatrix &shape) const 1466 { CalcVShape_RT(Trans, shape); } 1467 1468 virtual void CalcDivShape(const IntegrationPoint &ip, 1469 Vector &divshape) const; 1470 1471 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1472 DenseMatrix &I) const; 1473 1474 using FiniteElement::Project; 1475 1476 virtual void Project (VectorCoefficient &vc, 1477 ElementTransformation &Trans, Vector &dofs) const; 1478 }; 1479 1480 /** @brief A 2D 1st order Raviart-Thomas vector element on a square*/ 1481 class RT0QuadFiniteElement : public VectorFiniteElement 1482 { 1483 private: 1484 static const double nk[4][2]; 1485 1486 public: 1487 /// Construct the RT0QuadFiniteElement 1488 RT0QuadFiniteElement(); 1489 1490 virtual void CalcVShape(const IntegrationPoint &ip, 1491 DenseMatrix &shape) const; 1492 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1493 virtual void CalcVShape(ElementTransformation &Trans, 1494 DenseMatrix &shape) const 1495 { CalcVShape_RT(Trans, shape); } 1496 1497 virtual void CalcDivShape(const IntegrationPoint &ip, 1498 Vector &divshape) const; 1499 1500 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1501 DenseMatrix &I) const; 1502 1503 using FiniteElement::Project; 1504 1505 virtual void Project (VectorCoefficient &vc, 1506 ElementTransformation &Trans, Vector &dofs) const; 1507 }; 1508 1509 /** @brief A 2D 2nd order Raviart-Thomas vector element on a triangle */ 1510 class RT1TriangleFiniteElement : public VectorFiniteElement 1511 { 1512 private: 1513 static const double nk[8][2]; 1514 1515 public: 1516 /// Construct the RT1TriangleFiniteElement 1517 RT1TriangleFiniteElement(); 1518 1519 virtual void CalcVShape(const IntegrationPoint &ip, 1520 DenseMatrix &shape) const; 1521 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1522 virtual void CalcVShape(ElementTransformation &Trans, 1523 DenseMatrix &shape) const 1524 { CalcVShape_RT(Trans, shape); } 1525 1526 virtual void CalcDivShape(const IntegrationPoint &ip, 1527 Vector &divshape) const; 1528 1529 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1530 DenseMatrix &I) const; 1531 1532 using FiniteElement::Project; 1533 1534 virtual void Project (VectorCoefficient &vc, 1535 ElementTransformation &Trans, Vector &dofs) const; 1536 }; 1537 1538 /** @brief A 2D 2nd order Raviart-Thomas vector element on a square */ 1539 class RT1QuadFiniteElement : public VectorFiniteElement 1540 { 1541 private: 1542 static const double nk[12][2]; 1543 1544 public: 1545 /// Construct the RT1QuadFiniteElement 1546 RT1QuadFiniteElement(); 1547 1548 virtual void CalcVShape(const IntegrationPoint &ip, 1549 DenseMatrix &shape) const; 1550 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1551 virtual void CalcVShape(ElementTransformation &Trans, 1552 DenseMatrix &shape) const 1553 { CalcVShape_RT(Trans, shape); } 1554 1555 virtual void CalcDivShape(const IntegrationPoint &ip, 1556 Vector &divshape) const; 1557 1558 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1559 DenseMatrix &I) const; 1560 1561 using FiniteElement::Project; 1562 1563 virtual void Project (VectorCoefficient &vc, 1564 ElementTransformation &Trans, Vector &dofs) const; 1565 }; 1566 1567 /** @brief A 2D 3rd order Raviart-Thomas vector element on a triangle */ 1568 class RT2TriangleFiniteElement : public VectorFiniteElement 1569 { 1570 private: 1571 static const double M[15][15]; 1572 public: 1573 /// Construct the RT2TriangleFiniteElement 1574 RT2TriangleFiniteElement(); 1575 1576 virtual void CalcVShape(const IntegrationPoint &ip, 1577 DenseMatrix &shape) const; 1578 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1579 virtual void CalcVShape(ElementTransformation &Trans, 1580 DenseMatrix &shape) const 1581 { CalcVShape_RT(Trans, shape); } 1582 1583 virtual void CalcDivShape(const IntegrationPoint &ip, 1584 Vector &divshape) const; 1585 }; 1586 1587 /** @brief A 2D 3rd order Raviart-Thomas vector element on a square */ 1588 class RT2QuadFiniteElement : public VectorFiniteElement 1589 { 1590 private: 1591 static const double nk[24][2]; 1592 static const double pt[4]; 1593 static const double dpt[3]; 1594 1595 public: 1596 /// Construct the RT2QuadFiniteElement 1597 RT2QuadFiniteElement(); 1598 1599 virtual void CalcVShape(const IntegrationPoint &ip, 1600 DenseMatrix &shape) const; 1601 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1602 virtual void CalcVShape(ElementTransformation &Trans, 1603 DenseMatrix &shape) const 1604 { CalcVShape_RT(Trans, shape); } 1605 1606 virtual void CalcDivShape(const IntegrationPoint &ip, 1607 Vector &divshape) const; 1608 1609 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1610 DenseMatrix &I) const; 1611 1612 using FiniteElement::Project; 1613 1614 virtual void Project (VectorCoefficient &vc, 1615 ElementTransformation &Trans, Vector &dofs) const; 1616 }; 1617 1618 /// A 1D linear element with nodes at 1/3 and 2/3 (trace of RT1) 1619 class P1SegmentFiniteElement : public NodalFiniteElement 1620 { 1621 public: 1622 /// Construct the P1SegmentFiniteElement 1623 P1SegmentFiniteElement(); 1624 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1625 virtual void CalcDShape(const IntegrationPoint &ip, 1626 DenseMatrix &dshape) const; 1627 }; 1628 1629 /// A 1D quadratic element with nodes at the Gaussian points (trace of RT2) 1630 class P2SegmentFiniteElement : public NodalFiniteElement 1631 { 1632 public: 1633 /// Construct the P2SegmentFiniteElement 1634 P2SegmentFiniteElement(); 1635 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1636 virtual void CalcDShape(const IntegrationPoint &ip, 1637 DenseMatrix &dshape) const; 1638 }; 1639 1640 /// A 1D element with uniform nodes 1641 class Lagrange1DFiniteElement : public NodalFiniteElement 1642 { 1643 private: 1644 Vector rwk; 1645 #ifndef MFEM_THREAD_SAFE 1646 mutable Vector rxxk; 1647 #endif 1648 public: 1649 /// Construct the Lagrange1DFiniteElement with the provided @a degree 1650 Lagrange1DFiniteElement (int degree); 1651 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1652 virtual void CalcDShape(const IntegrationPoint &ip, 1653 DenseMatrix &dshape) const; 1654 }; 1655 1656 /// A 3D Crouzeix-Raviart element on the tetrahedron. 1657 class P1TetNonConfFiniteElement : public NodalFiniteElement 1658 { 1659 public: 1660 /// Construct the P1TetNonConfFiniteElement 1661 P1TetNonConfFiniteElement(); 1662 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1663 virtual void CalcDShape(const IntegrationPoint &ip, 1664 DenseMatrix &dshape) const; 1665 }; 1666 1667 /// A 3D constant element on a tetrahedron 1668 class P0TetFiniteElement : public NodalFiniteElement 1669 { 1670 public: 1671 /// Construct the P0TetFiniteElement 1672 P0TetFiniteElement (); 1673 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1674 virtual void CalcDShape(const IntegrationPoint &ip, 1675 DenseMatrix &dshape) const; ProjectDelta(int vertex,Vector & dofs) const1676 virtual void ProjectDelta(int vertex, Vector &dofs) const 1677 { dofs(0) = 1.0; } 1678 }; 1679 1680 /// A 3D constant element on a cube 1681 class P0HexFiniteElement : public NodalFiniteElement 1682 { 1683 public: 1684 /// Construct the P0HexFiniteElement 1685 P0HexFiniteElement (); 1686 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1687 virtual void CalcDShape(const IntegrationPoint &ip, 1688 DenseMatrix &dshape) const; ProjectDelta(int vertex,Vector & dofs) const1689 virtual void ProjectDelta(int vertex, Vector &dofs) const 1690 { dofs(0) = 1.0; } 1691 }; 1692 1693 /** @brief Tensor products of 1D Lagrange1DFiniteElement 1694 (only degree 2 is functional) */ 1695 class LagrangeHexFiniteElement : public NodalFiniteElement 1696 { 1697 private: 1698 Lagrange1DFiniteElement * fe1d; 1699 int dof1d; 1700 int *I, *J, *K; 1701 #ifndef MFEM_THREAD_SAFE 1702 mutable Vector shape1dx, shape1dy, shape1dz; 1703 mutable DenseMatrix dshape1dx, dshape1dy, dshape1dz; 1704 #endif 1705 1706 public: 1707 /// Construct the LagrangeHexFiniteElement with the provided @a degree 1708 LagrangeHexFiniteElement (int degree); 1709 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1710 virtual void CalcDShape(const IntegrationPoint &ip, 1711 DenseMatrix &dshape) const; 1712 ~LagrangeHexFiniteElement (); 1713 }; 1714 1715 1716 /// A 1D refined linear element 1717 class RefinedLinear1DFiniteElement : public NodalFiniteElement 1718 { 1719 public: 1720 /// Construct the RefinedLinear1DFiniteElement 1721 RefinedLinear1DFiniteElement(); 1722 1723 /** virtual function which evaluates the values of all 1724 shape functions at a given point ip and stores 1725 them in the vector shape of dimension Dof (3) */ 1726 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1727 1728 /** virtual function which evaluates the derivatives of all 1729 shape functions at a given point ip and stores them in 1730 the matrix dshape (Dof x Dim) (3 x 1) so that each row 1731 contains the derivative of one shape function */ 1732 virtual void CalcDShape(const IntegrationPoint &ip, 1733 DenseMatrix &dshape) const; 1734 }; 1735 1736 /// A 2D refined linear element on a triangle 1737 class RefinedLinear2DFiniteElement : public NodalFiniteElement 1738 { 1739 public: 1740 /// Construct the RefinedLinear2DFiniteElement 1741 RefinedLinear2DFiniteElement(); 1742 1743 /** virtual function which evaluates the values of all 1744 shape functions at a given point ip and stores 1745 them in the vector shape of dimension Dof (6) */ 1746 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1747 1748 /** virtual function which evaluates the values of all 1749 partial derivatives of all shape functions at a given 1750 point ip and stores them in the matrix dshape (Dof x Dim) (6 x 2) 1751 so that each row contains the derivatives of one shape function */ 1752 virtual void CalcDShape(const IntegrationPoint &ip, 1753 DenseMatrix &dshape) const; 1754 }; 1755 1756 /// A 2D refined linear element on a tetrahedron 1757 class RefinedLinear3DFiniteElement : public NodalFiniteElement 1758 { 1759 public: 1760 /// Construct the RefinedLinear3DFiniteElement 1761 RefinedLinear3DFiniteElement(); 1762 1763 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1764 1765 virtual void CalcDShape(const IntegrationPoint &ip, 1766 DenseMatrix &dshape) const; 1767 }; 1768 1769 /// A 2D refined bi-linear FE on a square 1770 class RefinedBiLinear2DFiniteElement : public NodalFiniteElement 1771 { 1772 public: 1773 /// Construct the RefinedBiLinear2DFiniteElement 1774 RefinedBiLinear2DFiniteElement(); 1775 1776 /** virtual function which evaluates the values of all 1777 shape functions at a given point ip and stores 1778 them in the vector shape of dimension Dof (9) */ 1779 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1780 1781 /** virtual function which evaluates the values of all 1782 partial derivatives of all shape functions at a given 1783 point ip and stores them in the matrix dshape (Dof x Dim) (9 x 2) 1784 so that each row contains the derivatives of one shape function */ 1785 virtual void CalcDShape(const IntegrationPoint &ip, 1786 DenseMatrix &dshape) const; 1787 }; 1788 1789 /// A 3D refined tri-linear element on a cube 1790 class RefinedTriLinear3DFiniteElement : public NodalFiniteElement 1791 { 1792 public: 1793 /// Construct the RefinedTriLinear3DFiniteElement 1794 RefinedTriLinear3DFiniteElement(); 1795 1796 /** virtual function which evaluates the values of all 1797 shape functions at a given point ip and stores 1798 them in the vector shape of dimension Dof (9) */ 1799 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1800 1801 /** virtual function which evaluates the values of all 1802 partial derivatives of all shape functions at a given 1803 point ip and stores them in the matrix dshape (Dof x Dim) (9 x 2) 1804 so that each row contains the derivatives of one shape function */ 1805 virtual void CalcDShape(const IntegrationPoint &ip, 1806 DenseMatrix &dshape) const; 1807 }; 1808 1809 1810 /// A 3D 1st order Nedelec element on a cube 1811 class Nedelec1HexFiniteElement : public VectorFiniteElement 1812 { 1813 private: 1814 static const double tk[12][3]; 1815 1816 public: 1817 /// Construct the Nedelec1HexFiniteElement 1818 Nedelec1HexFiniteElement(); 1819 virtual void CalcVShape(const IntegrationPoint &ip, 1820 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1821 virtual void CalcVShape(ElementTransformation &Trans, 1822 DenseMatrix &shape) const 1823 { CalcVShape_ND(Trans, shape); } 1824 virtual void CalcCurlShape(const IntegrationPoint &ip, 1825 DenseMatrix &curl_shape) const; 1826 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1827 DenseMatrix &I) const; 1828 using FiniteElement::Project; 1829 virtual void Project (VectorCoefficient &vc, 1830 ElementTransformation &Trans, Vector &dofs) const; 1831 }; 1832 1833 1834 /// A 3D 1st order Nedelec element on a tetrahedron 1835 class Nedelec1TetFiniteElement : public VectorFiniteElement 1836 { 1837 private: 1838 static const double tk[6][3]; 1839 1840 public: 1841 /// Construct the Nedelec1TetFiniteElement 1842 Nedelec1TetFiniteElement(); 1843 virtual void CalcVShape(const IntegrationPoint &ip, 1844 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1845 virtual void CalcVShape(ElementTransformation &Trans, 1846 DenseMatrix &shape) const 1847 { CalcVShape_ND(Trans, shape); } 1848 virtual void CalcCurlShape(const IntegrationPoint &ip, 1849 DenseMatrix &curl_shape) const; 1850 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1851 DenseMatrix &I) const; 1852 using FiniteElement::Project; 1853 virtual void Project (VectorCoefficient &vc, 1854 ElementTransformation &Trans, Vector &dofs) const; 1855 }; 1856 1857 1858 /// A 3D 0th order Raviert-Thomas element on a cube 1859 class RT0HexFiniteElement : public VectorFiniteElement 1860 { 1861 private: 1862 static const double nk[6][3]; 1863 1864 public: 1865 /// Construct the RT0HexFiniteElement 1866 RT0HexFiniteElement(); 1867 1868 virtual void CalcVShape(const IntegrationPoint &ip, 1869 DenseMatrix &shape) const; 1870 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1871 virtual void CalcVShape(ElementTransformation &Trans, 1872 DenseMatrix &shape) const 1873 { CalcVShape_RT(Trans, shape); } 1874 1875 virtual void CalcDivShape(const IntegrationPoint &ip, 1876 Vector &divshape) const; 1877 1878 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1879 DenseMatrix &I) const; 1880 1881 using FiniteElement::Project; 1882 1883 virtual void Project (VectorCoefficient &vc, 1884 ElementTransformation &Trans, Vector &dofs) const; 1885 }; 1886 1887 1888 /// A 3D 1st order Raviert-Thomas element on a cube 1889 class RT1HexFiniteElement : public VectorFiniteElement 1890 { 1891 private: 1892 static const double nk[36][3]; 1893 1894 public: 1895 /// Construct the RT1HexFiniteElement 1896 RT1HexFiniteElement(); 1897 1898 virtual void CalcVShape(const IntegrationPoint &ip, 1899 DenseMatrix &shape) const; 1900 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1901 virtual void CalcVShape(ElementTransformation &Trans, 1902 DenseMatrix &shape) const 1903 { CalcVShape_RT(Trans, shape); } 1904 1905 virtual void CalcDivShape(const IntegrationPoint &ip, 1906 Vector &divshape) const; 1907 1908 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1909 DenseMatrix &I) const; 1910 1911 using FiniteElement::Project; 1912 1913 virtual void Project (VectorCoefficient &vc, 1914 ElementTransformation &Trans, Vector &dofs) const; 1915 }; 1916 1917 1918 /// A 3D 0th order Raviert-Thomas element on a tetrahedron 1919 class RT0TetFiniteElement : public VectorFiniteElement 1920 { 1921 private: 1922 static const double nk[4][3]; 1923 1924 public: 1925 /// Construct the RT0TetFiniteElement 1926 RT0TetFiniteElement(); 1927 1928 virtual void CalcVShape(const IntegrationPoint &ip, 1929 DenseMatrix &shape) const; 1930 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const1931 virtual void CalcVShape(ElementTransformation &Trans, 1932 DenseMatrix &shape) const 1933 { CalcVShape_RT(Trans, shape); } 1934 1935 virtual void CalcDivShape(const IntegrationPoint &ip, 1936 Vector &divshape) const; 1937 1938 virtual void GetLocalInterpolation (ElementTransformation &Trans, 1939 DenseMatrix &I) const; 1940 1941 using FiniteElement::Project; 1942 1943 virtual void Project (VectorCoefficient &vc, 1944 ElementTransformation &Trans, Vector &dofs) const; 1945 }; 1946 1947 1948 class RotTriLinearHexFiniteElement : public NodalFiniteElement 1949 { 1950 public: 1951 /// Construct the RotTriLinearHexFiniteElement 1952 RotTriLinearHexFiniteElement(); 1953 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 1954 virtual void CalcDShape(const IntegrationPoint &ip, 1955 DenseMatrix &dshape) const; 1956 }; 1957 1958 1959 /// Class for computing 1D special polynomials and their associated basis 1960 /// functions 1961 class Poly_1D 1962 { 1963 public: 1964 enum EvalType 1965 { 1966 ChangeOfBasis = 0, // Use change of basis, O(p^2) Evals 1967 Barycentric = 1, // Use barycentric Lagrangian interpolation, O(p) Evals 1968 Positive = 2, // Fast evaluation of Bernstein polynomials 1969 Integrated = 3, // Integrated indicator functions (cf. Gerritsma) 1970 NumEvalTypes = 4 // Keep count of the number of eval types 1971 }; 1972 1973 class Basis 1974 { 1975 private: 1976 int etype; 1977 DenseMatrixInverse Ai; 1978 mutable Vector x, w; 1979 // The following data members are used for "integrated basis type", which 1980 // is defined in terms of nodal basis of one degree higher. 1981 mutable Vector u_aux, d_aux, d2_aux; 1982 Basis *auxiliary_basis; // Non-NULL only for etype == Integrated 1983 1984 public: 1985 /// Create a nodal or positive (Bernstein) basis 1986 Basis(const int p, const double *nodes, EvalType etype = Barycentric); 1987 void Eval(const double x, Vector &u) const; 1988 void Eval(const double x, Vector &u, Vector &d) const; 1989 void Eval(const double x, Vector &u, Vector &d, Vector &d2) const; 1990 /// Evaluate the "integrated" basis, which is given by the negative 1991 /// partial sum of the corresponding closed basis derivatives. The closed 1992 /// basis derivatives are given by @a d, and the result is stored in @a i. 1993 void EvalIntegrated(const Vector &d, Vector &i) const; IsIntegratedType() const1994 bool IsIntegratedType() const { return etype == Integrated; } 1995 ~Basis(); 1996 }; 1997 1998 private: 1999 typedef std::map< int, Array<double*>* > PointsMap; 2000 typedef std::map< int, Array<Basis*>* > BasisMap; 2001 2002 MemoryType h_mt; 2003 PointsMap points_container; 2004 BasisMap bases_container; 2005 2006 static Array2D<int> binom; 2007 2008 static void CalcMono(const int p, const double x, double *u); 2009 static void CalcMono(const int p, const double x, double *u, double *d); 2010 2011 static void CalcChebyshev(const int p, const double x, double *u); 2012 static void CalcChebyshev(const int p, const double x, double *u, double *d); 2013 static void CalcChebyshev(const int p, const double x, double *u, double *d, 2014 double *dd); 2015 2016 QuadratureFunctions1D quad_func; 2017 2018 public: Poly_1D()2019 Poly_1D(): h_mt(MemoryType::HOST) { } 2020 2021 /** @brief Get a pointer to an array containing the binomial coefficients "p 2022 choose k" for k=0,...,p for the given p. */ 2023 static const int *Binom(const int p); 2024 2025 /** @brief Get the coordinates of the points of the given BasisType, 2026 @a btype. 2027 2028 @param[in] p The polynomial degree; the number of points is `p+1`. 2029 @param[in] btype The BasisType. 2030 2031 @return A pointer to an array containing the `p+1` coordinates of the 2032 points. Returns NULL if the BasisType has no associated set of 2033 points. */ 2034 const double *GetPoints(const int p, const int btype); 2035 2036 /// Get coordinates of an open (GaussLegendre) set of points if degree @a p OpenPoints(const int p,const int btype=BasisType::GaussLegendre)2037 const double *OpenPoints(const int p, 2038 const int btype = BasisType::GaussLegendre) 2039 { return GetPoints(p, btype); } 2040 2041 /// Get coordinates of a closed (GaussLegendre) set of points if degree @a p ClosedPoints(const int p,const int btype=BasisType::GaussLobatto)2042 const double *ClosedPoints(const int p, 2043 const int btype = BasisType::GaussLobatto) 2044 { return GetPoints(p, btype); } 2045 2046 /** @brief Get a Poly_1D::Basis object of the given degree and BasisType, 2047 @a btype. 2048 2049 @param[in] p The polynomial degree of the basis. 2050 @param[in] btype The BasisType. 2051 2052 @return A reference to an object of type Poly_1D::Basis that represents 2053 the requested basis type. */ 2054 Basis &GetBasis(const int p, const int btype); 2055 2056 /** @brief Evaluate the values of a hierarchical 1D basis at point x 2057 hierarchical = k-th basis function is degree k polynomial */ CalcBasis(const int p,const double x,double * u)2058 static void CalcBasis(const int p, const double x, double *u) 2059 // { CalcMono(p, x, u); } 2060 // Bernstein basis is not hierarchical --> does not work for triangles 2061 // and tetrahedra 2062 // { CalcBernstein(p, x, u); } 2063 // { CalcLegendre(p, x, u); } 2064 { CalcChebyshev(p, x, u); } 2065 2066 /// Evaluate the values and derivatives of a hierarchical 1D basis at point @a x CalcBasis(const int p,const double x,double * u,double * d)2067 static void CalcBasis(const int p, const double x, double *u, double *d) 2068 // { CalcMono(p, x, u, d); } 2069 // { CalcBernstein(p, x, u, d); } 2070 // { CalcLegendre(p, x, u, d); } 2071 { CalcChebyshev(p, x, u, d); } 2072 2073 /// Evaluate the values, derivatives and second derivatives of a hierarchical 1D basis at point x CalcBasis(const int p,const double x,double * u,double * d,double * dd)2074 static void CalcBasis(const int p, const double x, double *u, double *d, 2075 double *dd) 2076 // { CalcMono(p, x, u, d); } 2077 // { CalcBernstein(p, x, u, d); } 2078 // { CalcLegendre(p, x, u, d); } 2079 { CalcChebyshev(p, x, u, d, dd); } 2080 2081 /// Evaluate a representation of a Delta function at point x CalcDelta(const int p,const double x)2082 static double CalcDelta(const int p, const double x) 2083 { return pow(x, (double) p); } 2084 2085 /** @brief Compute the points for the Chebyshev polynomials of order @a p 2086 and place them in the already allocated @a x array. */ 2087 static void ChebyshevPoints(const int p, double *x); 2088 2089 /** @brief Compute the @a p terms in the expansion of the binomial (x + y)^p 2090 and store them in the already allocated @a u array. */ 2091 static void CalcBinomTerms(const int p, const double x, const double y, 2092 double *u); 2093 /** @brief Compute the terms in the expansion of the binomial (x + y)^p and 2094 their derivatives with respect to x assuming that dy/dx = -1. Store the 2095 results in the already allocated @a u and @a d arrays.*/ 2096 static void CalcBinomTerms(const int p, const double x, const double y, 2097 double *u, double *d); 2098 /** @brief Compute the derivatives (w.r.t. x) of the terms in the expansion 2099 of the binomial (x + y)^p assuming that dy/dx = -1. Store the results 2100 in the already allocated @a d array.*/ 2101 static void CalcDBinomTerms(const int p, const double x, const double y, 2102 double *d); 2103 2104 /** @brief Compute the values of the Bernstein basis functions of order 2105 @a p at coordinate @a x and store the results in the already allocated 2106 @a u array. */ CalcBernstein(const int p,const double x,double * u)2107 static void CalcBernstein(const int p, const double x, double *u) 2108 { CalcBinomTerms(p, x, 1. - x, u); } 2109 2110 /** @brief Compute the values and derivatives of the Bernstein basis functions 2111 of order @a p at coordinate @a x and store the results in the already allocated 2112 @a u and @a d arrays. */ CalcBernstein(const int p,const double x,double * u,double * d)2113 static void CalcBernstein(const int p, const double x, double *u, double *d) 2114 { CalcBinomTerms(p, x, 1. - x, u, d); } 2115 2116 static void CalcLegendre(const int p, const double x, double *u); 2117 static void CalcLegendre(const int p, const double x, double *u, double *d); 2118 2119 ~Poly_1D(); 2120 }; 2121 2122 extern Poly_1D poly1d; 2123 2124 2125 /// An element defined as an ND tensor product of 1D elements on a segment, 2126 /// square, or cube 2127 class TensorBasisElement 2128 { 2129 protected: 2130 int b_type; 2131 Array<int> dof_map; 2132 Poly_1D::Basis &basis1d; 2133 Array<int> inv_dof_map; 2134 2135 public: 2136 enum DofMapType 2137 { 2138 L2_DOF_MAP = 0, 2139 H1_DOF_MAP = 1, 2140 Sr_DOF_MAP = 2, // Sr = Serendipity 2141 }; 2142 2143 TensorBasisElement(const int dims, const int p, const int btype, 2144 const DofMapType dmtype); 2145 GetBasisType() const2146 int GetBasisType() const { return b_type; } 2147 GetBasis1D() const2148 const Poly_1D::Basis& GetBasis1D() const { return basis1d; } 2149 2150 /** @brief Get an Array<int> that maps lexicographically ordered indices to 2151 the indices of the respective nodes/dofs/basis functions. If the dofs are 2152 ordered lexicographically, i.e. the mapping is identity, the returned 2153 Array will be empty. */ GetDofMap() const2154 const Array<int> &GetDofMap() const { return dof_map; } 2155 GetTensorProductGeometry(int dim)2156 static Geometry::Type GetTensorProductGeometry(int dim) 2157 { 2158 switch (dim) 2159 { 2160 case 1: return Geometry::SEGMENT; 2161 case 2: return Geometry::SQUARE; 2162 case 3: return Geometry::CUBE; 2163 default: 2164 MFEM_ABORT("invalid dimension: " << dim); 2165 return Geometry::INVALID; 2166 } 2167 } 2168 2169 /// Return @a base raised to the power @a dim. Pow(int base,int dim)2170 static int Pow(int base, int dim) 2171 { 2172 switch (dim) 2173 { 2174 case 1: return base; 2175 case 2: return base*base; 2176 case 3: return base*base*base; 2177 default: MFEM_ABORT("invalid dimension: " << dim); return -1; 2178 } 2179 } 2180 }; 2181 2182 class NodalTensorFiniteElement : public NodalFiniteElement, 2183 public TensorBasisElement 2184 { 2185 public: 2186 NodalTensorFiniteElement(const int dims, const int p, const int btype, 2187 const DofMapType dmtype); 2188 GetDofToQuad(const IntegrationRule & ir,DofToQuad::Mode mode) const2189 const DofToQuad &GetDofToQuad(const IntegrationRule &ir, 2190 DofToQuad::Mode mode) const 2191 { 2192 return (mode == DofToQuad::FULL) ? 2193 ScalarFiniteElement::GetDofToQuad(ir, mode) : 2194 ScalarFiniteElement::GetTensorDofToQuad(*this, ir, mode); 2195 } 2196 GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const2197 virtual void GetTransferMatrix(const FiniteElement &fe, 2198 ElementTransformation &Trans, 2199 DenseMatrix &I) const 2200 { 2201 if (basis1d.IsIntegratedType()) 2202 { 2203 CheckScalarFE(fe).ScalarLocalInterpolation(Trans, I, *this); 2204 } 2205 else 2206 { 2207 NodalFiniteElement::GetTransferMatrix(fe, Trans, I); 2208 } 2209 } 2210 }; 2211 2212 class PositiveTensorFiniteElement : public PositiveFiniteElement, 2213 public TensorBasisElement 2214 { 2215 public: 2216 PositiveTensorFiniteElement(const int dims, const int p, 2217 const DofMapType dmtype); 2218 GetDofToQuad(const IntegrationRule & ir,DofToQuad::Mode mode) const2219 const DofToQuad &GetDofToQuad(const IntegrationRule &ir, 2220 DofToQuad::Mode mode) const 2221 { 2222 return (mode == DofToQuad::FULL) ? 2223 ScalarFiniteElement::GetDofToQuad(ir, mode) : 2224 ScalarFiniteElement::GetTensorDofToQuad(*this, ir, mode); 2225 } 2226 }; 2227 2228 class VectorTensorFiniteElement : public VectorFiniteElement, 2229 public TensorBasisElement 2230 { 2231 private: 2232 mutable Array<DofToQuad*> dof2quad_array_open; 2233 2234 protected: 2235 Poly_1D::Basis &cbasis1d, &obasis1d; 2236 2237 public: 2238 VectorTensorFiniteElement(const int dims, const int d, const int p, 2239 const int cbtype, const int obtype, 2240 const int M, const DofMapType dmtype); 2241 2242 // For 1D elements: there is only an "open basis", no "closed basis" 2243 VectorTensorFiniteElement(const int dims, const int d, const int p, 2244 const int obtype, const int M, 2245 const DofMapType dmtype); 2246 2247 const DofToQuad &GetDofToQuad(const IntegrationRule &ir, 2248 DofToQuad::Mode mode) const; 2249 2250 const DofToQuad &GetDofToQuadOpen(const IntegrationRule &ir, 2251 DofToQuad::Mode mode) const; 2252 2253 const DofToQuad &GetTensorDofToQuad(const IntegrationRule &ir, 2254 DofToQuad::Mode mode, 2255 const bool closed) const; 2256 2257 ~VectorTensorFiniteElement(); 2258 }; 2259 2260 /// Arbitrary H1 elements in 1D 2261 class H1_SegmentElement : public NodalTensorFiniteElement 2262 { 2263 private: 2264 #ifndef MFEM_THREAD_SAFE 2265 mutable Vector shape_x, dshape_x, d2shape_x; 2266 #endif 2267 2268 public: 2269 /// Construct the H1_SegmentElement of order @a p and BasisType @a btype 2270 H1_SegmentElement(const int p, const int btype = BasisType::GaussLobatto); 2271 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2272 virtual void CalcDShape(const IntegrationPoint &ip, 2273 DenseMatrix &dshape) const; 2274 virtual void CalcHessian(const IntegrationPoint &ip, 2275 DenseMatrix &Hessian) const; 2276 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2277 }; 2278 2279 2280 /// Arbitrary H1 elements in 2D on a square 2281 class H1_QuadrilateralElement : public NodalTensorFiniteElement 2282 { 2283 private: 2284 #ifndef MFEM_THREAD_SAFE 2285 mutable Vector shape_x, shape_y, dshape_x, dshape_y, d2shape_x, d2shape_y; 2286 #endif 2287 2288 public: 2289 /// Construct the H1_QuadrilateralElement of order @a p and BasisType @a btype 2290 H1_QuadrilateralElement(const int p, 2291 const int btype = BasisType::GaussLobatto); 2292 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2293 virtual void CalcDShape(const IntegrationPoint &ip, 2294 DenseMatrix &dshape) const; 2295 virtual void CalcHessian(const IntegrationPoint &ip, 2296 DenseMatrix &Hessian) const; 2297 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2298 }; 2299 2300 2301 /// Arbitrary H1 elements in 3D on a cube 2302 class H1_HexahedronElement : public NodalTensorFiniteElement 2303 { 2304 private: 2305 #ifndef MFEM_THREAD_SAFE 2306 mutable Vector shape_x, shape_y, shape_z, dshape_x, dshape_y, dshape_z, 2307 d2shape_x, d2shape_y, d2shape_z; 2308 #endif 2309 2310 public: 2311 /// Construct the H1_HexahedronElement of order @a p and BasisType @a btype 2312 H1_HexahedronElement(const int p, const int btype = BasisType::GaussLobatto); 2313 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2314 virtual void CalcDShape(const IntegrationPoint &ip, 2315 DenseMatrix &dshape) const; 2316 virtual void CalcHessian(const IntegrationPoint &ip, 2317 DenseMatrix &Hessian) const; 2318 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2319 }; 2320 2321 /// Arbitrary order H1 elements in 1D utilizing the Bernstein basis 2322 class H1Pos_SegmentElement : public PositiveTensorFiniteElement 2323 { 2324 private: 2325 #ifndef MFEM_THREAD_SAFE 2326 // This is to share scratch space between invocations, which helps speed 2327 // things up, but with OpenMP, we need one copy per thread. Right now, we 2328 // solve this by allocating this space within each function call every time 2329 // we call it. Alternatively, we should do some sort thread private thing. 2330 // Brunner, Jan 2014 2331 mutable Vector shape_x, dshape_x; 2332 #endif 2333 2334 public: 2335 /// Construct the H1Pos_SegmentElement of order @a p 2336 H1Pos_SegmentElement(const int p); 2337 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2338 virtual void CalcDShape(const IntegrationPoint &ip, 2339 DenseMatrix &dshape) const; 2340 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2341 }; 2342 2343 2344 /// Arbitrary order H1 elements in 2D utilizing the Bernstein basis on a square 2345 class H1Pos_QuadrilateralElement : public PositiveTensorFiniteElement 2346 { 2347 private: 2348 #ifndef MFEM_THREAD_SAFE 2349 // See comment in H1Pos_SegmentElement 2350 mutable Vector shape_x, shape_y, dshape_x, dshape_y; 2351 #endif 2352 2353 public: 2354 /// Construct the H1Pos_QuadrilateralElement of order @a p 2355 H1Pos_QuadrilateralElement(const int p); 2356 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2357 virtual void CalcDShape(const IntegrationPoint &ip, 2358 DenseMatrix &dshape) const; 2359 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2360 }; 2361 2362 2363 /// Arbitrary order H1 serendipity elements in 2D on a quad 2364 class H1Ser_QuadrilateralElement : public ScalarFiniteElement 2365 { 2366 public: 2367 /// Construct the H1Ser_QuadrilateralElement of order @a p 2368 H1Ser_QuadrilateralElement(const int p); 2369 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2370 virtual void CalcDShape(const IntegrationPoint &ip, 2371 DenseMatrix &dshape) const; 2372 virtual void GetLocalInterpolation(ElementTransformation &Trans, 2373 DenseMatrix &I) const; 2374 using FiniteElement::Project; 2375 }; 2376 2377 /// Arbitrary order H1 elements in 3D utilizing the Bernstein basis on a cube 2378 class H1Pos_HexahedronElement : public PositiveTensorFiniteElement 2379 { 2380 private: 2381 #ifndef MFEM_THREAD_SAFE 2382 // See comment in H1Pos_SegementElement. 2383 mutable Vector shape_x, shape_y, shape_z, dshape_x, dshape_y, dshape_z; 2384 #endif 2385 2386 public: 2387 /// Construct the H1Pos_HexahedronElement of order @a p 2388 H1Pos_HexahedronElement(const int p); 2389 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2390 virtual void CalcDShape(const IntegrationPoint &ip, 2391 DenseMatrix &dshape) const; 2392 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2393 }; 2394 2395 2396 /// Arbitrary order H1 elements in 2D on a triangle 2397 class H1_TriangleElement : public NodalFiniteElement 2398 { 2399 private: 2400 #ifndef MFEM_THREAD_SAFE 2401 mutable Vector shape_x, shape_y, shape_l, dshape_x, dshape_y, dshape_l, u; 2402 mutable Vector ddshape_x, ddshape_y, ddshape_l; 2403 mutable DenseMatrix du, ddu; 2404 #endif 2405 DenseMatrixInverse Ti; 2406 2407 public: 2408 /// Construct the H1_TriangleElement of order @a p and BasisType @a btype 2409 H1_TriangleElement(const int p, const int btype = BasisType::GaussLobatto); 2410 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2411 virtual void CalcDShape(const IntegrationPoint &ip, 2412 DenseMatrix &dshape) const; 2413 virtual void CalcHessian(const IntegrationPoint &ip, 2414 DenseMatrix &ddshape) const; 2415 }; 2416 2417 2418 /// Arbitrary order H1 elements in 3D on a tetrahedron 2419 class H1_TetrahedronElement : public NodalFiniteElement 2420 { 2421 private: 2422 #ifndef MFEM_THREAD_SAFE 2423 mutable Vector shape_x, shape_y, shape_z, shape_l; 2424 mutable Vector dshape_x, dshape_y, dshape_z, dshape_l, u; 2425 mutable Vector ddshape_x, ddshape_y, ddshape_z, ddshape_l; 2426 mutable DenseMatrix du, ddu; 2427 #endif 2428 DenseMatrixInverse Ti; 2429 2430 public: 2431 /// Construct the H1_TetrahedronElement of order @a p and BasisType @a btype 2432 H1_TetrahedronElement(const int p, 2433 const int btype = BasisType::GaussLobatto); 2434 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2435 virtual void CalcDShape(const IntegrationPoint &ip, 2436 DenseMatrix &dshape) const; 2437 virtual void CalcHessian(const IntegrationPoint &ip, 2438 DenseMatrix &ddshape) const; 2439 }; 2440 2441 2442 /// Arbitrary order H1 elements in 2D utilizing the Bernstein basis on a triangle 2443 class H1Pos_TriangleElement : public PositiveFiniteElement 2444 { 2445 protected: 2446 #ifndef MFEM_THREAD_SAFE 2447 mutable Vector m_shape, dshape_1d; 2448 mutable DenseMatrix m_dshape; 2449 #endif 2450 Array<int> dof_map; 2451 2452 public: 2453 /// Construct the H1Pos_TriangleElement of order @a p 2454 H1Pos_TriangleElement(const int p); 2455 2456 // The size of shape is (p+1)(p+2)/2 (dof). 2457 static void CalcShape(const int p, const double x, const double y, 2458 double *shape); 2459 2460 // The size of dshape_1d is p+1; the size of dshape is (dof x dim). 2461 static void CalcDShape(const int p, const double x, const double y, 2462 double *dshape_1d, double *dshape); 2463 2464 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2465 virtual void CalcDShape(const IntegrationPoint &ip, 2466 DenseMatrix &dshape) const; 2467 }; 2468 2469 2470 /// Arbitrary order H1 elements in 3D utilizing the Bernstein basis on a 2471 /// tetrahedron 2472 class H1Pos_TetrahedronElement : public PositiveFiniteElement 2473 { 2474 protected: 2475 #ifndef MFEM_THREAD_SAFE 2476 mutable Vector m_shape, dshape_1d; 2477 mutable DenseMatrix m_dshape; 2478 #endif 2479 Array<int> dof_map; 2480 2481 public: 2482 /// Construct the H1Pos_TetrahedronElement of order @a p 2483 H1Pos_TetrahedronElement(const int p); 2484 2485 // The size of shape is (p+1)(p+2)(p+3)/6 (dof). 2486 static void CalcShape(const int p, const double x, const double y, 2487 const double z, double *shape); 2488 2489 // The size of dshape_1d is p+1; the size of dshape is (dof x dim). 2490 static void CalcDShape(const int p, const double x, const double y, 2491 const double z, double *dshape_1d, double *dshape); 2492 2493 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2494 virtual void CalcDShape(const IntegrationPoint &ip, 2495 DenseMatrix &dshape) const; 2496 }; 2497 2498 2499 /// Arbitrary order H1 elements in 3D on a wedge 2500 class H1_WedgeElement : public NodalFiniteElement 2501 { 2502 private: 2503 #ifndef MFEM_THREAD_SAFE 2504 mutable Vector t_shape, s_shape; 2505 mutable DenseMatrix t_dshape, s_dshape; 2506 #endif 2507 Array<int> t_dof, s_dof; 2508 2509 H1_TriangleElement TriangleFE; 2510 H1_SegmentElement SegmentFE; 2511 2512 public: 2513 /// Construct the H1_WedgeElement of order @a p and BasisType @a btype 2514 H1_WedgeElement(const int p, 2515 const int btype = BasisType::GaussLobatto); 2516 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2517 virtual void CalcDShape(const IntegrationPoint &ip, 2518 DenseMatrix &dshape) const; 2519 }; 2520 2521 /// Class for linear FE on wedge 2522 class BiLinear3DFiniteElement : public H1_WedgeElement 2523 { 2524 public: 2525 /// Construct a linear FE on wedge BiLinear3DFiniteElement()2526 BiLinear3DFiniteElement() : H1_WedgeElement(1) {} 2527 }; 2528 2529 /// Class for quadratic FE on wedge 2530 class BiQuadratic3DFiniteElement : public H1_WedgeElement 2531 { 2532 public: 2533 /// Construct a quadratic FE on wedge BiQuadratic3DFiniteElement()2534 BiQuadratic3DFiniteElement() : H1_WedgeElement(2) {} 2535 }; 2536 2537 /// Class for cubic FE on wedge 2538 class BiCubic3DFiniteElement : public H1_WedgeElement 2539 { 2540 public: 2541 /// Construct a cubic FE on wedge BiCubic3DFiniteElement()2542 BiCubic3DFiniteElement() : H1_WedgeElement(3) {} 2543 }; 2544 2545 /// Arbitrary order H1 elements in 3D utilizing the Bernstein basis on a wedge 2546 class H1Pos_WedgeElement : public PositiveFiniteElement 2547 { 2548 protected: 2549 #ifndef MFEM_THREAD_SAFE 2550 mutable Vector t_shape, s_shape; 2551 mutable DenseMatrix t_dshape, s_dshape; 2552 #endif 2553 Array<int> t_dof, s_dof; 2554 2555 H1Pos_TriangleElement TriangleFE; 2556 H1Pos_SegmentElement SegmentFE; 2557 2558 public: 2559 /// Construct the H1Pos_WedgeElement of order @a p 2560 H1Pos_WedgeElement(const int p); 2561 2562 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2563 virtual void CalcDShape(const IntegrationPoint &ip, 2564 DenseMatrix &dshape) const; 2565 }; 2566 2567 2568 /// Arbitrary L2 elements in 1D on a segment 2569 class L2_SegmentElement : public NodalTensorFiniteElement 2570 { 2571 private: 2572 #ifndef MFEM_THREAD_SAFE 2573 mutable Vector shape_x, dshape_x; 2574 #endif 2575 2576 public: 2577 /// Construct the L2_SegmentElement of order @a p and BasisType @a btype 2578 L2_SegmentElement(const int p, const int btype = BasisType::GaussLegendre); 2579 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2580 virtual void CalcDShape(const IntegrationPoint &ip, 2581 DenseMatrix &dshape) const; 2582 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2583 }; 2584 2585 /// Arbitrary order L2 elements in 1D utilizing the Bernstein basis on a segment 2586 class L2Pos_SegmentElement : public PositiveTensorFiniteElement 2587 { 2588 private: 2589 #ifndef MFEM_THREAD_SAFE 2590 mutable Vector shape_x, dshape_x; 2591 #endif 2592 2593 public: 2594 /// Construct the L2Pos_SegmentElement of order @a p 2595 L2Pos_SegmentElement(const int p); 2596 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2597 virtual void CalcDShape(const IntegrationPoint &ip, 2598 DenseMatrix &dshape) const; 2599 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2600 }; 2601 2602 2603 /// Arbitrary order L2 elements in 2D on a square 2604 class L2_QuadrilateralElement : public NodalTensorFiniteElement 2605 { 2606 private: 2607 #ifndef MFEM_THREAD_SAFE 2608 mutable Vector shape_x, shape_y, dshape_x, dshape_y; 2609 #endif 2610 2611 public: 2612 /// Construct the L2_QuadrilateralElement of order @a p and BasisType @a btype 2613 L2_QuadrilateralElement(const int p, 2614 const int btype = BasisType::GaussLegendre); 2615 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2616 virtual void CalcDShape(const IntegrationPoint &ip, 2617 DenseMatrix &dshape) const; 2618 virtual void ProjectDelta(int vertex, Vector &dofs) const; ProjectCurl(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const2619 virtual void ProjectCurl(const FiniteElement &fe, 2620 ElementTransformation &Trans, 2621 DenseMatrix &curl) const 2622 { ProjectCurl_2D(fe, Trans, curl); } 2623 }; 2624 2625 /// Arbitrary order L2 elements in 2D utilizing the Bernstein basis on a square 2626 class L2Pos_QuadrilateralElement : public PositiveTensorFiniteElement 2627 { 2628 private: 2629 #ifndef MFEM_THREAD_SAFE 2630 mutable Vector shape_x, shape_y, dshape_x, dshape_y; 2631 #endif 2632 2633 public: 2634 /// Construct the L2Pos_QuadrilateralElement of order @a p 2635 L2Pos_QuadrilateralElement(const int p); 2636 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2637 virtual void CalcDShape(const IntegrationPoint &ip, 2638 DenseMatrix &dshape) const; 2639 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2640 }; 2641 2642 /// Arbitrary order L2 elements in 3D on a cube 2643 class L2_HexahedronElement : public NodalTensorFiniteElement 2644 { 2645 private: 2646 #ifndef MFEM_THREAD_SAFE 2647 mutable Vector shape_x, shape_y, shape_z, dshape_x, dshape_y, dshape_z; 2648 #endif 2649 2650 public: 2651 /// Construct the L2_HexahedronElement of order @a p and BasisType @a btype 2652 L2_HexahedronElement(const int p, 2653 const int btype = BasisType::GaussLegendre); 2654 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2655 virtual void CalcDShape(const IntegrationPoint &ip, 2656 DenseMatrix &dshape) const; 2657 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2658 }; 2659 2660 2661 /// Arbitrary order L2 elements in 3D utilizing the Bernstein basis on a cube 2662 class L2Pos_HexahedronElement : public PositiveTensorFiniteElement 2663 { 2664 private: 2665 #ifndef MFEM_THREAD_SAFE 2666 mutable Vector shape_x, shape_y, shape_z, dshape_x, dshape_y, dshape_z; 2667 #endif 2668 2669 public: 2670 /// Construct the L2Pos_HexahedronElement of order @a p 2671 L2Pos_HexahedronElement(const int p); 2672 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2673 virtual void CalcDShape(const IntegrationPoint &ip, 2674 DenseMatrix &dshape) const; 2675 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2676 }; 2677 2678 2679 /// Arbitrary order L2 elements in 2D on a triangle 2680 class L2_TriangleElement : public NodalFiniteElement 2681 { 2682 private: 2683 #ifndef MFEM_THREAD_SAFE 2684 mutable Vector shape_x, shape_y, shape_l, dshape_x, dshape_y, dshape_l, u; 2685 mutable DenseMatrix du; 2686 #endif 2687 DenseMatrixInverse Ti; 2688 2689 public: 2690 /// Construct the L2_TriangleElement of order @a p and BasisType @a btype 2691 L2_TriangleElement(const int p, 2692 const int btype = BasisType::GaussLegendre); 2693 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2694 virtual void CalcDShape(const IntegrationPoint &ip, 2695 DenseMatrix &dshape) const; 2696 virtual void ProjectDelta(int vertex, Vector &dofs) const; ProjectCurl(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const2697 virtual void ProjectCurl(const FiniteElement &fe, 2698 ElementTransformation &Trans, 2699 DenseMatrix &curl) const 2700 { ProjectCurl_2D(fe, Trans, curl); } 2701 }; 2702 2703 /// Arbitrary order L2 elements in 2D utilizing the Bernstein basis on a triangle 2704 class L2Pos_TriangleElement : public PositiveFiniteElement 2705 { 2706 private: 2707 #ifndef MFEM_THREAD_SAFE 2708 mutable Vector dshape_1d; 2709 #endif 2710 2711 public: 2712 /// Construct the L2Pos_TriangleElement of order @a p 2713 L2Pos_TriangleElement(const int p); 2714 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2715 virtual void CalcDShape(const IntegrationPoint &ip, 2716 DenseMatrix &dshape) const; 2717 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2718 }; 2719 2720 2721 /// Arbitrary order L2 elements in 3D on a tetrahedron 2722 class L2_TetrahedronElement : public NodalFiniteElement 2723 { 2724 private: 2725 #ifndef MFEM_THREAD_SAFE 2726 mutable Vector shape_x, shape_y, shape_z, shape_l; 2727 mutable Vector dshape_x, dshape_y, dshape_z, dshape_l, u; 2728 mutable DenseMatrix du; 2729 #endif 2730 DenseMatrixInverse Ti; 2731 2732 public: 2733 /// Construct the L2_TetrahedronElement of order @a p and BasisType @a btype 2734 L2_TetrahedronElement(const int p, 2735 const int btype = BasisType::GaussLegendre); 2736 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2737 virtual void CalcDShape(const IntegrationPoint &ip, 2738 DenseMatrix &dshape) const; 2739 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2740 }; 2741 2742 2743 /// Arbitrary order L2 elements in 3D utilizing the Bernstein basis on a 2744 /// tetrahedron 2745 class L2Pos_TetrahedronElement : public PositiveFiniteElement 2746 { 2747 private: 2748 #ifndef MFEM_THREAD_SAFE 2749 mutable Vector dshape_1d; 2750 #endif 2751 2752 public: 2753 /// Construct the L2Pos_TetrahedronElement of order @a p 2754 L2Pos_TetrahedronElement(const int p); 2755 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2756 virtual void CalcDShape(const IntegrationPoint &ip, 2757 DenseMatrix &dshape) const; 2758 virtual void ProjectDelta(int vertex, Vector &dofs) const; 2759 }; 2760 2761 2762 /// Arbitrary order L2 elements in 3D on a wedge 2763 class L2_WedgeElement : public NodalFiniteElement 2764 { 2765 private: 2766 #ifndef MFEM_THREAD_SAFE 2767 mutable Vector t_shape, s_shape; 2768 mutable DenseMatrix t_dshape, s_dshape; 2769 #endif 2770 Array<int> t_dof, s_dof; 2771 2772 L2_TriangleElement TriangleFE; 2773 L2_SegmentElement SegmentFE; 2774 2775 public: 2776 /// Construct the L2_WedgeElement of order @a p and BasisType @a btype 2777 L2_WedgeElement(const int p, 2778 const int btype = BasisType::GaussLegendre); 2779 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2780 virtual void CalcDShape(const IntegrationPoint &ip, 2781 DenseMatrix &dshape) const; 2782 }; 2783 2784 /// A 0th order L2 element on a Wedge 2785 class P0WedgeFiniteElement : public L2_WedgeElement 2786 { 2787 public: 2788 /// Construct the P0WedgeFiniteElement P0WedgeFiniteElement()2789 P0WedgeFiniteElement () : L2_WedgeElement(0) {} 2790 }; 2791 2792 /// Arbitrary order L2 elements in 3D utilizing the Bernstein basis on a wedge 2793 class L2Pos_WedgeElement : public PositiveFiniteElement 2794 { 2795 protected: 2796 #ifndef MFEM_THREAD_SAFE 2797 mutable Vector t_shape, s_shape; 2798 mutable DenseMatrix t_dshape, s_dshape; 2799 #endif 2800 Array<int> t_dof, s_dof; 2801 2802 L2Pos_TriangleElement TriangleFE; 2803 L2Pos_SegmentElement SegmentFE; 2804 2805 public: 2806 /// Construct the L2Pos_WedgeElement of order @a p 2807 L2Pos_WedgeElement(const int p); 2808 2809 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 2810 virtual void CalcDShape(const IntegrationPoint &ip, 2811 DenseMatrix &dshape) const; 2812 }; 2813 2814 /// Arbitrary order Raviart-Thomas elements in 2D on a square 2815 class RT_QuadrilateralElement : public VectorTensorFiniteElement 2816 { 2817 private: 2818 static const double nk[8]; 2819 2820 #ifndef MFEM_THREAD_SAFE 2821 mutable Vector shape_cx, shape_ox, shape_cy, shape_oy; 2822 mutable Vector dshape_cx, dshape_cy; 2823 #endif 2824 Array<int> dof2nk; 2825 const double *cp; 2826 2827 public: 2828 /** @brief Construct the RT_QuadrilateralElement of order @a p and closed and 2829 open BasisType @a cb_type and @a ob_type */ 2830 RT_QuadrilateralElement(const int p, 2831 const int cb_type = BasisType::GaussLobatto, 2832 const int ob_type = BasisType::GaussLegendre); 2833 virtual void CalcVShape(const IntegrationPoint &ip, 2834 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const2835 virtual void CalcVShape(ElementTransformation &Trans, 2836 DenseMatrix &shape) const 2837 { CalcVShape_RT(Trans, shape); } 2838 virtual void CalcDivShape(const IntegrationPoint &ip, 2839 Vector &divshape) const; GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const2840 virtual void GetLocalInterpolation(ElementTransformation &Trans, 2841 DenseMatrix &I) const 2842 { LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); } GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const2843 virtual void GetLocalRestriction(ElementTransformation &Trans, 2844 DenseMatrix &R) const 2845 { LocalRestriction_RT(nk, dof2nk, Trans, R); } GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const2846 virtual void GetTransferMatrix(const FiniteElement &fe, 2847 ElementTransformation &Trans, 2848 DenseMatrix &I) const 2849 { LocalInterpolation_RT(CheckVectorFE(fe), nk, dof2nk, Trans, I); } 2850 using FiniteElement::Project; Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const2851 virtual void Project(VectorCoefficient &vc, 2852 ElementTransformation &Trans, Vector &dofs) const 2853 { 2854 if (obasis1d.IsIntegratedType()) { ProjectIntegrated(vc, Trans, dofs); } 2855 else { Project_RT(nk, dof2nk, vc, Trans, dofs); } 2856 } ProjectFromNodes(Vector & vc,ElementTransformation & Trans,Vector & dofs) const2857 virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, 2858 Vector &dofs) const 2859 { Project_RT(nk, dof2nk, vc, Trans, dofs); } ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const2860 virtual void ProjectMatrixCoefficient( 2861 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const 2862 { ProjectMatrixCoefficient_RT(nk, dof2nk, mc, T, dofs); } Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const2863 virtual void Project(const FiniteElement &fe, ElementTransformation &Trans, 2864 DenseMatrix &I) const 2865 { Project_RT(nk, dof2nk, fe, Trans, I); } 2866 // Gradient + rotation = Curl: H1 -> H(div) ProjectGrad(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const2867 virtual void ProjectGrad(const FiniteElement &fe, 2868 ElementTransformation &Trans, 2869 DenseMatrix &grad) const 2870 { ProjectGrad_RT(nk, dof2nk, fe, Trans, grad); } 2871 // Curl = Gradient + rotation: H1 -> H(div) ProjectCurl(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const2872 virtual void ProjectCurl(const FiniteElement &fe, 2873 ElementTransformation &Trans, 2874 DenseMatrix &curl) const 2875 { ProjectGrad_RT(nk, dof2nk, fe, Trans, curl); } 2876 2877 protected: 2878 void ProjectIntegrated(VectorCoefficient &vc, ElementTransformation &Trans, 2879 Vector &dofs) const; 2880 }; 2881 2882 2883 /// Arbitrary order Raviart-Thomas elements in 3D on a cube 2884 class RT_HexahedronElement : public VectorTensorFiniteElement 2885 { 2886 static const double nk[18]; 2887 2888 #ifndef MFEM_THREAD_SAFE 2889 mutable Vector shape_cx, shape_ox, shape_cy, shape_oy, shape_cz, shape_oz; 2890 mutable Vector dshape_cx, dshape_cy, dshape_cz; 2891 #endif 2892 Array<int> dof2nk; 2893 const double *cp; 2894 2895 public: 2896 /** @brief Construct the RT_HexahedronElement of order @a p and closed and 2897 open BasisType @a cb_type and @a ob_type */ 2898 RT_HexahedronElement(const int p, 2899 const int cb_type = BasisType::GaussLobatto, 2900 const int ob_type = BasisType::GaussLegendre); 2901 2902 virtual void CalcVShape(const IntegrationPoint &ip, 2903 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const2904 virtual void CalcVShape(ElementTransformation &Trans, 2905 DenseMatrix &shape) const 2906 { CalcVShape_RT(Trans, shape); } 2907 virtual void CalcDivShape(const IntegrationPoint &ip, 2908 Vector &divshape) const; GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const2909 virtual void GetLocalInterpolation(ElementTransformation &Trans, 2910 DenseMatrix &I) const 2911 { LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); } GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const2912 virtual void GetLocalRestriction(ElementTransformation &Trans, 2913 DenseMatrix &R) const 2914 { LocalRestriction_RT(nk, dof2nk, Trans, R); } GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const2915 virtual void GetTransferMatrix(const FiniteElement &fe, 2916 ElementTransformation &Trans, 2917 DenseMatrix &I) const 2918 { LocalInterpolation_RT(CheckVectorFE(fe), nk, dof2nk, Trans, I); } 2919 using FiniteElement::Project; Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const2920 virtual void Project(VectorCoefficient &vc, 2921 ElementTransformation &Trans, Vector &dofs) const 2922 { 2923 if (obasis1d.IsIntegratedType()) { ProjectIntegrated(vc, Trans, dofs); } 2924 else { Project_RT(nk, dof2nk, vc, Trans, dofs); } 2925 } ProjectFromNodes(Vector & vc,ElementTransformation & Trans,Vector & dofs) const2926 virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, 2927 Vector &dofs) const 2928 { Project_RT(nk, dof2nk, vc, Trans, dofs); } ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const2929 virtual void ProjectMatrixCoefficient( 2930 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const 2931 { ProjectMatrixCoefficient_RT(nk, dof2nk, mc, T, dofs); } Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const2932 virtual void Project(const FiniteElement &fe, ElementTransformation &Trans, 2933 DenseMatrix &I) const 2934 { Project_RT(nk, dof2nk, fe, Trans, I); } ProjectCurl(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const2935 virtual void ProjectCurl(const FiniteElement &fe, 2936 ElementTransformation &Trans, 2937 DenseMatrix &curl) const 2938 { ProjectCurl_RT(nk, dof2nk, fe, Trans, curl); } 2939 2940 protected: 2941 void ProjectIntegrated(VectorCoefficient &vc, 2942 ElementTransformation &Trans, 2943 Vector &dofs) const; 2944 }; 2945 2946 2947 /// Arbitrary order Raviart-Thomas elements in 2D on a triangle 2948 class RT_TriangleElement : public VectorFiniteElement 2949 { 2950 static const double nk[6], c; 2951 2952 #ifndef MFEM_THREAD_SAFE 2953 mutable Vector shape_x, shape_y, shape_l; 2954 mutable Vector dshape_x, dshape_y, dshape_l; 2955 mutable DenseMatrix u; 2956 mutable Vector divu; 2957 #endif 2958 Array<int> dof2nk; 2959 DenseMatrixInverse Ti; 2960 2961 public: 2962 /// Construct the RT_TriangleElement of order @a p 2963 RT_TriangleElement(const int p); 2964 virtual void CalcVShape(const IntegrationPoint &ip, 2965 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const2966 virtual void CalcVShape(ElementTransformation &Trans, 2967 DenseMatrix &shape) const 2968 { CalcVShape_RT(Trans, shape); } 2969 virtual void CalcDivShape(const IntegrationPoint &ip, 2970 Vector &divshape) const; GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const2971 virtual void GetLocalInterpolation(ElementTransformation &Trans, 2972 DenseMatrix &I) const 2973 { LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); } GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const2974 virtual void GetLocalRestriction(ElementTransformation &Trans, 2975 DenseMatrix &R) const 2976 { LocalRestriction_RT(nk, dof2nk, Trans, R); } GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const2977 virtual void GetTransferMatrix(const FiniteElement &fe, 2978 ElementTransformation &Trans, 2979 DenseMatrix &I) const 2980 { LocalInterpolation_RT(CheckVectorFE(fe), nk, dof2nk, Trans, I); } 2981 using FiniteElement::Project; Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const2982 virtual void Project(VectorCoefficient &vc, 2983 ElementTransformation &Trans, Vector &dofs) const 2984 { Project_RT(nk, dof2nk, vc, Trans, dofs); } ProjectFromNodes(Vector & vc,ElementTransformation & Trans,Vector & dofs) const2985 virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, 2986 Vector &dofs) const 2987 { Project_RT(nk, dof2nk, vc, Trans, dofs); } ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const2988 virtual void ProjectMatrixCoefficient( 2989 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const 2990 { ProjectMatrixCoefficient_RT(nk, dof2nk, mc, T, dofs); } Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const2991 virtual void Project(const FiniteElement &fe, ElementTransformation &Trans, 2992 DenseMatrix &I) const 2993 { Project_RT(nk, dof2nk, fe, Trans, I); } 2994 // Gradient + rotation = Curl: H1 -> H(div) ProjectGrad(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const2995 virtual void ProjectGrad(const FiniteElement &fe, 2996 ElementTransformation &Trans, 2997 DenseMatrix &grad) const 2998 { ProjectGrad_RT(nk, dof2nk, fe, Trans, grad); } 2999 // Curl = Gradient + rotation: H1 -> H(div) ProjectCurl(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const3000 virtual void ProjectCurl(const FiniteElement &fe, 3001 ElementTransformation &Trans, 3002 DenseMatrix &curl) const 3003 { ProjectGrad_RT(nk, dof2nk, fe, Trans, curl); } 3004 }; 3005 3006 3007 /// Arbitrary order Raviart-Thomas elements in 3D on a tetrahedron 3008 class RT_TetrahedronElement : public VectorFiniteElement 3009 { 3010 static const double nk[12], c; 3011 3012 #ifndef MFEM_THREAD_SAFE 3013 mutable Vector shape_x, shape_y, shape_z, shape_l; 3014 mutable Vector dshape_x, dshape_y, dshape_z, dshape_l; 3015 mutable DenseMatrix u; 3016 mutable Vector divu; 3017 #endif 3018 Array<int> dof2nk; 3019 DenseMatrixInverse Ti; 3020 3021 public: 3022 /// Construct the RT_TetrahedronElement of order @a p 3023 RT_TetrahedronElement(const int p); 3024 virtual void CalcVShape(const IntegrationPoint &ip, 3025 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const3026 virtual void CalcVShape(ElementTransformation &Trans, 3027 DenseMatrix &shape) const 3028 { CalcVShape_RT(Trans, shape); } 3029 virtual void CalcDivShape(const IntegrationPoint &ip, 3030 Vector &divshape) const; GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const3031 virtual void GetLocalInterpolation(ElementTransformation &Trans, 3032 DenseMatrix &I) const 3033 { LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); } GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const3034 virtual void GetLocalRestriction(ElementTransformation &Trans, 3035 DenseMatrix &R) const 3036 { LocalRestriction_RT(nk, dof2nk, Trans, R); } GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3037 virtual void GetTransferMatrix(const FiniteElement &fe, 3038 ElementTransformation &Trans, 3039 DenseMatrix &I) const 3040 { LocalInterpolation_RT(CheckVectorFE(fe), nk, dof2nk, Trans, I); } 3041 using FiniteElement::Project; Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const3042 virtual void Project(VectorCoefficient &vc, 3043 ElementTransformation &Trans, Vector &dofs) const 3044 { Project_RT(nk, dof2nk, vc, Trans, dofs); } ProjectFromNodes(Vector & vc,ElementTransformation & Trans,Vector & dofs) const3045 virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, 3046 Vector &dofs) const 3047 { Project_RT(nk, dof2nk, vc, Trans, dofs); } ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const3048 virtual void ProjectMatrixCoefficient( 3049 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const 3050 { ProjectMatrixCoefficient_RT(nk, dof2nk, mc, T, dofs); } Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3051 virtual void Project(const FiniteElement &fe, ElementTransformation &Trans, 3052 DenseMatrix &I) const 3053 { Project_RT(nk, dof2nk, fe, Trans, I); } ProjectCurl(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const3054 virtual void ProjectCurl(const FiniteElement &fe, 3055 ElementTransformation &Trans, 3056 DenseMatrix &curl) const 3057 { ProjectCurl_RT(nk, dof2nk, fe, Trans, curl); } 3058 }; 3059 3060 3061 /// Arbitrary order Nedelec elements in 3D on a cube 3062 class ND_HexahedronElement : public VectorTensorFiniteElement 3063 { 3064 static const double tk[18]; 3065 #ifndef MFEM_THREAD_SAFE 3066 mutable Vector shape_cx, shape_ox, shape_cy, shape_oy, shape_cz, shape_oz; 3067 mutable Vector dshape_cx, dshape_cy, dshape_cz; 3068 #endif 3069 Array<int> dof2tk; 3070 const double *cp; 3071 3072 public: 3073 /** @brief Construct the ND_HexahedronElement of order @a p and closed and 3074 open BasisType @a cb_type and @a ob_type */ 3075 ND_HexahedronElement(const int p, 3076 const int cb_type = BasisType::GaussLobatto, 3077 const int ob_type = BasisType::GaussLegendre); 3078 3079 virtual void CalcVShape(const IntegrationPoint &ip, 3080 DenseMatrix &shape) const; 3081 CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const3082 virtual void CalcVShape(ElementTransformation &Trans, 3083 DenseMatrix &shape) const 3084 { CalcVShape_ND(Trans, shape); } 3085 3086 virtual void CalcCurlShape(const IntegrationPoint &ip, 3087 DenseMatrix &curl_shape) const; 3088 GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const3089 virtual void GetLocalInterpolation(ElementTransformation &Trans, 3090 DenseMatrix &I) const 3091 { LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); } 3092 GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const3093 virtual void GetLocalRestriction(ElementTransformation &Trans, 3094 DenseMatrix &R) const 3095 { LocalRestriction_ND(tk, dof2tk, Trans, R); } 3096 GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3097 virtual void GetTransferMatrix(const FiniteElement &fe, 3098 ElementTransformation &Trans, 3099 DenseMatrix &I) const 3100 { LocalInterpolation_ND(CheckVectorFE(fe), tk, dof2tk, Trans, I); } 3101 3102 using FiniteElement::Project; 3103 Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const3104 virtual void Project(VectorCoefficient &vc, 3105 ElementTransformation &Trans, Vector &dofs) const 3106 { 3107 if (obasis1d.IsIntegratedType()) { ProjectIntegrated(vc, Trans, dofs); } 3108 else { Project_ND(tk, dof2tk, vc, Trans, dofs); } 3109 } 3110 ProjectFromNodes(Vector & vc,ElementTransformation & Trans,Vector & dofs) const3111 virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, 3112 Vector &dofs) const 3113 { Project_ND(tk, dof2tk, vc, Trans, dofs); } 3114 ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const3115 virtual void ProjectMatrixCoefficient( 3116 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const 3117 { ProjectMatrixCoefficient_ND(tk, dof2tk, mc, T, dofs); } 3118 Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3119 virtual void Project(const FiniteElement &fe, 3120 ElementTransformation &Trans, 3121 DenseMatrix &I) const 3122 { Project_ND(tk, dof2tk, fe, Trans, I); } 3123 ProjectGrad(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const3124 virtual void ProjectGrad(const FiniteElement &fe, 3125 ElementTransformation &Trans, 3126 DenseMatrix &grad) const 3127 { ProjectGrad_ND(tk, dof2tk, fe, Trans, grad); } 3128 ProjectCurl(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const3129 virtual void ProjectCurl(const FiniteElement &fe, 3130 ElementTransformation &Trans, 3131 DenseMatrix &curl) const 3132 { ProjectCurl_ND(tk, dof2tk, fe, Trans, curl); } 3133 3134 protected: 3135 void ProjectIntegrated(VectorCoefficient &vc, 3136 ElementTransformation &Trans, 3137 Vector &dofs) const; 3138 }; 3139 3140 3141 /// Arbitrary order Nedelec elements in 2D on a square 3142 class ND_QuadrilateralElement : public VectorTensorFiniteElement 3143 { 3144 static const double tk[8]; 3145 3146 #ifndef MFEM_THREAD_SAFE 3147 mutable Vector shape_cx, shape_ox, shape_cy, shape_oy; 3148 mutable Vector dshape_cx, dshape_cy; 3149 #endif 3150 Array<int> dof2tk; 3151 const double *cp; 3152 3153 public: 3154 /** @brief Construct the ND_QuadrilateralElement of order @a p and closed and 3155 open BasisType @a cb_type and @a ob_type */ 3156 ND_QuadrilateralElement(const int p, 3157 const int cb_type = BasisType::GaussLobatto, 3158 const int ob_type = BasisType::GaussLegendre); 3159 virtual void CalcVShape(const IntegrationPoint &ip, 3160 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const3161 virtual void CalcVShape(ElementTransformation &Trans, 3162 DenseMatrix &shape) const 3163 { CalcVShape_ND(Trans, shape); } 3164 virtual void CalcCurlShape(const IntegrationPoint &ip, 3165 DenseMatrix &curl_shape) const; GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const3166 virtual void GetLocalInterpolation(ElementTransformation &Trans, 3167 DenseMatrix &I) const 3168 { LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); } GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const3169 virtual void GetLocalRestriction(ElementTransformation &Trans, 3170 DenseMatrix &R) const 3171 { LocalRestriction_ND(tk, dof2tk, Trans, R); } GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3172 virtual void GetTransferMatrix(const FiniteElement &fe, 3173 ElementTransformation &Trans, 3174 DenseMatrix &I) const 3175 { LocalInterpolation_ND(CheckVectorFE(fe), tk, dof2tk, Trans, I); } 3176 using FiniteElement::Project; Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const3177 virtual void Project(VectorCoefficient &vc, 3178 ElementTransformation &Trans, Vector &dofs) const 3179 { 3180 if (obasis1d.IsIntegratedType()) { ProjectIntegrated(vc, Trans, dofs); } 3181 else { Project_ND(tk, dof2tk, vc, Trans, dofs); } 3182 } ProjectFromNodes(Vector & vc,ElementTransformation & Trans,Vector & dofs) const3183 virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, 3184 Vector &dofs) const 3185 { Project_ND(tk, dof2tk, vc, Trans, dofs); } ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const3186 virtual void ProjectMatrixCoefficient( 3187 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const 3188 { ProjectMatrixCoefficient_ND(tk, dof2tk, mc, T, dofs); } Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3189 virtual void Project(const FiniteElement &fe, 3190 ElementTransformation &Trans, 3191 DenseMatrix &I) const 3192 { Project_ND(tk, dof2tk, fe, Trans, I); } ProjectGrad(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const3193 virtual void ProjectGrad(const FiniteElement &fe, 3194 ElementTransformation &Trans, 3195 DenseMatrix &grad) const 3196 { ProjectGrad_ND(tk, dof2tk, fe, Trans, grad); } 3197 3198 protected: 3199 void ProjectIntegrated(VectorCoefficient &vc, 3200 ElementTransformation &Trans, 3201 Vector &dofs) const; 3202 }; 3203 3204 3205 /// Arbitrary order Nedelec elements in 3D on a tetrahedron 3206 class ND_TetrahedronElement : public VectorFiniteElement 3207 { 3208 static const double tk[18], c; 3209 3210 #ifndef MFEM_THREAD_SAFE 3211 mutable Vector shape_x, shape_y, shape_z, shape_l; 3212 mutable Vector dshape_x, dshape_y, dshape_z, dshape_l; 3213 mutable DenseMatrix u; 3214 #endif 3215 Array<int> dof2tk; 3216 DenseMatrixInverse Ti; 3217 3218 public: 3219 /// Construct the ND_TetrahedronElement of order @a p 3220 ND_TetrahedronElement(const int p); 3221 virtual void CalcVShape(const IntegrationPoint &ip, 3222 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const3223 virtual void CalcVShape(ElementTransformation &Trans, 3224 DenseMatrix &shape) const 3225 { CalcVShape_ND(Trans, shape); } 3226 virtual void CalcCurlShape(const IntegrationPoint &ip, 3227 DenseMatrix &curl_shape) const; GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const3228 virtual void GetLocalInterpolation(ElementTransformation &Trans, 3229 DenseMatrix &I) const 3230 { LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); } GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const3231 virtual void GetLocalRestriction(ElementTransformation &Trans, 3232 DenseMatrix &R) const 3233 { LocalRestriction_ND(tk, dof2tk, Trans, R); } GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3234 virtual void GetTransferMatrix(const FiniteElement &fe, 3235 ElementTransformation &Trans, 3236 DenseMatrix &I) const 3237 { LocalInterpolation_ND(CheckVectorFE(fe), tk, dof2tk, Trans, I); } 3238 using FiniteElement::Project; Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const3239 virtual void Project(VectorCoefficient &vc, 3240 ElementTransformation &Trans, Vector &dofs) const 3241 { Project_ND(tk, dof2tk, vc, Trans, dofs); } ProjectFromNodes(Vector & vc,ElementTransformation & Trans,Vector & dofs) const3242 virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, 3243 Vector &dofs) const 3244 { Project_ND(tk, dof2tk, vc, Trans, dofs); } ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const3245 virtual void ProjectMatrixCoefficient( 3246 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const 3247 { ProjectMatrixCoefficient_ND(tk, dof2tk, mc, T, dofs); } Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3248 virtual void Project(const FiniteElement &fe, 3249 ElementTransformation &Trans, 3250 DenseMatrix &I) const 3251 { Project_ND(tk, dof2tk, fe, Trans, I); } ProjectGrad(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const3252 virtual void ProjectGrad(const FiniteElement &fe, 3253 ElementTransformation &Trans, 3254 DenseMatrix &grad) const 3255 { ProjectGrad_ND(tk, dof2tk, fe, Trans, grad); } 3256 ProjectCurl(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & curl) const3257 virtual void ProjectCurl(const FiniteElement &fe, 3258 ElementTransformation &Trans, 3259 DenseMatrix &curl) const 3260 { ProjectCurl_ND(tk, dof2tk, fe, Trans, curl); } 3261 }; 3262 3263 /// Arbitrary order Nedelec elements in 2D on a triangle 3264 class ND_TriangleElement : public VectorFiniteElement 3265 { 3266 static const double tk[8], c; 3267 3268 #ifndef MFEM_THREAD_SAFE 3269 mutable Vector shape_x, shape_y, shape_l; 3270 mutable Vector dshape_x, dshape_y, dshape_l; 3271 mutable DenseMatrix u; 3272 mutable Vector curlu; 3273 #endif 3274 Array<int> dof2tk; 3275 DenseMatrixInverse Ti; 3276 3277 public: 3278 /// Construct the ND_TriangleElement of order @a p 3279 ND_TriangleElement(const int p); 3280 virtual void CalcVShape(const IntegrationPoint &ip, 3281 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const3282 virtual void CalcVShape(ElementTransformation &Trans, 3283 DenseMatrix &shape) const 3284 { CalcVShape_ND(Trans, shape); } 3285 virtual void CalcCurlShape(const IntegrationPoint &ip, 3286 DenseMatrix &curl_shape) const; GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const3287 virtual void GetLocalInterpolation(ElementTransformation &Trans, 3288 DenseMatrix &I) const 3289 { LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); } GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const3290 virtual void GetLocalRestriction(ElementTransformation &Trans, 3291 DenseMatrix &R) const 3292 { LocalRestriction_ND(tk, dof2tk, Trans, R); } GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3293 virtual void GetTransferMatrix(const FiniteElement &fe, 3294 ElementTransformation &Trans, 3295 DenseMatrix &I) const 3296 { LocalInterpolation_ND(CheckVectorFE(fe), tk, dof2tk, Trans, I); } 3297 using FiniteElement::Project; Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const3298 virtual void Project(VectorCoefficient &vc, 3299 ElementTransformation &Trans, Vector &dofs) const 3300 { Project_ND(tk, dof2tk, vc, Trans, dofs); } ProjectFromNodes(Vector & vc,ElementTransformation & Trans,Vector & dofs) const3301 virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, 3302 Vector &dofs) const 3303 { Project_ND(tk, dof2tk, vc, Trans, dofs); } ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const3304 virtual void ProjectMatrixCoefficient( 3305 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const 3306 { ProjectMatrixCoefficient_ND(tk, dof2tk, mc, T, dofs); } Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3307 virtual void Project(const FiniteElement &fe, 3308 ElementTransformation &Trans, 3309 DenseMatrix &I) const 3310 { Project_ND(tk, dof2tk, fe, Trans, I); } ProjectGrad(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const3311 virtual void ProjectGrad(const FiniteElement &fe, 3312 ElementTransformation &Trans, 3313 DenseMatrix &grad) const 3314 { ProjectGrad_ND(tk, dof2tk, fe, Trans, grad); } 3315 }; 3316 3317 3318 /// Arbitrary order Nedelec elements in 1D on a segment 3319 class ND_SegmentElement : public VectorTensorFiniteElement 3320 { 3321 static const double tk[1]; 3322 Array<int> dof2tk; 3323 3324 public: 3325 /** @brief Construct the ND_SegmentElement of order @a p and open 3326 BasisType @a ob_type */ 3327 ND_SegmentElement(const int p, const int ob_type = BasisType::GaussLegendre); CalcShape(const IntegrationPoint & ip,Vector & shape) const3328 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const 3329 { obasis1d.Eval(ip.x, shape); } 3330 virtual void CalcVShape(const IntegrationPoint &ip, 3331 DenseMatrix &shape) const; CalcVShape(ElementTransformation & Trans,DenseMatrix & shape) const3332 virtual void CalcVShape(ElementTransformation &Trans, 3333 DenseMatrix &shape) const 3334 { CalcVShape_ND(Trans, shape); } 3335 // virtual void CalcCurlShape(const IntegrationPoint &ip, 3336 // DenseMatrix &curl_shape) const; GetLocalInterpolation(ElementTransformation & Trans,DenseMatrix & I) const3337 virtual void GetLocalInterpolation(ElementTransformation &Trans, 3338 DenseMatrix &I) const 3339 { LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); } GetLocalRestriction(ElementTransformation & Trans,DenseMatrix & R) const3340 virtual void GetLocalRestriction(ElementTransformation &Trans, 3341 DenseMatrix &R) const 3342 { LocalRestriction_ND(tk, dof2tk, Trans, R); } GetTransferMatrix(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3343 virtual void GetTransferMatrix(const FiniteElement &fe, 3344 ElementTransformation &Trans, 3345 DenseMatrix &I) const 3346 { LocalInterpolation_ND(CheckVectorFE(fe), tk, dof2tk, Trans, I); } 3347 using FiniteElement::Project; Project(VectorCoefficient & vc,ElementTransformation & Trans,Vector & dofs) const3348 virtual void Project(VectorCoefficient &vc, 3349 ElementTransformation &Trans, Vector &dofs) const 3350 { Project_ND(tk, dof2tk, vc, Trans, dofs); } ProjectMatrixCoefficient(MatrixCoefficient & mc,ElementTransformation & T,Vector & dofs) const3351 virtual void ProjectMatrixCoefficient( 3352 MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const 3353 { ProjectMatrixCoefficient_ND(tk, dof2tk, mc, T, dofs); } Project(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & I) const3354 virtual void Project(const FiniteElement &fe, 3355 ElementTransformation &Trans, 3356 DenseMatrix &I) const 3357 { Project_ND(tk, dof2tk, fe, Trans, I); } ProjectGrad(const FiniteElement & fe,ElementTransformation & Trans,DenseMatrix & grad) const3358 virtual void ProjectGrad(const FiniteElement &fe, 3359 ElementTransformation &Trans, 3360 DenseMatrix &grad) const 3361 { ProjectGrad_ND(tk, dof2tk, fe, Trans, grad); } 3362 }; 3363 3364 3365 /// An arbitrary order and dimension NURBS element 3366 class NURBSFiniteElement : public ScalarFiniteElement 3367 { 3368 protected: 3369 mutable Array <const KnotVector*> kv; 3370 mutable const int *ijk; 3371 mutable int patch, elem; 3372 mutable Vector weights; 3373 3374 public: 3375 /** @brief Construct NURBSFiniteElement with given 3376 @param D Reference space dimension 3377 @param G Geometry type (of type Geometry::Type) 3378 @param Do Number of degrees of freedom in the FiniteElement 3379 @param O Order/degree of the FiniteElement 3380 @param F FunctionSpace type of the FiniteElement 3381 */ NURBSFiniteElement(int D,Geometry::Type G,int Do,int O,int F)3382 NURBSFiniteElement(int D, Geometry::Type G, int Do, int O, int F) 3383 : ScalarFiniteElement(D, G, Do, O, F) 3384 { 3385 ijk = NULL; 3386 patch = elem = -1; 3387 kv.SetSize(dim); 3388 weights.SetSize(dof); 3389 weights = 1.0; 3390 } 3391 Reset() const3392 void Reset () const { patch = elem = -1; } SetIJK(const int * IJK) const3393 void SetIJK (const int *IJK) const { ijk = IJK; } GetPatch() const3394 int GetPatch () const { return patch; } SetPatch(int p) const3395 void SetPatch (int p) const { patch = p; } GetElement() const3396 int GetElement () const { return elem; } SetElement(int e) const3397 void SetElement (int e) const { elem = e; } KnotVectors() const3398 Array <const KnotVector*> &KnotVectors() const { return kv; } Weights() const3399 Vector &Weights () const { return weights; } 3400 /// Update the NURBSFiniteElement according to the currently set knot vectors SetOrder() const3401 virtual void SetOrder () const { } 3402 }; 3403 3404 3405 /// An arbitrary order 1D NURBS element on a segment 3406 class NURBS1DFiniteElement : public NURBSFiniteElement 3407 { 3408 protected: 3409 mutable Vector shape_x; 3410 3411 public: 3412 /// Construct the NURBS1DFiniteElement of order @a p NURBS1DFiniteElement(int p)3413 NURBS1DFiniteElement(int p) 3414 : NURBSFiniteElement(1, Geometry::SEGMENT, p + 1, p, FunctionSpace::Qk), 3415 shape_x(p + 1) { } 3416 3417 virtual void SetOrder() const; 3418 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 3419 virtual void CalcDShape(const IntegrationPoint &ip, 3420 DenseMatrix &dshape) const; 3421 virtual void CalcHessian (const IntegrationPoint &ip, 3422 DenseMatrix &hessian) const; 3423 }; 3424 3425 /// An arbitrary order 2D NURBS element on a square 3426 class NURBS2DFiniteElement : public NURBSFiniteElement 3427 { 3428 protected: 3429 mutable Vector u, shape_x, shape_y, dshape_x, dshape_y, d2shape_x, d2shape_y; 3430 mutable DenseMatrix du; 3431 3432 public: 3433 /// Construct the NURBS2DFiniteElement of order @a p NURBS2DFiniteElement(int p)3434 NURBS2DFiniteElement(int p) 3435 : NURBSFiniteElement(2, Geometry::SQUARE, (p + 1)*(p + 1), p, 3436 FunctionSpace::Qk), 3437 u(dof), shape_x(p + 1), shape_y(p + 1), dshape_x(p + 1), 3438 dshape_y(p + 1), d2shape_x(p + 1), d2shape_y(p + 1), du(dof,2) 3439 { orders[0] = orders[1] = p; } 3440 3441 /// Construct the NURBS2DFiniteElement with x-order @a px and y-order @a py NURBS2DFiniteElement(int px,int py)3442 NURBS2DFiniteElement(int px, int py) 3443 : NURBSFiniteElement(2, Geometry::SQUARE, (px + 1)*(py + 1), 3444 std::max(px, py), FunctionSpace::Qk), 3445 u(dof), shape_x(px + 1), shape_y(py + 1), dshape_x(px + 1), 3446 dshape_y(py + 1), d2shape_x(px + 1), d2shape_y(py + 1), du(dof,2) 3447 { orders[0] = px; orders[1] = py; } 3448 3449 virtual void SetOrder() const; 3450 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 3451 virtual void CalcDShape(const IntegrationPoint &ip, 3452 DenseMatrix &dshape) const; 3453 virtual void CalcHessian (const IntegrationPoint &ip, 3454 DenseMatrix &hessian) const; 3455 }; 3456 3457 /// An arbitrary order 3D NURBS element on a cube 3458 class NURBS3DFiniteElement : public NURBSFiniteElement 3459 { 3460 protected: 3461 mutable Vector u, shape_x, shape_y, shape_z; 3462 mutable Vector dshape_x, dshape_y, dshape_z; 3463 mutable Vector d2shape_x, d2shape_y, d2shape_z; 3464 mutable DenseMatrix du; 3465 3466 public: 3467 /// Construct the NURBS3DFiniteElement of order @a p NURBS3DFiniteElement(int p)3468 NURBS3DFiniteElement(int p) 3469 : NURBSFiniteElement(3, Geometry::CUBE, (p + 1)*(p + 1)*(p + 1), p, 3470 FunctionSpace::Qk), 3471 u(dof), shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), 3472 dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), 3473 d2shape_x(p + 1), d2shape_y(p + 1), d2shape_z(p + 1), du(dof,3) 3474 { orders[0] = orders[1] = orders[2] = p; } 3475 3476 /// Construct the NURBS3DFiniteElement with x-order @a px and y-order @a py 3477 /// and z-order @a pz NURBS3DFiniteElement(int px,int py,int pz)3478 NURBS3DFiniteElement(int px, int py, int pz) 3479 : NURBSFiniteElement(3, Geometry::CUBE, (px + 1)*(py + 1)*(pz + 1), 3480 std::max(std::max(px,py),pz), FunctionSpace::Qk), 3481 u(dof), shape_x(px + 1), shape_y(py + 1), shape_z(pz + 1), 3482 dshape_x(px + 1), dshape_y(py + 1), dshape_z(pz + 1), 3483 d2shape_x(px + 1), d2shape_y(py + 1), d2shape_z(pz + 1), du(dof,3) 3484 { orders[0] = px; orders[1] = py; orders[2] = pz; } 3485 3486 virtual void SetOrder() const; 3487 virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const; 3488 virtual void CalcDShape(const IntegrationPoint &ip, 3489 DenseMatrix &dshape) const; 3490 virtual void CalcHessian (const IntegrationPoint &ip, 3491 DenseMatrix &hessian) const; 3492 }; 3493 3494 } // namespace mfem 3495 3496 #endif 3497