Quinoa all test code coverage report
Current view: top level - PDE/Integrate - Basis.cpp (source / functions) Hit Total Coverage
Commit: -128-NOTFOUND Lines: 257 467 55.0 %
Date: 2024-11-22 09:12:55 Functions: 10 15 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 75 330 22.7 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/PDE/Integrate/Basis.cpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.
       7                 :            :              All rights reserved. See the LICENSE file for details.
       8                 :            :   \brief     Functions for computing the Dubiner basis functions in DG methods
       9                 :            :   \details   This file contains functionality for computing the basis functions
      10                 :            :      and relating coordinates transformation functions used in discontinuous
      11                 :            :      Galerkin methods for variaous orders of numerical representation. The basis
      12                 :            :      functions chosen for the DG method are the Dubiner basis, which are
      13                 :            :      Legendre polynomials modified for tetrahedra, which are defined only on
      14                 :            :      the reference/master tetrahedron.
      15                 :            :   \see [1] https://doi.org/10.1007/BF01060030
      16                 :            :   \see [2] https://doi.org/10.1093/imamat/hxh111
      17                 :            : */
      18                 :            : // *****************************************************************************
      19                 :            : 
      20                 :            : #include <array>
      21                 :            : #include "QuinoaConfig.hpp"
      22                 :            : 
      23                 :            : #include "Basis.hpp"
      24                 :            : #include "Vector.hpp"
      25                 :            : #include "Mass.hpp"
      26                 :            : 
      27                 :            : std::array< tk::real, 3 >
      28                 :  133326316 : tk::eval_gp ( const std::size_t igp,
      29                 :            :               const std::array< std::array< tk::real, 3>, 3 >& coordfa,
      30                 :            :               const std::array< std::vector< tk::real >, 2 >& coordgp )
      31                 :            : // *****************************************************************************
      32                 :            : //  Compute the coordinates of quadrature points for face integral in physical
      33                 :            : //  space
      34                 :            : //! \param[in] igp Index of quadrature points
      35                 :            : //! \param[in] coordfa Array of nodal coordinates for face element
      36                 :            : //! \param[in] coordgp Array of coordinates for quadrature points in reference
      37                 :            : //!   space
      38                 :            : //! \return Array of coordinates for quadrature points in physical space
      39                 :            : // *****************************************************************************
      40                 :            : {
      41                 :            :   // Barycentric coordinates for the triangular face
      42                 :  133326316 :   auto shp1 = 1.0 - coordgp[0][igp] - coordgp[1][igp];
      43                 :            :   auto shp2 = coordgp[0][igp];
      44                 :            :   auto shp3 = coordgp[1][igp];
      45                 :            : 
      46                 :            :   // Transformation of the quadrature point from the 2D reference/master
      47                 :            :   // element to physical space, to obtain its physical (x,y,z) coordinates.
      48                 :  133326316 :   return {{ coordfa[0][0]*shp1 + coordfa[1][0]*shp2 + coordfa[2][0]*shp3,
      49                 :  133326316 :             coordfa[0][1]*shp1 + coordfa[1][1]*shp2 + coordfa[2][1]*shp3,
      50                 :  133326316 :             coordfa[0][2]*shp1 + coordfa[1][2]*shp2 + coordfa[2][2]*shp3 }};
      51                 :            : }
      52                 :            : 
      53                 :            : std::array< tk::real, 3 >
      54                 :   65325203 : tk::eval_gp ( const std::size_t igp,
      55                 :            :               const std::array< std::array< tk::real, 3>, 4 >& coord,
      56                 :            :               const std::array< std::vector< tk::real >, 3 >& coordgp )
      57                 :            : // *****************************************************************************
      58                 :            : //  Compute the coordinates of quadrature points for volume integral in
      59                 :            : //  physical space
      60                 :            : //! \param[in] igp Index of quadrature points
      61                 :            : //! \param[in] coord Array of nodal coordinates for tetrahedron element
      62                 :            : //! \param[in] coordgp Array of coordinates for quadrature points in reference space
      63                 :            : //! \return Array of coordinates for quadrature points in physical space
      64                 :            : // *****************************************************************************
      65                 :            : {
      66                 :            :   // Barycentric coordinates for the tetradedron element
      67                 :   65325203 :   auto shp1 = 1.0 - coordgp[0][igp] - coordgp[1][igp] - coordgp[2][igp];
      68                 :            :   auto shp2 = coordgp[0][igp];
      69                 :            :   auto shp3 = coordgp[1][igp];
      70                 :            :   auto shp4 = coordgp[2][igp];
      71                 :            : 
      72                 :            :   // Transformation of the quadrature point from the reference/master
      73                 :            :   // element to physical space, to obtain its physical (x,y,z) coordinates.
      74                 :            :   return {{
      75                 :   65325203 :    coord[0][0]*shp1 + coord[1][0]*shp2 + coord[2][0]*shp3 + coord[3][0]*shp4,
      76                 :   65325203 :    coord[0][1]*shp1 + coord[1][1]*shp2 + coord[2][1]*shp3 + coord[3][1]*shp4,
      77                 :   65325203 :    coord[0][2]*shp1 + coord[1][2]*shp2 + coord[2][2]*shp3 + coord[3][2]*shp4 }};
      78                 :            : }
      79                 :            : 
      80                 :            : std::array< std::vector<tk::real>, 3 >
      81                 :    1861455 : tk::eval_dBdxi( const std::size_t ndof,
      82                 :            :   const std::array< tk::real, 3 >& coordgp )
      83                 :            : // *****************************************************************************
      84                 :            : //  Compute the derivatives of Dubiner basis wrt. reference coordinates
      85                 :            : //! \param[in] ndof Number of degrees of freedom
      86                 :            : //! \param[in] coordgp Coordinates in ref element where derivatives are needed
      87                 :            : //! \return Array of the derivatives of basis functions
      88                 :            : // *****************************************************************************
      89                 :            : {
      90                 :            :   // Initialize array
      91                 :            :   std::array< std::vector< tk::real >, 3 > dBdxi;
      92         [ +  + ]:    7445820 :   for (std::size_t idir=0; idir<3; ++idir) {
      93         [ +  - ]:    5584365 :     dBdxi[idir].resize(ndof, 0.0);
      94                 :            :   }
      95                 :            : 
      96                 :            :   // high-order basis
      97         [ +  - ]:    1861455 :   if (ndof > 1) {
      98                 :    1861455 :     dBdxi[0][0] = 0.0;
      99                 :    1861455 :     dBdxi[1][0] = 0.0;
     100                 :    1861455 :     dBdxi[2][0] = 0.0;
     101                 :            : 
     102                 :    1861455 :     dBdxi[0][1] = 2.0;
     103                 :    1861455 :     dBdxi[1][1] = 1.0;
     104                 :    1861455 :     dBdxi[2][1] = 1.0;
     105                 :            : 
     106                 :    1861455 :     dBdxi[0][2] = 0.0;
     107                 :    1861455 :     dBdxi[1][2] = 3.0;
     108                 :    1861455 :     dBdxi[2][2] = 1.0;
     109                 :            : 
     110                 :    1861455 :     dBdxi[0][3] = 0.0;
     111                 :    1861455 :     dBdxi[1][3] = 0.0;
     112                 :    1861455 :     dBdxi[2][3] = 4.0;
     113                 :            : 
     114         [ +  - ]:    1861455 :     if (ndof > 4) {
     115                 :    1861455 :       dBdxi[0][4] = 12.0 * coordgp[0] + 6.0 * coordgp[1]
     116                 :    1861455 :                   +  6.0 * coordgp[2] - 6.0;
     117                 :    1861455 :       dBdxi[1][4] =  6.0 * coordgp[0] + 2.0 * coordgp[1]
     118                 :    1861455 :                   +  2.0 * coordgp[2] - 2.0;
     119                 :    1861455 :       dBdxi[2][4] =  6.0 * coordgp[0] + 2.0 * coordgp[1]
     120                 :    1861455 :                   +  2.0 * coordgp[2] - 2.0;
     121                 :            : 
     122                 :    1861455 :       dBdxi[0][5] = 10.0 * coordgp[1] +  2.0 * coordgp[2] - 2.0;
     123                 :    1861455 :       dBdxi[1][5] = 10.0 * coordgp[0] + 10.0 * coordgp[1]
     124                 :    1861455 :                   +  6.0 * coordgp[2] - 6.0;
     125                 :    1861455 :       dBdxi[2][5] =  2.0 * coordgp[0] +  6.0 * coordgp[1]
     126                 :    1861455 :                   +  2.0 * coordgp[2] - 2.0;
     127                 :            : 
     128                 :    1861455 :       dBdxi[0][6] = 12.0 * coordgp[2] - 2.0;
     129                 :    1861455 :       dBdxi[1][6] =  6.0 * coordgp[2] - 1.0;
     130                 :    1861455 :       dBdxi[2][6] = 12.0 * coordgp[0] + 6.0 * coordgp[1]
     131                 :    1861455 :                   + 12.0 * coordgp[2] - 7.0;
     132                 :            : 
     133                 :    1861455 :       dBdxi[0][7] = 0.0;
     134                 :    1861455 :       dBdxi[1][7] = 20.0 * coordgp[1] + 8.0 * coordgp[2] - 8.0;
     135                 :    1861455 :       dBdxi[2][7] =  8.0 * coordgp[1] + 2.0 * coordgp[2] - 2.0;
     136                 :            : 
     137                 :    1861455 :       dBdxi[0][8] = 0.0;
     138                 :    1861455 :       dBdxi[1][8] = 18.0 * coordgp[2] -  3.0;
     139                 :    1861455 :       dBdxi[2][8] = 18.0 * coordgp[1] + 12.0 * coordgp[2] - 7.0;
     140                 :            : 
     141                 :    1861455 :       dBdxi[0][9] = 0.0;
     142                 :    1861455 :       dBdxi[1][9] = 0.0;
     143                 :    1861455 :       dBdxi[2][9] = 30.0 * coordgp[2] - 10.0;
     144                 :            :     }
     145                 :            :   }
     146                 :            : 
     147                 :    1861455 :   return dBdxi;
     148                 :            : }
     149                 :            : 
     150                 :            : std::array< std::vector<tk::real>, 3 >
     151                 :    8266911 : tk::eval_dBdx_p1( const std::size_t ndof,
     152                 :            :                   const std::array< std::array< tk::real, 3 >, 3 >& jacInv )
     153                 :            : // *****************************************************************************
     154                 :            : //  Compute the derivatives of basis functions for DG(P1)
     155                 :            : //! \param[in] ndof Number of degrees of freedom
     156                 :            : //! \param[in] jacInv Array of the inverse of Jacobian
     157                 :            : //! \return Array of the derivatives of basis functions
     158                 :            : // *****************************************************************************
     159                 :            : {
     160                 :            :   // The derivatives of the basis functions dB/dx are easily calculated
     161                 :            :   // via a transformation to the reference space as,
     162                 :            :   // dB/dx = dB/dxi . dxi/dx,
     163                 :            :   // where, x = (x,y,z) are the physical coordinates, and
     164                 :            :   //        xi = (xi, eta, zeta) are the reference coordinates.
     165                 :            :   // The matrix dxi/dx is the inverse of the Jacobian of transformation
     166                 :            :   // and the matrix vector product has to be calculated. This follows.
     167                 :            : 
     168                 :            :   std::array< std::vector<tk::real>, 3 > dBdx;
     169 [ +  - ][ +  - ]:    8266911 :   dBdx[0].resize( ndof, 0 );
     170 [ +  - ][ +  - ]:    8266911 :   dBdx[1].resize( ndof, 0 );
     171         [ +  - ]:    8266911 :   dBdx[2].resize( ndof, 0 );
     172                 :            : 
     173                 :            :   auto db2dxi1 = 2.0;
     174                 :            :   auto db2dxi2 = 1.0;
     175                 :            :   auto db2dxi3 = 1.0;
     176                 :            : 
     177                 :            :   auto db3dxi1 = 0.0;
     178                 :            :   auto db3dxi2 = 3.0;
     179                 :            :   auto db3dxi3 = 1.0;
     180                 :            : 
     181                 :            :   auto db4dxi1 = 0.0;
     182                 :            :   auto db4dxi2 = 0.0;
     183                 :            :   auto db4dxi3 = 4.0;
     184                 :            : 
     185                 :    8266911 :   dBdx[0][1] =  db2dxi1 * jacInv[0][0]
     186                 :    8266911 :               + db2dxi2 * jacInv[1][0]
     187                 :    8266911 :               + db2dxi3 * jacInv[2][0];
     188                 :            : 
     189                 :    8266911 :   dBdx[1][1] =  db2dxi1 * jacInv[0][1]
     190                 :    8266911 :               + db2dxi2 * jacInv[1][1]
     191                 :    8266911 :               + db2dxi3 * jacInv[2][1];
     192                 :            : 
     193                 :    8266911 :   dBdx[2][1] =  db2dxi1 * jacInv[0][2]
     194                 :    8266911 :               + db2dxi2 * jacInv[1][2]
     195                 :    8266911 :               + db2dxi3 * jacInv[2][2];
     196                 :            : 
     197                 :    8266911 :   dBdx[0][2] =  db3dxi1 * jacInv[0][0]
     198                 :    8266911 :               + db3dxi2 * jacInv[1][0]
     199                 :    8266911 :               + db3dxi3 * jacInv[2][0];
     200                 :            : 
     201                 :    8266911 :   dBdx[1][2] =  db3dxi1 * jacInv[0][1]
     202                 :    8266911 :               + db3dxi2 * jacInv[1][1]
     203                 :    8266911 :               + db3dxi3 * jacInv[2][1];
     204                 :            : 
     205                 :    8266911 :   dBdx[2][2] =  db3dxi1 * jacInv[0][2]
     206                 :    8266911 :               + db3dxi2 * jacInv[1][2]
     207                 :    8266911 :               + db3dxi3 * jacInv[2][2];
     208                 :            : 
     209                 :    8266911 :   dBdx[0][3] =  db4dxi1 * jacInv[0][0]
     210                 :    8266911 :               + db4dxi2 * jacInv[1][0]
     211                 :    8266911 :               + db4dxi3 * jacInv[2][0];
     212                 :            : 
     213                 :    8266911 :   dBdx[1][3] =  db4dxi1 * jacInv[0][1]
     214                 :    8266911 :               + db4dxi2 * jacInv[1][1]
     215                 :    8266911 :               + db4dxi3 * jacInv[2][1];
     216                 :            : 
     217                 :    8266911 :   dBdx[2][3] =  db4dxi1 * jacInv[0][2]
     218                 :    8266911 :               + db4dxi2 * jacInv[1][2]
     219                 :    8266911 :               + db4dxi3 * jacInv[2][2];
     220                 :            : 
     221                 :    8266911 :   return dBdx;
     222                 :            : }
     223                 :            : 
     224                 :            : void
     225                 :   14707176 : tk::eval_dBdx_p2( const std::size_t igp,
     226                 :            :                   const std::array< std::vector< tk::real >, 3 >& coordgp,
     227                 :            :                   const std::array< std::array< tk::real, 3 >, 3 >& jacInv,
     228                 :            :                   std::array< std::vector<tk::real>, 3 >& dBdx )
     229                 :            : // *****************************************************************************
     230                 :            : //  Compute the derivatives of Dubiner basis function for DG(P2)
     231                 :            : //! \param[in] igp Index of quadrature points
     232                 :            : //! \param[in] coordgp Gauss point coordinates for tetrahedron element
     233                 :            : //! \param[in] jacInv Array of the inverse of Jacobian
     234                 :            : //! \param[in,out] dBdx Array of the derivatives of basis function
     235                 :            : // *****************************************************************************
     236                 :            : {
     237                 :   14707176 :   auto db5dxi1 = 12.0 * coordgp[0][igp] + 6.0 * coordgp[1][igp]
     238                 :   14707176 :                +  6.0 * coordgp[2][igp] - 6.0;
     239                 :   14707176 :   auto db5dxi2 =  6.0 * coordgp[0][igp] + 2.0 * coordgp[1][igp]
     240                 :   14707176 :                +  2.0 * coordgp[2][igp] - 2.0;
     241                 :            :   auto db5dxi3 =  6.0 * coordgp[0][igp] + 2.0 * coordgp[1][igp]
     242                 :            :                +  2.0 * coordgp[2][igp] - 2.0;
     243                 :            : 
     244                 :   14707176 :   auto db6dxi1 = 10.0 * coordgp[1][igp] +  2.0 * coordgp[2][igp] - 2.0;
     245                 :   14707176 :   auto db6dxi2 = 10.0 * coordgp[0][igp] + 10.0 * coordgp[1][igp]
     246                 :   14707176 :                +  6.0 * coordgp[2][igp] - 6.0;
     247                 :   14707176 :   auto db6dxi3 =  2.0 * coordgp[0][igp] +  6.0 * coordgp[1][igp]
     248                 :   14707176 :                +  2.0 * coordgp[2][igp] - 2.0;
     249                 :            : 
     250                 :   14707176 :   auto db7dxi1 = 12.0 * coordgp[2][igp] - 2.0;
     251                 :   14707176 :   auto db7dxi2 =  6.0 * coordgp[2][igp] - 1.0;
     252                 :            :   auto db7dxi3 = 12.0 * coordgp[0][igp] + 6.0 * coordgp[1][igp]
     253                 :   14707176 :                + 12.0 * coordgp[2][igp] - 7.0;
     254                 :            : 
     255                 :            :   auto db8dxi1 =  0;
     256                 :   14707176 :   auto db8dxi2 = 20.0 * coordgp[1][igp] + 8.0 * coordgp[2][igp] - 8.0;
     257                 :   14707176 :   auto db8dxi3 =  8.0 * coordgp[1][igp] + 2.0 * coordgp[2][igp] - 2.0;
     258                 :            : 
     259                 :            :   auto db9dxi1 =  0;
     260                 :   14707176 :   auto db9dxi2 = 18.0 * coordgp[2][igp] -  3.0;
     261                 :   14707176 :   auto db9dxi3 = 18.0 * coordgp[1][igp] + 12.0 * coordgp[2][igp] - 7.0;
     262                 :            : 
     263                 :            :   auto db10dxi1 =  0;
     264                 :            :   auto db10dxi2 =  0;
     265                 :   14707176 :   auto db10dxi3 = 30.0 * coordgp[2][igp] - 10.0;
     266                 :            : 
     267                 :   14707176 :   dBdx[0][4] =  db5dxi1 * jacInv[0][0]
     268                 :   14707176 :               + db5dxi2 * jacInv[1][0]
     269                 :   14707176 :               + db5dxi3 * jacInv[2][0];
     270                 :            : 
     271                 :   14707176 :   dBdx[1][4] =  db5dxi1 * jacInv[0][1]
     272                 :   14707176 :               + db5dxi2 * jacInv[1][1]
     273                 :   14707176 :               + db5dxi3 * jacInv[2][1];
     274                 :            : 
     275                 :   14707176 :   dBdx[2][4] =  db5dxi1 * jacInv[0][2]
     276                 :   14707176 :               + db5dxi2 * jacInv[1][2]
     277                 :   14707176 :               + db5dxi3 * jacInv[2][2];
     278                 :            : 
     279                 :   14707176 :   dBdx[0][5] =  db6dxi1 * jacInv[0][0]
     280                 :   14707176 :               + db6dxi2 * jacInv[1][0]
     281                 :   14707176 :               + db6dxi3 * jacInv[2][0];
     282                 :            : 
     283                 :   14707176 :   dBdx[1][5] =  db6dxi1 * jacInv[0][1]
     284                 :   14707176 :               + db6dxi2 * jacInv[1][1]
     285                 :   14707176 :               + db6dxi3 * jacInv[2][1];
     286                 :            : 
     287                 :   14707176 :   dBdx[2][5] =  db6dxi1 * jacInv[0][2]
     288                 :   14707176 :               + db6dxi2 * jacInv[1][2]
     289                 :   14707176 :               + db6dxi3 * jacInv[2][2];
     290                 :            : 
     291                 :   14707176 :   dBdx[0][6] =  db7dxi1 * jacInv[0][0]
     292                 :   14707176 :               + db7dxi2 * jacInv[1][0]
     293                 :   14707176 :               + db7dxi3 * jacInv[2][0];
     294                 :            : 
     295                 :   14707176 :   dBdx[1][6] =  db7dxi1 * jacInv[0][1]
     296                 :   14707176 :               + db7dxi2 * jacInv[1][1]
     297                 :   14707176 :               + db7dxi3 * jacInv[2][1];
     298                 :            : 
     299                 :   14707176 :   dBdx[2][6] =  db7dxi1 * jacInv[0][2]
     300                 :   14707176 :               + db7dxi2 * jacInv[1][2]
     301                 :   14707176 :               + db7dxi3 * jacInv[2][2];
     302                 :            : 
     303                 :   14707176 :   dBdx[0][7] =  db8dxi1 * jacInv[0][0]
     304                 :   14707176 :               + db8dxi2 * jacInv[1][0]
     305                 :   14707176 :               + db8dxi3 * jacInv[2][0];
     306                 :            : 
     307                 :   14707176 :   dBdx[1][7] =  db8dxi1 * jacInv[0][1]
     308                 :   14707176 :               + db8dxi2 * jacInv[1][1]
     309                 :   14707176 :               + db8dxi3 * jacInv[2][1];
     310                 :            : 
     311                 :   14707176 :   dBdx[2][7] =  db8dxi1 * jacInv[0][2]
     312                 :   14707176 :               + db8dxi2 * jacInv[1][2]
     313                 :   14707176 :               + db8dxi3 * jacInv[2][2];
     314                 :            : 
     315                 :   14707176 :   dBdx[0][8] =  db9dxi1 * jacInv[0][0]
     316                 :   14707176 :               + db9dxi2 * jacInv[1][0]
     317                 :   14707176 :               + db9dxi3 * jacInv[2][0];
     318                 :            : 
     319                 :   14707176 :   dBdx[1][8] =  db9dxi1 * jacInv[0][1]
     320                 :   14707176 :               + db9dxi2 * jacInv[1][1]
     321                 :   14707176 :               + db9dxi3 * jacInv[2][1];
     322                 :            : 
     323                 :   14707176 :   dBdx[2][8] =  db9dxi1 * jacInv[0][2]
     324                 :   14707176 :               + db9dxi2 * jacInv[1][2]
     325                 :   14707176 :               + db9dxi3 * jacInv[2][2];
     326                 :            : 
     327                 :   14707176 :   dBdx[0][9] =  db10dxi1 * jacInv[0][0]
     328                 :   14707176 :               + db10dxi2 * jacInv[1][0]
     329                 :   14707176 :               + db10dxi3 * jacInv[2][0];
     330                 :            : 
     331                 :   14707176 :   dBdx[1][9] =  db10dxi1 * jacInv[0][1]
     332                 :   14707176 :               + db10dxi2 * jacInv[1][1]
     333                 :   14707176 :               + db10dxi3 * jacInv[2][1];
     334                 :            : 
     335                 :   14707176 :   dBdx[2][9] =  db10dxi1 * jacInv[0][2]
     336                 :   14707176 :               + db10dxi2 * jacInv[1][2]
     337                 :   14707176 :               + db10dxi3 * jacInv[2][2];
     338                 :   14707176 : }
     339                 :            : 
     340                 :            : std::vector< tk::real >
     341                 :  289902982 : tk::eval_basis( const std::size_t ndof,
     342                 :            :                 const tk::real xi,
     343                 :            :                 const tk::real eta,
     344                 :            :                 const tk::real zeta )
     345                 :            : // *****************************************************************************
     346                 :            : //  Compute the Dubiner basis functions
     347                 :            : //! \param[in] ndof Number of degrees of freedom
     348                 :            : //! \param[in] xi,eta,zeta Coordinates for quadrature points in reference space
     349                 :            : //! \return Vector of basis functions
     350                 :            : // *****************************************************************************
     351                 :            : {
     352                 :            :   // Array of basis functions
     353                 :  289902982 :   std::vector< tk::real > B( ndof, 1.0 );
     354                 :            : 
     355         [ +  + ]:  289902982 :   if ( ndof > 1 )           // DG(P1)
     356                 :            :   {
     357                 :  229157811 :     B[1] = 2.0 * xi + eta + zeta - 1.0;
     358                 :  229157811 :     B[2] = 3.0 * eta + zeta - 1.0;
     359                 :  229157811 :     B[3] = 4.0 * zeta - 1.0;
     360                 :            : 
     361         [ +  + ]:  229157811 :     if( ndof > 4 )         // DG(P2)
     362                 :            :     {
     363                 :   65740965 :       B[4] =  6.0 * xi * xi + eta * eta + zeta * zeta
     364                 :   65740965 :             + 6.0 * xi * eta + 6.0 * xi * zeta + 2.0 * eta * zeta
     365                 :   65740965 :             - 6.0 * xi - 2.0 * eta - 2.0 * zeta + 1.0;
     366                 :   65740965 :       B[5] =  5.0 * eta * eta + zeta * zeta
     367                 :   65740965 :             + 10.0 * xi * eta + 2.0 * xi * zeta + 6.0 * eta * zeta
     368                 :   65740965 :             - 2.0 * xi - 6.0 * eta - 2.0 * zeta + 1.0;
     369                 :   65740965 :       B[6] =  6.0 * zeta * zeta + 12.0 * xi * zeta + 6.0 * eta * zeta - 2.0 * xi
     370                 :   65740965 :             - eta - 7.0 * zeta + 1.0;
     371                 :   65740965 :       B[7] =  10.0 * eta * eta + zeta * zeta + 8.0 * eta * zeta
     372                 :   65740965 :             - 8.0 * eta - 2.0 * zeta + 1.0;
     373                 :   65740965 :       B[8] =  6.0 * zeta * zeta + 18.0 * eta * zeta - 3.0 * eta - 7.0 * zeta
     374                 :   65740965 :             + 1.0;
     375                 :   65740965 :       B[9] =  15.0 * zeta * zeta - 10.0 * zeta + 1.0;
     376                 :            :     }
     377                 :            :   }
     378                 :            : 
     379                 :  289902982 :   return B;
     380                 :            : }
     381                 :            : 
     382                 :            : std::vector< tk::real >
     383         [ +  + ]:  455145443 : tk::eval_state ( ncomp_t ncomp,
     384                 :            :                  const std::size_t ndof,
     385                 :            :                  const std::size_t ndof_el,
     386                 :            :                  const std::size_t e,
     387                 :            :                  const Fields& U,
     388                 :            :                  const std::vector< tk::real >& B )
     389                 :            : // *****************************************************************************
     390                 :            : //  Compute the state variables for the tetrahedron element
     391                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     392                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     393                 :            : //! \param[in] ndof_el Number of degrees of freedom for the local element
     394                 :            : //! \param[in] e Index for the tetrahedron element
     395                 :            : //! \param[in] U Solution vector at recent time step
     396                 :            : //! \param[in] B Vector of basis functions
     397                 :            : //! \return Vector of state variable for tetrahedron element
     398                 :            : // *****************************************************************************
     399                 :            : {
     400                 :            :   // This is commented for now because that when p0/p1 adaptive with limiter
     401                 :            :   // applied, the size of basis will be 10. However, ndof_el will be 4 which
     402                 :            :   // leads to a size mismatch in limiter function.
     403                 :            :   //Assert( B.size() == ndof_el, "Size mismatch" );
     404                 :            : 
     405         [ +  + ]:  455145443 :   if (U.empty()) return {};
     406                 :            : 
     407                 :            :   // Array of state variable for tetrahedron element
     408                 :  294420305 :   std::vector< tk::real > state( ncomp, 0.0 );
     409                 :            : 
     410         [ +  + ]: 1578054840 :   for (ncomp_t c=0; c<ncomp; ++c)
     411                 :            :   {
     412         [ +  + ]: 1283634535 :     auto mark = c*ndof;
     413         [ +  + ]: 1283634535 :     state[c] = U( e, mark );
     414                 :            : 
     415         [ +  + ]: 1283634535 :     if(ndof_el > 1)        // Second order polynomial solution
     416                 :            :     {
     417                 :  979207047 :       state[c] += U( e, mark+1 ) * B[1]
     418                 :  979207047 :                 + U( e, mark+2 ) * B[2]
     419                 :  979207047 :                 + U( e, mark+3 ) * B[3];
     420                 :            :     }
     421                 :            : 
     422         [ +  + ]: 1283634535 :     if(ndof_el > 4)        // Third order polynomial solution
     423                 :            :     {
     424                 :  174496433 :       state[c] += U( e, mark+4 ) * B[4]
     425                 :  174496433 :                 + U( e, mark+5 ) * B[5]
     426                 :  174496433 :                 + U( e, mark+6 ) * B[6]
     427                 :  174496433 :                 + U( e, mark+7 ) * B[7]
     428                 :  174496433 :                 + U( e, mark+8 ) * B[8]
     429                 :  174496433 :                 + U( e, mark+9 ) * B[9];
     430                 :            :     }
     431                 :            :   }
     432                 :            : 
     433                 :            :   return state;
     434                 :            : }
     435                 :            : 
     436                 :            : std::vector< std::vector< tk::real > >
     437                 :          0 : tk::DubinerToTaylor( ncomp_t ncomp,
     438                 :            :                      const std::size_t e,
     439                 :            :                      const std::size_t ndof,
     440                 :            :                      const tk::Fields& U,
     441                 :            :                      const std::vector< std::size_t >& inpoel,
     442                 :            :                      const tk::UnsMesh::Coords& coord )
     443                 :            : // *****************************************************************************
     444                 :            : //  Transform the solution with Dubiner basis to the solution with Taylor basis
     445                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     446                 :            : //! \param[in] e Id of element whose solution is to be limited
     447                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     448                 :            : //! \param[in] U High-order solution vector with Dubiner basis
     449                 :            : //! \param[in] inpoel Element connectivity
     450                 :            : //! \param[in] coord Array of nodal coordinates
     451                 :            : //! \return High-order solution vector with Taylor basis
     452                 :            : // *****************************************************************************
     453                 :            : {
     454                 :            :   std::vector< std::vector< tk::real > >
     455 [ -  - ][ -  - ]:          0 :     unk(ncomp, std::vector<tk::real>(ndof, 0.0));
     456                 :            : 
     457                 :            :   const auto& cx = coord[0];
     458                 :            :   const auto& cy = coord[1];
     459                 :            :   const auto& cz = coord[2];
     460                 :            : 
     461                 :            :   std::array< std::vector< tk::real >, 3 > center;
     462         [ -  - ]:          0 :   center[0].resize(1, 0.25);
     463         [ -  - ]:          0 :   center[1].resize(1, 0.25);
     464         [ -  - ]:          0 :   center[2].resize(1, 0.25);
     465                 :            : 
     466                 :            :   // Evaluate the cell center solution
     467         [ -  - ]:          0 :   for(ncomp_t icomp = 0; icomp < ncomp; icomp++)
     468                 :            :   {
     469                 :          0 :     auto mark = icomp * ndof;
     470                 :          0 :     unk[icomp][0] = U(e, mark);
     471                 :            :   }
     472                 :            : 
     473                 :            :   // Evaluate the first order derivative
     474                 :            :   std::array< std::array< tk::real, 3>, 4 > coordel {{
     475                 :          0 :     {{ cx[ inpoel[4*e  ] ], cy[ inpoel[4*e  ] ], cz[ inpoel[4*e  ] ] }},
     476                 :          0 :     {{ cx[ inpoel[4*e+1] ], cy[ inpoel[4*e+1] ], cz[ inpoel[4*e+1] ] }},
     477                 :          0 :     {{ cx[ inpoel[4*e+2] ], cy[ inpoel[4*e+2] ], cz[ inpoel[4*e+2] ] }},
     478                 :          0 :     {{ cx[ inpoel[4*e+3] ], cy[ inpoel[4*e+3] ], cz[ inpoel[4*e+3] ] }}
     479                 :          0 :   }};
     480                 :            : 
     481                 :            :   auto jacInv =
     482                 :          0 :               tk::inverseJacobian( coordel[0], coordel[1], coordel[2], coordel[3] );
     483                 :            : 
     484                 :            :   // Compute the derivatives of basis function for DG(P1)
     485         [ -  - ]:          0 :   auto dBdx = tk::eval_dBdx_p1( ndof, jacInv );
     486                 :            : 
     487         [ -  - ]:          0 :   if(ndof > 4) {
     488         [ -  - ]:          0 :     tk::eval_dBdx_p2(0, center, jacInv, dBdx);
     489                 :            :   }
     490                 :            : 
     491         [ -  - ]:          0 :   for(ncomp_t icomp = 0; icomp < ncomp; icomp++)
     492                 :            :   {
     493                 :          0 :     auto mark = icomp * ndof; 
     494         [ -  - ]:          0 :     for(std::size_t idir = 0; idir < 3; idir++)
     495                 :            :     {
     496                 :          0 :       unk[icomp][idir+1] = 0;
     497         [ -  - ]:          0 :       for(std::size_t idof = 1; idof < ndof; idof++)
     498                 :          0 :         unk[icomp][idir+1] += U(e, mark+idof) * dBdx[idir][idof];
     499                 :            :     }
     500                 :            :   }
     501                 :            : 
     502                 :            :   // Evaluate the second order derivative if DGP2 is applied
     503                 :            :   // The basic idea of the computation follows
     504                 :            :   //    d2Udx2 = /sum u_i * (d2B_i/dx2)
     505                 :            :   // where d2B_i/dx2 = d( dB_i/dxi * dxi/dx ) / dxi * dxi/dx
     506         [ -  - ]:          0 :   if(ndof > 4)
     507                 :            :   {
     508                 :            :     // Matrix to store the second order derivatives of basis functions in
     509                 :            :     // reference domain
     510                 :          0 :     tk::real d2Bdxi2[6][6] =
     511                 :            :     { { 12.0,  0.0,  0.0,  0.0,  0.0,  0.0 },
     512                 :            :       {  2.0, 10.0,  0.0, 20.0,  0.0,  0.0 },
     513                 :            :       {  2.0,  2.0, 12.0,  2.0, 12.0, 30.0 },
     514                 :            :       {  6.0, 10.0,  0.0,  0.0,  0.0,  0.0 },
     515                 :            :       {  6.0,  2.0, 12.0,  0.0,  0.0,  0.0 },
     516                 :            :       {  2.0,  6.0,  6.0,  8.0, 18.0,  0.0 } };
     517                 :            : 
     518                 :            :     // Transform matrix to convert the second order derivatives of basis
     519                 :            :     // function in reference domain to the one in physical domain
     520                 :            :     tk::real d2xdxi2[6][6];
     521                 :            : 
     522                 :          0 :     d2xdxi2[0][0] = jacInv[0][0] * jacInv[0][0];
     523                 :          0 :     d2xdxi2[0][1] = jacInv[1][0] * jacInv[1][0];
     524                 :          0 :     d2xdxi2[0][2] = jacInv[2][0] * jacInv[2][0];
     525                 :          0 :     d2xdxi2[0][3] = jacInv[0][0] * jacInv[1][0] * 2.0;
     526                 :          0 :     d2xdxi2[0][4] = jacInv[0][0] * jacInv[2][0] * 2.0;
     527                 :          0 :     d2xdxi2[0][5] = jacInv[1][0] * jacInv[2][0] * 2.0;
     528                 :            : 
     529                 :          0 :     d2xdxi2[1][0] = jacInv[0][1] * jacInv[0][1];
     530                 :          0 :     d2xdxi2[1][1] = jacInv[1][1] * jacInv[1][1];
     531                 :          0 :     d2xdxi2[1][2] = jacInv[2][1] * jacInv[2][1];
     532                 :          0 :     d2xdxi2[1][3] = jacInv[0][1] * jacInv[1][1] * 2.0;
     533                 :          0 :     d2xdxi2[1][4] = jacInv[0][1] * jacInv[2][1] * 2.0;
     534                 :          0 :     d2xdxi2[1][5] = jacInv[1][1] * jacInv[2][1] * 2.0;
     535                 :            : 
     536                 :          0 :     d2xdxi2[2][0] = jacInv[0][2] * jacInv[0][2];
     537                 :          0 :     d2xdxi2[2][1] = jacInv[1][2] * jacInv[1][2];
     538                 :          0 :     d2xdxi2[2][2] = jacInv[2][2] * jacInv[2][2];
     539                 :          0 :     d2xdxi2[2][3] = jacInv[0][2] * jacInv[1][2] * 2.0;
     540                 :          0 :     d2xdxi2[2][4] = jacInv[0][2] * jacInv[2][2] * 2.0;
     541                 :          0 :     d2xdxi2[2][5] = jacInv[1][2] * jacInv[2][2] * 2.0;
     542                 :            : 
     543                 :          0 :     d2xdxi2[3][0] = jacInv[0][0] * jacInv[0][1];
     544                 :          0 :     d2xdxi2[3][1] = jacInv[1][0] * jacInv[1][1];
     545                 :          0 :     d2xdxi2[3][2] = jacInv[2][0] * jacInv[2][1];
     546                 :          0 :     d2xdxi2[3][3] = jacInv[0][0] * jacInv[1][1] + jacInv[1][0] * jacInv[0][1];
     547                 :          0 :     d2xdxi2[3][4] = jacInv[0][0] * jacInv[2][1] + jacInv[2][0] * jacInv[0][1];
     548                 :          0 :     d2xdxi2[3][5] = jacInv[1][0] * jacInv[2][1] + jacInv[2][0] * jacInv[1][1];
     549                 :            : 
     550                 :          0 :     d2xdxi2[4][0] = jacInv[0][0] * jacInv[0][2];
     551                 :          0 :     d2xdxi2[4][1] = jacInv[1][0] * jacInv[1][2];
     552                 :          0 :     d2xdxi2[4][2] = jacInv[2][0] * jacInv[2][2];
     553                 :          0 :     d2xdxi2[4][3] = jacInv[0][0] * jacInv[1][2] + jacInv[1][0] * jacInv[0][2];
     554                 :          0 :     d2xdxi2[4][4] = jacInv[0][0] * jacInv[2][2] + jacInv[2][0] * jacInv[0][2];
     555                 :          0 :     d2xdxi2[4][5] = jacInv[1][0] * jacInv[2][2] + jacInv[2][0] * jacInv[1][2];
     556                 :            : 
     557                 :          0 :     d2xdxi2[5][0] = jacInv[0][1] * jacInv[0][2];
     558                 :          0 :     d2xdxi2[5][1] = jacInv[1][1] * jacInv[1][2];
     559                 :          0 :     d2xdxi2[5][2] = jacInv[2][1] * jacInv[2][2];
     560                 :          0 :     d2xdxi2[5][3] = jacInv[0][1] * jacInv[1][2] + jacInv[1][1] * jacInv[0][2];
     561                 :          0 :     d2xdxi2[5][4] = jacInv[0][1] * jacInv[2][2] + jacInv[2][1] * jacInv[0][2];
     562                 :          0 :     d2xdxi2[5][5] = jacInv[1][1] * jacInv[2][2] + jacInv[2][1] * jacInv[1][2];
     563                 :            : 
     564                 :            :     // Matrix to store the second order derivatives of basis functions in
     565                 :            :     // physical domain
     566                 :            :     tk::real d2Bdx2[6][6];
     567         [ -  - ]:          0 :     for(std::size_t ibasis = 0; ibasis < 6; ibasis++) {
     568         [ -  - ]:          0 :       for(std::size_t idir = 0; idir < 6; idir++) {
     569                 :          0 :         d2Bdx2[idir][ibasis] = 0;
     570         [ -  - ]:          0 :         for(std::size_t k = 0; k < 6; k++)
     571                 :          0 :           d2Bdx2[idir][ibasis] += d2xdxi2[idir][k] * d2Bdxi2[k][ibasis];
     572                 :            :       }
     573                 :            :     }
     574                 :            : 
     575         [ -  - ]:          0 :     for(ncomp_t icomp = 0; icomp < ncomp; icomp++)
     576                 :            :     {
     577                 :          0 :       auto mark = icomp * ndof;
     578         [ -  - ]:          0 :       for(std::size_t idir = 0; idir < 6; idir++)
     579                 :            :       {
     580                 :          0 :         unk[icomp][idir+4] = 0;
     581         [ -  - ]:          0 :         for(std::size_t ibasis = 0; ibasis < 6; ibasis++)
     582                 :          0 :           unk[icomp][idir+4] += U(e, mark+4+ibasis) * d2Bdx2[idir][ibasis];
     583                 :            :       }
     584                 :            :     }
     585                 :            :   }
     586                 :          0 :   return unk;
     587                 :            : }
     588                 :            : 
     589                 :            : void
     590                 :          0 : tk::TaylorToDubiner( ncomp_t ncomp,
     591                 :            :                      std::size_t e,
     592                 :            :                      std::size_t ndof,
     593                 :            :                      const std::vector< std::size_t >& inpoel,
     594                 :            :                      const tk::UnsMesh::Coords& coord,
     595                 :            :                      const tk::Fields& geoElem,
     596                 :            :                      std::vector< std::vector< tk::real > >& unk )
     597                 :            : // *****************************************************************************
     598                 :            : //  Convert the solution with Taylor basis to the solution with Dubiner basis by
     599                 :            : //    projection method
     600                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     601                 :            : //! \param[in] e Id of element whose solution is to be limited
     602                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     603                 :            : //! \param[in] inpoel Element connectivity
     604                 :            : //! \param[in] coord Array of nodal coordinates
     605                 :            : //! \param[in, out] unk High-order solution vector with Taylor basis
     606                 :            : // *****************************************************************************
     607                 :            : {
     608                 :            :   Assert( ncomp > 0, "Number of scalar components is incorrect" );
     609                 :            : 
     610                 :            :   // The diagonal of mass matrix
     611                 :          0 :   std::vector< tk::real > L(ndof, 0.0);
     612                 :            : 
     613                 :            :   tk::real vol = 1.0 / 6.0;
     614                 :            : 
     615                 :          0 :   L[0] = vol;
     616                 :            : 
     617         [ -  - ]:          0 :   if(ndof > 1) {
     618                 :            :     Assert( (ndof == 4)||(ndof == 10),
     619                 :            :       "Mismatch in number of degrees of freedom" );
     620                 :          0 :     L[1] = vol / 10.0;
     621                 :          0 :     L[2] = vol * 3.0/10.0;
     622                 :          0 :     L[3] = vol * 3.0/5.0;
     623                 :            :   }
     624                 :            : 
     625         [ -  - ]:          0 :   if(ndof > 4) {
     626                 :            :     Assert( ndof == 10, "Mismatch in number of degrees of freedom" );
     627                 :          0 :     L[4] = vol / 35.0;
     628                 :          0 :     L[5] = vol / 21.0;
     629                 :          0 :     L[6] = vol / 14.0;
     630                 :          0 :     L[7] = vol / 7.0;
     631                 :          0 :     L[8] = vol * 3.0/14.0;
     632                 :          0 :     L[9] = vol * 3.0/7.0;
     633                 :            :   }
     634                 :            : 
     635                 :            :   // Coordinates of the centroid in physical domain
     636                 :          0 :   std::array< tk::real, 3 > x_c{geoElem(e,1), geoElem(e,2), geoElem(e,3)};
     637                 :            : 
     638                 :            :   const auto& cx = coord[0];
     639                 :            :   const auto& cy = coord[1];
     640                 :            :   const auto& cz = coord[2];
     641                 :            : 
     642                 :            :   std::array< std::array< tk::real, 3>, 4 > coordel {{
     643                 :          0 :     {{ cx[ inpoel[4*e  ] ], cy[ inpoel[4*e  ] ], cz[ inpoel[4*e  ] ] }},
     644                 :          0 :     {{ cx[ inpoel[4*e+1] ], cy[ inpoel[4*e+1] ], cz[ inpoel[4*e+1] ] }},
     645                 :          0 :     {{ cx[ inpoel[4*e+2] ], cy[ inpoel[4*e+2] ], cz[ inpoel[4*e+2] ] }},
     646                 :          0 :     {{ cx[ inpoel[4*e+3] ], cy[ inpoel[4*e+3] ], cz[ inpoel[4*e+3] ] }}
     647                 :          0 :   }};
     648                 :            : 
     649                 :            :   // Number of quadrature points for volume integration
     650         [ -  - ]:          0 :   auto ng = tk::NGvol(ndof);
     651                 :            : 
     652                 :            :   // arrays for quadrature points
     653                 :            :   std::array< std::vector< tk::real >, 3 > coordgp;
     654                 :            :   std::vector< tk::real > wgp;
     655                 :            : 
     656         [ -  - ]:          0 :   coordgp[0].resize( ng );
     657         [ -  - ]:          0 :   coordgp[1].resize( ng );
     658         [ -  - ]:          0 :   coordgp[2].resize( ng );
     659         [ -  - ]:          0 :   wgp.resize( ng );
     660                 :            : 
     661                 :            :   // get quadrature point weights and coordinates for triangle
     662         [ -  - ]:          0 :   tk::GaussQuadratureTet( ng, coordgp, wgp );
     663                 :            : 
     664                 :            :   // right hand side vector
     665 [ -  - ][ -  - ]:          0 :   std::vector< tk::real > R( ncomp*ndof, 0.0 );
     666                 :            : 
     667                 :            :   // Gaussian quadrature
     668         [ -  - ]:          0 :   for (std::size_t igp=0; igp<ng; ++igp)
     669                 :            :   {
     670         [ -  - ]:          0 :     auto wt = wgp[igp] * vol;
     671                 :            : 
     672         [ -  - ]:          0 :     auto gp = tk::eval_gp( igp, coordel, coordgp );
     673                 :            : 
     674         [ -  - ]:          0 :     auto B_taylor = eval_TaylorBasis( ndof, gp, x_c, coordel);
     675                 :            : 
     676                 :            :     // Compute high order solution at gauss point
     677 [ -  - ][ -  - ]:          0 :     std::vector< tk::real > state( ncomp, 0.0 );
     678         [ -  - ]:          0 :     for (ncomp_t c=0; c<ncomp; ++c)
     679                 :            :     {
     680         [ -  - ]:          0 :       state[c] = unk[c][0];
     681                 :          0 :       state[c] += unk[c][1] * B_taylor[1]
     682                 :          0 :                 + unk[c][2] * B_taylor[2]
     683                 :          0 :                 + unk[c][3] * B_taylor[3];
     684                 :            : 
     685         [ -  - ]:          0 :       if(ndof > 4)
     686                 :          0 :         state[c] += unk[c][4] * B_taylor[4] + unk[c][5] * B_taylor[5]
     687                 :          0 :                   + unk[c][6] * B_taylor[6] + unk[c][7] * B_taylor[7]
     688                 :          0 :                   + unk[c][8] * B_taylor[8] + unk[c][9] * B_taylor[9];
     689                 :            :     }
     690                 :            : 
     691         [ -  - ]:          0 :     auto B = tk::eval_basis( ndof, coordgp[0][igp], coordgp[1][igp], coordgp[2][igp] );
     692                 :            : 
     693         [ -  - ]:          0 :     for (ncomp_t c=0; c<ncomp; ++c)
     694                 :            :     {
     695                 :          0 :       auto mark = c*ndof;
     696         [ -  - ]:          0 :       R[mark] += wt * state[c];
     697                 :            : 
     698         [ -  - ]:          0 :       if(ndof > 1)
     699                 :            :       {
     700         [ -  - ]:          0 :         R[mark+1] += wt * state[c] * B[1];
     701                 :          0 :         R[mark+2] += wt * state[c] * B[2];
     702                 :          0 :         R[mark+3] += wt * state[c] * B[3];
     703                 :            : 
     704         [ -  - ]:          0 :         if(ndof > 4)
     705                 :            :         {
     706                 :          0 :           R[mark+4] += wt * state[c] * B[4];
     707                 :          0 :           R[mark+5] += wt * state[c] * B[5];
     708                 :          0 :           R[mark+6] += wt * state[c] * B[6];
     709                 :          0 :           R[mark+7] += wt * state[c] * B[7];
     710                 :          0 :           R[mark+8] += wt * state[c] * B[8];
     711                 :          0 :           R[mark+9] += wt * state[c] * B[9];
     712                 :            :         }
     713                 :            :       }
     714                 :            :     }
     715                 :            :   }
     716                 :            : 
     717         [ -  - ]:          0 :   for (ncomp_t c=0; c<ncomp; ++c)
     718                 :            :   {
     719                 :          0 :     auto mark = c*ndof;
     720         [ -  - ]:          0 :     for(std::size_t idof = 0; idof < ndof; idof++)
     721                 :          0 :       unk[c][idof] = R[mark+idof] / L[idof];
     722                 :            :   }
     723                 :          0 : }
     724                 :            : 
     725                 :            : std::vector< tk::real >
     726                 :          0 : tk::eval_TaylorBasis( const std::size_t ndof,
     727                 :            :                       const std::array< tk::real, 3 >& x,
     728                 :            :                       const std::array< tk::real, 3 >& x_c,
     729                 :            :                       const std::array< std::array< tk::real, 3>, 4 >& coordel )
     730                 :            : // *****************************************************************************
     731                 :            : //  Evaluate the Taylor basis at points
     732                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     733                 :            : //! \param[in] x Nodal coordinates
     734                 :            : //! \param[in] x_c Coordinates of the centroid
     735                 :            : //! \param[in] coordel Array of nodal coordinates for the tetrahedron
     736                 :            : // *****************************************************************************
     737                 :            : {
     738                 :          0 :   std::vector< tk::real > avg( 6, 0.0 );
     739         [ -  - ]:          0 :   if(ndof > 4)
     740                 :            :   {
     741                 :            :     Assert( ndof == 10, "Mismatch in number of degrees of freedom" );
     742         [ -  - ]:          0 :     auto ng = tk::NGvol(ndof);
     743                 :            : 
     744                 :            :     std::array< std::vector< tk::real >, 3 > coordgp;
     745                 :            :     std::vector< tk::real > wgp;
     746                 :            : 
     747         [ -  - ]:          0 :     coordgp[0].resize( ng );
     748         [ -  - ]:          0 :     coordgp[1].resize( ng );
     749         [ -  - ]:          0 :     coordgp[2].resize( ng );
     750         [ -  - ]:          0 :     wgp.resize( ng );
     751                 :            : 
     752         [ -  - ]:          0 :     tk::GaussQuadratureTet( ng, coordgp, wgp );
     753                 :            : 
     754         [ -  - ]:          0 :     for (std::size_t igp=0; igp<ng; ++igp)
     755                 :            :     {
     756                 :            :       // Compute the coordinates of quadrature point at physical domain
     757         [ -  - ]:          0 :       auto gp = tk::eval_gp( igp, coordel, coordgp );
     758                 :            : 
     759                 :          0 :       avg[0] += wgp[igp] * (gp[0] - x_c[0]) * (gp[0] - x_c[0]) * 0.5;
     760                 :          0 :       avg[1] += wgp[igp] * (gp[1] - x_c[1]) * (gp[1] - x_c[1]) * 0.5;
     761                 :          0 :       avg[2] += wgp[igp] * (gp[2] - x_c[2]) * (gp[2] - x_c[2]) * 0.5;
     762                 :          0 :       avg[3] += wgp[igp] * (gp[0] - x_c[0]) * (gp[1] - x_c[1]);
     763                 :          0 :       avg[4] += wgp[igp] * (gp[0] - x_c[0]) * (gp[2] - x_c[2]);
     764                 :          0 :       avg[5] += wgp[igp] * (gp[1] - x_c[1]) * (gp[2] - x_c[2]);
     765                 :            :     }
     766                 :            :   }
     767                 :            : 
     768 [ -  - ][ -  - ]:          0 :   std::vector< tk::real > B( ndof, 1.0 );
     769                 :            : 
     770         [ -  - ]:          0 :   if(ndof > 1) {
     771                 :            :     Assert( (ndof == 4)||(ndof == 10) ,
     772                 :            :       "Mismatch in number of degrees of freedom" );
     773                 :          0 :     B[1] = x[0] - x_c[0];
     774                 :          0 :     B[2] = x[1] - x_c[1];
     775                 :          0 :     B[3] = x[2] - x_c[2];
     776                 :            :   }
     777                 :            : 
     778         [ -  - ]:          0 :   if(ndof > 4) {
     779                 :          0 :     B[4] = B[1] * B[1] * 0.5 - avg[0];
     780                 :          0 :     B[5] = B[2] * B[2] * 0.5 - avg[1];
     781                 :          0 :     B[6] = B[3] * B[3] * 0.5 - avg[2];
     782                 :          0 :     B[7] = B[1] * B[2] - avg[3];
     783                 :          0 :     B[8] = B[1] * B[3] - avg[4];
     784                 :          0 :     B[9] = B[2] * B[3] - avg[5];
     785                 :            :   }
     786                 :            : 
     787                 :          0 :   return B;
     788                 :            : }
     789                 :            : 
     790                 :            : // -----------------------------------------------------------------------------
     791                 :            : // Functions for reference element Taylor basis and related Xforms
     792                 :            : // -----------------------------------------------------------------------------
     793                 :            : 
     794                 :            : std::vector< std::vector< tk::real > >
     795                 :          0 : tk::DubinerToTaylorRefEl( ncomp_t ncomp,
     796                 :            :   const std::size_t e,
     797                 :            :   const std::size_t ndof,
     798                 :            :   const std::size_t ndof_el,
     799                 :            :   const std::vector< std::vector< tk::real > >& mtInv,
     800                 :            :   const tk::Fields& U )
     801                 :            : // *****************************************************************************
     802                 :            : //  Transform the solution from Dubiner basis to Taylor basis
     803                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     804                 :            : //! \param[in] e Id of element whose solution is to be limited
     805                 :            : //! \param[in] ndof Maximum number of degrees of freedom
     806                 :            : //! \param[in] ndof_el Local number of degrees of freedom for the element
     807                 :            : //! \param[in] mtInv Inverse of Taylor mass matrix
     808                 :            : //! \param[in] U High-order solution vector with Dubiner basis
     809                 :            : //! \return High-order solution vector with Taylor basis (ref element)
     810                 :            : // *****************************************************************************
     811                 :            : {
     812                 :            :   auto vol = 1.0/6.0;
     813                 :            : 
     814                 :            :   // 1. Get rhs for L2-projection
     815                 :            :   // Quadrature setup
     816                 :          0 :   auto ng = tk::NGvol(ndof_el);
     817                 :            :   std::array< std::vector< real >, 3 > coordgp;
     818                 :            :   std::vector< real > wgp;
     819         [ -  - ]:          0 :   coordgp[0].resize( ng );
     820         [ -  - ]:          0 :   coordgp[1].resize( ng );
     821         [ -  - ]:          0 :   coordgp[2].resize( ng );
     822         [ -  - ]:          0 :   wgp.resize( ng );
     823         [ -  - ]:          0 :   GaussQuadratureTet( ng, coordgp, wgp );
     824                 :            : 
     825                 :            :   // Gaussian quadrature
     826                 :            :   std::vector< std::vector< tk::real > >
     827 [ -  - ][ -  - ]:          0 :     R(ncomp, std::vector<tk::real>(ndof_el, 0.0));
                 [ -  - ]
     828         [ -  - ]:          0 :   for (std::size_t igp=0; igp<ng; ++igp)
     829                 :            :   {
     830                 :            :     // Dubiner basis functions
     831         [ -  - ]:          0 :     auto B = eval_basis( ndof_el, coordgp[0][igp], coordgp[1][igp],
     832         [ -  - ]:          0 :                          coordgp[2][igp] );
     833                 :            :     // Taylor basis functions
     834         [ -  - ]:          0 :     auto Bt = eval_TaylorBasisRefEl(ndof_el, coordgp[0][igp], coordgp[1][igp],
     835         [ -  - ]:          0 :       coordgp[2][igp]);
     836                 :            : 
     837         [ -  - ]:          0 :     auto state = tk::eval_state(ncomp, ndof, ndof_el, e, U, B);
     838                 :            : 
     839         [ -  - ]:          0 :     for (std::size_t c=0; c<ncomp; ++c) {
     840         [ -  - ]:          0 :       for (std::size_t id=0; id<ndof_el; ++id) {
     841                 :          0 :         R[c][id] += wgp[igp] * vol * state[c] * Bt[id];
     842                 :            :       }
     843                 :            :     }
     844                 :            :   }
     845                 :            : 
     846                 :            : 
     847                 :            :   // 2. Get Taylor solution by premultiplying by mass matrix inverse
     848                 :            :   std::vector< std::vector< tk::real > >
     849 [ -  - ][ -  - ]:          0 :     unk(ncomp, std::vector<tk::real>(ndof_el, 0.0));
     850         [ -  - ]:          0 :   for (std::size_t c=0; c<ncomp; ++c) {
     851         [ -  - ]:          0 :     for (std::size_t id=0; id<ndof_el; ++id) {
     852         [ -  - ]:          0 :       for (std::size_t jd=0; jd<ndof_el; ++jd) {
     853                 :          0 :         unk[c][id] += mtInv[id][jd] * R[c][jd];
     854                 :            :       }
     855                 :            :     }
     856                 :            :   }
     857                 :            : 
     858                 :          0 :   return unk;
     859                 :            : }
     860                 :            : 
     861                 :            : void
     862                 :          0 : tk::TaylorToDubinerRefEl( ncomp_t ncomp,
     863                 :            :   const std::size_t ndof,
     864                 :            :   std::vector< std::vector< tk::real > >& unk )
     865                 :            : // *****************************************************************************
     866                 :            : //  Transform the solution from Taylor to Dubiner basis
     867                 :            : //! \param[in] ncomp Number of scalar components in this PDE system
     868                 :            : //! \param[in] ndof Number of degrees of freedom
     869                 :            : //! \param[in,out] unk High-order solution vector with Taylor basis that gets
     870                 :            : //!   transformed to solution with Dubiner basis
     871                 :            : // *****************************************************************************
     872                 :            : {
     873                 :            :   auto vol = 1.0/6.0;
     874                 :            : 
     875                 :          0 :   auto M = massMatrixDubiner(ndof, vol);
     876                 :            : 
     877                 :            :   // 1. Get rhs for L2-projection
     878                 :            :   // Quadrature setup
     879         [ -  - ]:          0 :   auto ng = tk::NGvol(ndof);
     880                 :            :   std::array< std::vector< real >, 3 > coordgp;
     881                 :            :   std::vector< real > wgp;
     882         [ -  - ]:          0 :   coordgp[0].resize( ng );
     883         [ -  - ]:          0 :   coordgp[1].resize( ng );
     884         [ -  - ]:          0 :   coordgp[2].resize( ng );
     885         [ -  - ]:          0 :   wgp.resize( ng );
     886         [ -  - ]:          0 :   GaussQuadratureTet( ng, coordgp, wgp );
     887                 :            : 
     888                 :            :   // Gaussian quadrature
     889                 :            :   std::vector< std::vector< tk::real > >
     890 [ -  - ][ -  - ]:          0 :     R(ncomp, std::vector<tk::real>(ndof, 0.0));
                 [ -  - ]
     891         [ -  - ]:          0 :   for (std::size_t igp=0; igp<ng; ++igp)
     892                 :            :   {
     893                 :            :     // Dubiner basis functions
     894         [ -  - ]:          0 :     auto B = eval_basis( ndof, coordgp[0][igp], coordgp[1][igp],
     895         [ -  - ]:          0 :                          coordgp[2][igp] );
     896                 :            :     // Taylor basis functions
     897         [ -  - ]:          0 :     auto Bt = eval_TaylorBasisRefEl(ndof, coordgp[0][igp], coordgp[1][igp],
     898         [ -  - ]:          0 :       coordgp[2][igp]);
     899                 :            : 
     900         [ -  - ]:          0 :     for (std::size_t c=0; c<ncomp; ++c) {
     901                 :            :       real state(0.0);
     902         [ -  - ]:          0 :       for (std::size_t id=0; id<ndof; ++id) {
     903                 :          0 :         state += unk[c][id] * Bt[id];
     904                 :            :       }
     905         [ -  - ]:          0 :       for (std::size_t id=0; id<ndof; ++id) {
     906                 :          0 :         R[c][id] += wgp[igp] * vol * state * B[id];
     907                 :            :       }
     908                 :            :     }
     909                 :            :   }
     910                 :            : 
     911                 :            :   // 2. Get Dubiner solution by premultiplying by mass matrix inverse
     912         [ -  - ]:          0 :   for (std::size_t c=0; c<ncomp; ++c) {
     913         [ -  - ]:          0 :     for (std::size_t id=0; id<ndof; ++id) {
     914                 :          0 :       unk[c][id] = R[c][id] / M[id];
     915                 :            :     }
     916                 :            :   }
     917                 :          0 : }
     918                 :            : 
     919                 :            : std::vector< tk::real >
     920                 :       2844 : tk::eval_TaylorBasisRefEl( std::size_t ndof, tk::real x, tk::real y,
     921                 :            :   tk::real z )
     922                 :            : // *****************************************************************************
     923                 :            : //  Evaluate the Taylor basis at a point in the reference element
     924                 :            : //! \param[in] ndof Number of degrees of freedom
     925                 :            : //! \param[in] x Xi coordinate of point in reference element
     926                 :            : //! \param[in] y Eta coordinate of point in reference element
     927                 :            : //! \param[in] z Zeta coordinate of point in reference element
     928                 :            : // *****************************************************************************
     929                 :            : {
     930                 :            :   // Get averages required for P2 basis functions
     931                 :       2844 :   std::vector< tk::real > avg( 6, 0.0 );
     932         [ +  + ]:       2844 :   if(ndof > 4)
     933                 :            :   {
     934         [ +  - ]:       1694 :     auto ng = tk::NGvol(ndof);
     935                 :            :     std::array< std::vector< tk::real >, 3 > coordgp;
     936                 :            :     std::vector< tk::real > wgp;
     937         [ +  - ]:       1694 :     coordgp[0].resize( ng );
     938         [ +  - ]:       1694 :     coordgp[1].resize( ng );
     939         [ +  - ]:       1694 :     coordgp[2].resize( ng );
     940         [ +  - ]:       1694 :     wgp.resize( ng );
     941         [ +  - ]:       1694 :     tk::GaussQuadratureTet( ng, coordgp, wgp );
     942                 :            : 
     943         [ +  + ]:      20328 :     for (std::size_t igp=0; igp<ng; ++igp)
     944                 :            :     {
     945                 :      18634 :       avg[0] += wgp[igp] * (coordgp[0][igp] - 0.25) * (coordgp[0][igp] - 0.25) * 0.5;
     946                 :      18634 :       avg[1] += wgp[igp] * (coordgp[1][igp] - 0.25) * (coordgp[1][igp] - 0.25) * 0.5;
     947                 :      18634 :       avg[2] += wgp[igp] * (coordgp[2][igp] - 0.25) * (coordgp[2][igp] - 0.25) * 0.5;
     948                 :      18634 :       avg[3] += wgp[igp] * (coordgp[0][igp] - 0.25) * (coordgp[1][igp] - 0.25);
     949                 :      18634 :       avg[4] += wgp[igp] * (coordgp[0][igp] - 0.25) * (coordgp[2][igp] - 0.25);
     950                 :      18634 :       avg[5] += wgp[igp] * (coordgp[1][igp] - 0.25) * (coordgp[2][igp] - 0.25);
     951                 :            :     }
     952                 :            :   }
     953                 :            : 
     954                 :            :   // Get Taylor basis functions
     955 [ +  - ][ -  - ]:       2844 :   std::vector< tk::real > B( ndof, 1.0 );
     956         [ +  - ]:       2844 :   if(ndof > 1) {
     957                 :       2844 :     B[1] = x - 0.25;
     958                 :       2844 :     B[2] = y - 0.25;
     959                 :       2844 :     B[3] = z - 0.25;
     960         [ +  + ]:       2844 :     if(ndof > 4) {
     961                 :       1694 :       B[4] = B[1] * B[1] * 0.5 - avg[0];
     962                 :       1694 :       B[5] = B[2] * B[2] * 0.5 - avg[1];
     963                 :       1694 :       B[6] = B[3] * B[3] * 0.5 - avg[2];
     964                 :       1694 :       B[7] = B[1] * B[2] - avg[3];
     965                 :       1694 :       B[8] = B[1] * B[3] - avg[4];
     966                 :       1694 :       B[9] = B[2] * B[3] - avg[5];
     967                 :            :     }
     968                 :            :   }
     969                 :            : 
     970                 :       2844 :   return B;
     971                 :            : }
     972                 :            : 
     973                 :            : std::vector< std::vector< tk::real > >
     974                 :        801 : tk::invMassMatTaylorRefEl( std::size_t dof )
     975                 :            : // *****************************************************************************
     976                 :            : //  Obtain inverse mass matrix for Taylor basis in reference element
     977                 :            : //! \param[in] dof Number of degrees of freedom
     978                 :            : //! \return Inverse mass matrix
     979                 :            : // *****************************************************************************
     980                 :            : {
     981                 :            :   // Get Taylor mass matrix
     982                 :        801 :   auto Mt = massMatrixTaylorRefEl(dof);
     983                 :            : 
     984                 :            :   // Only invert if DGP2
     985         [ +  + ]:        801 :   if (dof > 4) {
     986                 :            :     double mtInv[10*10];
     987         [ +  + ]:       1694 :     for (std::size_t i=0; i<Mt.size(); ++i) {
     988         [ +  + ]:      16940 :       for (std::size_t j=0; j<Mt[i].size(); ++j) {
     989                 :      15400 :         std::size_t idx = 10*i+j;
     990                 :      15400 :         mtInv[idx] = Mt[i][j];
     991                 :            :       }
     992                 :            :     }
     993                 :            :     lapack_int ipiv[10];
     994                 :            :     // LU-factorization for inversion
     995         [ +  - ]:        154 :     lapack_int info1 = LAPACKE_dgetrf(LAPACK_ROW_MAJOR, 10, 10, mtInv, 10, ipiv);
     996 [ -  + ][ -  - ]:        154 :     if (info1 != 0) Throw("Taylor mass matrix is singular");
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     997                 :            :     // Inversion
     998         [ +  - ]:        154 :     lapack_int info2 = LAPACKE_dgetri(LAPACK_ROW_MAJOR, 10, mtInv, 10, ipiv);
     999 [ +  - ][ -  - ]:        154 :     if (info2 != 0) Throw("Error while inverting Taylor mass matrix");
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
    1000                 :            : 
    1001                 :            :     // Get 2D vector from 1D array mass matrix inverse
    1002         [ +  + ]:       1694 :     for (std::size_t i=0; i<Mt.size(); ++i) {
    1003         [ +  + ]:      16940 :       for (std::size_t j=0; j<Mt[i].size(); ++j) {
    1004                 :      15400 :         std::size_t idx = 10*i+j;
    1005                 :      15400 :         Mt[i][j] = mtInv[idx];
    1006                 :            :       }
    1007                 :            :     }
    1008                 :            :   }
    1009                 :            : 
    1010                 :        801 :   return Mt;
    1011                 :            : }
    1012                 :            : 
    1013                 :            : std::vector< std::vector< tk::real > >
    1014                 :        801 : tk::massMatrixTaylorRefEl(std::size_t dof)
    1015                 :            : // *****************************************************************************
    1016                 :            : //  Obtain mass matrix for Taylor basis in reference element
    1017                 :            : //! \param[in] dof Number of degrees of freedom
    1018                 :            : //! \return Mass matrix
    1019                 :            : // *****************************************************************************
    1020                 :            : {
    1021                 :            :   std::vector< std::vector< tk::real > >
    1022 [ +  - ][ +  - ]:        801 :     Mt(dof, std::vector<tk::real>(dof,0.0));
    1023                 :            : 
    1024                 :            :   // Mt(1,1)
    1025                 :            :   tk::real vol = 1.0/6.0;
    1026                 :        801 :   Mt[0][0] = vol;
    1027                 :            : 
    1028                 :            :   // Mt(i,j) for i,j > 1
    1029         [ +  + ]:        801 :   if (dof > 1) {
    1030                 :            :     // Quadrature information
    1031         [ +  - ]:        384 :     auto ng = tk::NGvol(dof);
    1032                 :            :     std::array< std::vector< tk::real >, 3 > coordgp;
    1033                 :            :     std::vector< tk::real > wgp;
    1034         [ +  - ]:        384 :     coordgp[0].resize( ng );
    1035         [ +  - ]:        384 :     coordgp[1].resize( ng );
    1036         [ +  - ]:        384 :     coordgp[2].resize( ng );
    1037         [ +  - ]:        384 :     wgp.resize( ng );
    1038         [ +  - ]:        384 :     tk::GaussQuadratureTet( ng, coordgp, wgp );
    1039                 :            : 
    1040         [ +  + ]:       3228 :     for (std::size_t igp=0; igp<ng; ++igp)
    1041                 :            :     {
    1042         [ +  - ]:       2844 :       auto Bt = eval_TaylorBasisRefEl(dof, coordgp[0][igp], coordgp[1][igp],
    1043 [ +  - ][ +  - ]:       5688 :         coordgp[2][igp]);
    1044         [ +  + ]:      21540 :       for (std::size_t id=1; id<dof; ++id) {
    1045         [ +  + ]:     166260 :         for (std::size_t jd=1; jd<dof; ++jd) {
    1046                 :     147564 :           Mt[id][jd] += vol*wgp[igp]*Bt[id]*Bt[jd];
    1047                 :            :         }
    1048                 :            :       }
    1049                 :            :     }
    1050                 :            :   }
    1051                 :            : 
    1052                 :        801 :   return Mt;
    1053                 :            : }

Generated by: LCOV version 1.14