LCOV - code coverage report
Current view: top level - /builds/ug4-project/ugcore/ug4-new/plugins/ConvectionDiffusion/fvcr - convection_diffusion_fvcr.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 267 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 234 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2012-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Christian Wehner
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include "convection_diffusion_fvcr.h"
      34              : 
      35              : #include "lib_disc/spatial_disc/disc_util/geom_provider.h"
      36              : #include "lib_disc/spatial_disc/disc_util/fvcr_geom.h"
      37              : #include "lib_disc/spatial_disc/disc_util/hfvcr_geom.h"
      38              : #include "lib_disc/spatial_disc/disc_util/conv_shape.h"
      39              : 
      40              : namespace ug{
      41              : namespace ConvectionDiffusionPlugin{
      42              : 
      43              : ////////////////////////////////////////////////////////////////////////////////
      44              : //      general
      45              : ////////////////////////////////////////////////////////////////////////////////
      46              : 
      47              : template<typename TDomain>
      48            0 : ConvectionDiffusionFVCR<TDomain>::
      49              : ConvectionDiffusionFVCR(const char* functions, const char* subsets)
      50              :  : ConvectionDiffusionBase<TDomain>(functions,subsets),
      51            0 :    m_spConvShape(new ConvectionShapesNoUpwind<dim>),
      52            0 :    m_bNonRegularGrid(false)
      53              : {
      54            0 :         register_all_funcs(m_bNonRegularGrid);
      55            0 : }
      56              : 
      57              : template<typename TDomain>
      58            0 : void ConvectionDiffusionFVCR<TDomain>::
      59              : prepare_setting(const std::vector<LFEID>& vLfeID, bool bNonRegularGrid)
      60              : {
      61              : //      check number
      62            0 :         if(vLfeID.size() != 1)
      63            0 :                 UG_THROW("ConvectionDiffusion: Wrong number of functions given. "
      64              :                                 "Need exactly "<<1);
      65              : 
      66            0 :         if(vLfeID[0].order() != 1 || vLfeID[0].type() != LFEID::CROUZEIX_RAVIART)
      67            0 :                 UG_THROW("ConvectionDiffusion FVCR Scheme only implemented for 1st order.");
      68              : 
      69              : //      remember
      70            0 :         m_bNonRegularGrid = bNonRegularGrid;
      71              : 
      72              : //      update assemble functions
      73            0 :         register_all_funcs(m_bNonRegularGrid);
      74            0 : }
      75              : 
      76              : template<typename TDomain>
      77            0 : bool ConvectionDiffusionFVCR<TDomain>::
      78              : use_hanging() const
      79              : {
      80            0 :         return true;
      81              : }
      82              : 
      83              : 
      84              : ////////////////////////////////////////////////////////////////////////////////
      85              : // Assembling functions
      86              : ////////////////////////////////////////////////////////////////////////////////
      87              : 
      88              : 
      89              : template<typename TDomain>
      90              : template<typename TElem, typename TFVGeom>
      91            0 : void ConvectionDiffusionFVCR<TDomain>::
      92              : prep_elem_loop(const ReferenceObjectID roid, const int si)
      93              : {
      94            0 :         if(m_imFlux.data_given())
      95            0 :                 UG_THROW("ConvectionDiffusionFVCR: Flux import not implemented.");
      96              : 
      97            0 :         if(     m_imSourceExpl.data_given() ||
      98            0 :                 m_imReactionExpl.data_given() ||
      99              :                 m_imReactionRateExpl.data_given())
     100            0 :                 UG_THROW("ConvectionDiffusionFVCR: Explicit terms not implemented.");
     101              : 
     102              : //      set local positions
     103              :         if(!TFVGeom::usesHangingNodes)
     104              :         {
     105              :                 static const int refDim = TElem::dim;
     106            0 :                 static TFVGeom& geo = GeomProvider<TFVGeom>::get();
     107              : 
     108            0 :                 geo.update_local_data();
     109              : 
     110            0 :                 m_imDiffusion.template  set_local_ips<refDim>(geo.scvf_local_ips(),
     111              :                                                               geo.num_scvf_ips(), false);
     112            0 :                 m_imVelocity.template   set_local_ips<refDim>(geo.scvf_local_ips(),
     113              :                                                               geo.num_scvf_ips(), false);
     114            0 :                 m_imSource.template     set_local_ips<refDim>(geo.scv_local_ips(),
     115              :                                                               geo.num_scv_ips(), false);
     116            0 :                 m_imReactionRate.template       set_local_ips<refDim>(geo.scv_local_ips(),
     117              :                                                               geo.num_scv_ips(), false);
     118            0 :                 m_imReaction.template   set_local_ips<refDim>(geo.scv_local_ips(),
     119              :                                                               geo.num_scv_ips(), false);
     120            0 :                 m_imMassScale.template  set_local_ips<refDim>(geo.scv_local_ips(),
     121              :                                                               geo.num_scv_ips(), false);
     122            0 :                 m_imMass.template       set_local_ips<refDim>(geo.scv_local_ips(),
     123              :                                                               geo.num_scv_ips(), false);
     124              :         }
     125              : 
     126              : //      check, that upwind has been set
     127              : //      if(m_spConvShape.invalid())
     128              : //              UG_THROW("ConvectionDiffusion::prep_elem_loop:"
     129              : //                                              " Upwind has not been set.");
     130              : 
     131              : //      init upwind for element type
     132              : //      if(!m_spConvShape->template set_geometry_type<TFVGeom>())
     133              : //              UG_THROW("ConvectionDiffusion::prep_elem_loop:"
     134              : //                                              " Cannot init upwind for element type.");
     135            0 : }
     136              : 
     137              : template<typename TDomain>
     138              : template<typename TElem, typename TFVGeom>
     139            0 : void ConvectionDiffusionFVCR<TDomain>::
     140              : fsh_elem_loop()
     141            0 : {}
     142              : 
     143              : template<typename TDomain>
     144              : template<typename TElem, typename TFVGeom>
     145            0 : void ConvectionDiffusionFVCR<TDomain>::
     146              : prep_elem(const LocalVector& u, GridObject* elem, const ReferenceObjectID roid, const MathVector<dim> vCornerCoords[])
     147              : {
     148              : //      Update Geometry for this element
     149            0 :         static TFVGeom& geo = GeomProvider<TFVGeom>::get();
     150              : 
     151              :         try{
     152            0 :                 geo.update(elem, vCornerCoords, &(this->subset_handler()));
     153              :         }
     154            0 :         UG_CATCH_THROW("ConvectionDiffusion::prep_elem:"
     155              :                                         " Cannot update Finite Volume Geometry.");
     156              : 
     157              : //      set local positions
     158              :         if(TFVGeom::usesHangingNodes)
     159              :         {
     160              :                 static const int refDim = TElem::dim;
     161            0 :                 m_imDiffusion.template  set_local_ips<refDim>(geo.scvf_local_ips(),
     162              :                                                               geo.num_scvf_ips());
     163            0 :                 m_imVelocity.template   set_local_ips<refDim>(geo.scvf_local_ips(),
     164              :                                                               geo.num_scvf_ips());
     165            0 :                 m_imSource.template     set_local_ips<refDim>(geo.scv_local_ips(),
     166              :                                                               geo.num_scv_ips());
     167            0 :                 m_imReactionRate.template       set_local_ips<refDim>(geo.scv_local_ips(),
     168              :                                                               geo.num_scv_ips());
     169            0 :                 m_imReaction.template   set_local_ips<refDim>(geo.scv_local_ips(),
     170              :                                                               geo.num_scv_ips());
     171            0 :                 m_imMassScale.template  set_local_ips<refDim>(geo.scv_local_ips(),
     172              :                                                               geo.num_scv_ips());
     173            0 :                 m_imMass.template       set_local_ips<refDim>(geo.scv_local_ips(),
     174              :                                                               geo.num_scv_ips());
     175              : /*              if(m_spConvShape.valid())
     176              :                         if(!m_spConvShape->template set_geometry_type<TFVGeom>(geo))
     177              :                                 UG_THROW("ConvectionDiffusion::prep_elem_loop:"
     178              :                                                                 " Cannot init upwind for element type.");*/
     179              :         }
     180              : 
     181              :         //      set global positions
     182            0 :         const MathVector<dim>* vSCVFip = geo.scvf_global_ips();
     183              :         const size_t numSCVFip = geo.num_scvf_ips();
     184              :         const MathVector<dim>* vSCVip = geo.scv_global_ips();
     185              :         const size_t numSCVip = geo.num_scv_ips();
     186            0 :         m_imDiffusion.                  set_global_ips(vSCVFip, numSCVFip);
     187            0 :         m_imVelocity.                   set_global_ips(vSCVFip, numSCVFip);
     188              :         // m_imFlux.                            set_global_ips(vSCVFip, numSCVFip);
     189            0 :         m_imSource.                             set_global_ips(vSCVip, numSCVip);
     190              :         // m_imVectorSource.            set_global_ips(vSCVFip, numSCVFip);
     191            0 :         m_imReactionRate.               set_global_ips(vSCVip, numSCVip);
     192              :         // m_imReactionRateExpl.        set_global_ips(vSCVip, numSCVip);
     193              :         // m_imReactionExpl.            set_global_ips(vSCVip, numSCVip);
     194              :         // m_imSourceExpl.                      set_global_ips(vSCVip, numSCVip);
     195            0 :         m_imReaction.                   set_global_ips(vSCVip, numSCVip);
     196              :         // m_imMassScale.                       set_global_ips(vSCVip, numSCVip);
     197            0 :         m_imMass.                               set_global_ips(vSCVip, numSCVip);
     198            0 : }
     199              : 
     200              : template<typename TDomain>
     201              : template<typename TElem, typename TFVGeom>
     202            0 : void ConvectionDiffusionFVCR<TDomain>::
     203              : add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     204              : {
     205              : // get finite volume geometry
     206            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     207              : 
     208              : //      Diff. Tensor times Gradient
     209              :         MathVector<dim> Dgrad;
     210              : 
     211              : //      get conv shapes
     212              : //      const IConvectionShapes<dim>& convShape = get_updated_conv_shapes(geo);
     213              : 
     214              : //      Diffusion and Velocity Term
     215            0 :         if(m_imDiffusion.data_given() || m_imVelocity.data_given())
     216              :         {
     217              :         //      loop Sub Control Volume Faces (SCVF)
     218            0 :                 for(size_t ip = 0; ip < geo.num_scvf(); ++ip)
     219              :                 {
     220              :                 //      get current SCVF
     221            0 :                         const typename TFVGeom::SCVF& scvf = geo.scvf(ip);
     222              : 
     223              :                 ////////////////////////////////////////////////////
     224              :                 // Diffusive Term
     225              :                 ////////////////////////////////////////////////////
     226            0 :                         if(m_imDiffusion.data_given())
     227              :                         {
     228              :                         //      loop shape functions
     229            0 :                                 for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     230              :                                 {
     231              :                                 //      Compute Diffusion Tensor times Gradient
     232              :                                         MatVecMult(Dgrad, m_imDiffusion[ip], scvf.global_grad(sh));
     233              : 
     234              :                                 //      Compute flux at IP
     235              :                                         const number D_diff_flux = VecDot(Dgrad, scvf.normal());
     236              : 
     237              :                                 //      Add flux term to local matrix
     238            0 :                                         J(_C_, scvf.from(), _C_, sh) -= D_diff_flux;
     239            0 :                                         J(_C_, scvf.to()  , _C_, sh) += D_diff_flux;
     240              :                                 }
     241              :                         }
     242              : 
     243              :                 ////////////////////////////////////////////////////
     244              :                 // Convective Term
     245              :                 ////////////////////////////////////////////////////
     246              :         /*              if(m_imVelocity.data_given())
     247              :                         {
     248              :                         //      Add Flux contribution
     249              :                                 for(size_t sh = 0; sh < convShape.num_sh(); ++sh)
     250              :                                 {
     251              :                                         const number D_conv_flux = convShape(ip, sh);
     252              : 
     253              :                                 //      Add flux term to local matrix
     254              :                                         J(_C_, scvf.from(), _C_, sh) += D_conv_flux;
     255              :                                         J(_C_, scvf.to(),   _C_, sh) -= D_conv_flux;
     256              :                                 }
     257              :                         }*/
     258              :                 }
     259              :         }
     260              : 
     261              :         // handle constrained dofs
     262              :         if(TFVGeom::usesHangingNodes){
     263            0 :                 for (size_t i=0;i<geo.num_constrained_dofs();i++){
     264              :                         const typename TFVGeom::CONSTRAINED_DOF& cd = geo.constrained_dof(i);
     265              :                         const size_t index = cd.index();
     266            0 :                         J(_C_,index,_C_,index) = 1;
     267            0 :                         for (size_t j=0;j<cd.num_constraining_dofs();j++)
     268            0 :                                 J(_C_, index, _C_, cd.constraining_dofs_index(j)) = -cd.constraining_dofs_weight(j);
     269              :                         // insert interpolation equation directly for all dofs
     270            0 :                         for (size_t j=0;j<geo.num_scv();j++){
     271              :                                 const size_t nodeID = geo.scv(j).node_id();
     272            0 :                                 number alpha=J(_C_,nodeID,_C_,index);
     273            0 :                                 J(_C_,nodeID,_C_,index)=0;
     274            0 :                                 for (size_t k=0;k<cd.num_constraining_dofs();k++)
     275            0 :                                         J(_C_,nodeID,_C_,cd.constraining_dofs_index(k)) += alpha*cd.constraining_dofs_weight(k);
     276              :                         }
     277              :                 }
     278              :         }
     279              : 
     280              : /*      UG_LOG("Local Matrix is: \n");
     281              :         size_t n = geo.num_scv()+geo.num_constrained_dofs();
     282              :         UG_LOG("locA=[");
     283              :         for (size_t i=0;i<n;i++){
     284              :                 for (size_t j=0;j<n;j++)
     285              :                         UG_LOG(J(0,i,0,j) << " ");
     286              :                 UG_LOG(";\n");
     287              :         }
     288              :         UG_LOG("]\n");*/
     289              : ////////////////////////////////////////////////////
     290              : // Reaction Term (using lumping)
     291              : ////////////////////////////////////////////////////
     292              : 
     293              : //      if no data for reaction rate given, return
     294            0 :         if(!m_imReactionRate.data_given()) return;
     295              : 
     296              : //      loop Sub Control Volume (SCV)
     297            0 :         for(size_t ip = 0; ip < geo.num_scv(); ++ip)
     298              :         {
     299              :         //      get current SCV
     300            0 :                 const typename TFVGeom::SCV& scv = geo.scv(ip);
     301              : 
     302              :         //      get associated node
     303            0 :                 const int co = scv.node_id();
     304              : 
     305              :         //      Add to local matrix
     306            0 :                 J(_C_, co, _C_, co) += m_imReactionRate[ip] * scv.volume();
     307              :         }
     308              : 
     309              : //      reaction term does not explicitly depend on the associated unknown function
     310              : }
     311              : 
     312              : 
     313              : template<typename TDomain>
     314              : template<typename TElem, typename TFVGeom>
     315            0 : void ConvectionDiffusionFVCR<TDomain>::
     316              : add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     317              : {
     318              : //      get finite volume geometry
     319            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     320              : 
     321            0 :         if(!m_imMassScale.data_given()) return;
     322              : 
     323              : //      loop Sub Control Volumes (SCV)
     324            0 :         for(size_t ip = 0; ip < geo.num_scv(); ++ip)
     325              :         {
     326              :         //      get current SCV
     327            0 :                 const typename TFVGeom::SCV& scv = geo.scv(ip);
     328              : 
     329              :         //      get associated node
     330            0 :                 const int co = scv.node_id();
     331              : 
     332              :         //      Add to local matrix
     333            0 :                 J(_C_, co, _C_, co) += scv.volume() * m_imMassScale[ip];
     334              :         }
     335              : 
     336              : //      m_imMass part does not explicitly depend on associated unknown function
     337              : }
     338              : 
     339              : 
     340              : template<typename TDomain>
     341              : template<typename TElem, typename TFVGeom>
     342            0 : void ConvectionDiffusionFVCR<TDomain>::
     343              : add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     344              : {
     345              : //      get finite volume geometry
     346            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     347              : 
     348              : //      get conv shapes
     349              : //      const IConvectionShapes<dim>& convShape = get_updated_conv_shapes(geo);
     350              : 
     351            0 :         if(m_imDiffusion.data_given() || m_imVelocity.data_given())
     352              :         {
     353              :         //      loop Sub Control Volume Faces (SCVF)
     354            0 :                 for(size_t ip = 0; ip < geo.num_scvf(); ++ip)
     355              :                 {
     356              :                 //      get current SCVF
     357            0 :                         const typename TFVGeom::SCVF& scvf = geo.scvf(ip);
     358              : 
     359              :                 /////////////////////////////////////////////////////
     360              :                 // Diffusive Term
     361              :                 /////////////////////////////////////////////////////
     362            0 :                         if(m_imDiffusion.data_given())
     363              :                         {
     364              :                         //      to compute D \nabla c
     365              :                                 MathVector<dim> Dgrad_c, grad_c;
     366              : 
     367              :                         //      compute gradient and shape at ip
     368              :                                 VecSet(grad_c, 0.0);
     369            0 :                                 for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     370              :                                         VecScaleAppend(grad_c, u(_C_,sh), scvf.global_grad(sh));
     371              : 
     372              :                         //      scale by diffusion tensor
     373              :                                 MatVecMult(Dgrad_c, m_imDiffusion[ip], grad_c);
     374              : 
     375              :                         //      Compute flux
     376              :                                 const number diff_flux = VecDot(Dgrad_c, scvf.normal());
     377              : 
     378              :                         //      Add to local defect
     379            0 :                                 d(_C_, scvf.from()) -= diff_flux;
     380            0 :                                 d(_C_, scvf.to()  ) += diff_flux;
     381              :                         }
     382              : 
     383              :                 /////////////////////////////////////////////////////
     384              :                 // Convective Term
     385              :                 /////////////////////////////////////////////////////
     386              :         /*              if(m_imVelocity.data_given())
     387              :                         {
     388              :                         //      sum up convective flux using convection shapes
     389              :                                 number conv_flux = 0.0;
     390              :                                 for(size_t sh = 0; sh < convShape.num_sh(); ++sh)
     391              :                                         conv_flux += u(_C_, sh) * convShape(ip, sh);
     392              : 
     393              :                         //  add to local defect
     394              :                                 d(_C_, scvf.from()) += conv_flux;
     395              :                                 d(_C_, scvf.to()  ) -= conv_flux;
     396              :                         }*/
     397              :                 }
     398              :         }
     399              : 
     400              : //      reaction rate
     401            0 :         if(m_imReactionRate.data_given())
     402              :         {
     403              :         //      loop Sub Control Volumes (SCV)
     404            0 :                 for(size_t ip = 0; ip < geo.num_scv(); ++ip)
     405              :                 {
     406              :                 //      get current SCV
     407            0 :                         const typename TFVGeom::SCV& scv = geo.scv(ip);
     408              : 
     409              :                 //      get associated node
     410            0 :                         const int co = scv.node_id();
     411              : 
     412              :                 //      Add to local defect
     413            0 :                         d(_C_, co) += u(_C_, co) * m_imReactionRate[ip] * scv.volume();
     414              :                 }
     415              :         }
     416              : 
     417              : //      reaction rate
     418            0 :         if(m_imReaction.data_given())
     419              :         {
     420              :         //      loop Sub Control Volumes (SCV)
     421            0 :                 for(size_t ip = 0; ip < geo.num_scv(); ++ip)
     422              :                 {
     423              :                 //      get current SCV
     424            0 :                         const typename TFVGeom::SCV& scv = geo.scv(ip);
     425              : 
     426              :                 //      get associated node
     427            0 :                         const int co = scv.node_id();
     428              : 
     429              :                 //      Add to local defect
     430            0 :                         d(_C_, co) += m_imReaction[ip] * scv.volume();
     431              :                 }
     432              :         }
     433              : 
     434              :         // handle constrained dofs, compute defect of interpolation equation
     435              :         if(TFVGeom::usesHangingNodes){
     436            0 :                 for (size_t i=0;i<geo.num_constrained_dofs();i++){
     437              :                         const typename TFVGeom::CONSTRAINED_DOF& cd = geo.constrained_dof(i);
     438              :                         const size_t index = cd.index();
     439              :                         number defect = u(_C_,index);
     440            0 :                         for (size_t j=0;j<cd.num_constraining_dofs();j++)
     441            0 :                                 defect -= cd.constraining_dofs_weight(j) * u(_C_,cd.constraining_dofs_index(j));
     442            0 :                         d(_C_,index) = defect;
     443              :                 }
     444              :         }
     445            0 : }
     446              : 
     447              : 
     448              : template<typename TDomain>
     449              : template<typename TElem, typename TFVGeom>
     450            0 : void ConvectionDiffusionFVCR<TDomain>::
     451              : add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     452              : {
     453              : //      get finite volume geometry
     454            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     455              : 
     456            0 :         if(!m_imMassScale.data_given() && !m_imMass.data_given()) return;
     457              : 
     458              : //      loop Sub Control Volumes (SCV)
     459            0 :         for(size_t ip = 0; ip < geo.num_scv(); ++ip)
     460              :         {
     461              :         //      get current SCV
     462            0 :                 const typename TFVGeom::SCV& scv = geo.scv(ip);
     463              : 
     464              :         //      get associated node
     465            0 :                 const int co = scv.node_id();
     466              : 
     467              :         //      mass value
     468              :                 number val = 0.0;
     469              : 
     470              :         //      multiply by scaling
     471            0 :                 if(m_imMassScale.data_given())
     472            0 :                         val += m_imMassScale[ip] * u(_C_, co);
     473              : 
     474              :         //      add mass
     475            0 :                 if(m_imMass.data_given())
     476            0 :                         val += m_imMass[ip];
     477              : 
     478              :         //      Add to local defect
     479            0 :                 d(_C_, co) += val * scv.volume();
     480              :         }
     481              : }
     482              : 
     483              : 
     484              : template<typename TDomain>
     485              : template<typename TElem, typename TFVGeom>
     486            0 : void ConvectionDiffusionFVCR<TDomain>::
     487              : add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector<dim> vCornerCoords[])
     488              : {
     489              : //      if zero data given, return
     490            0 :         if(!m_imSource.data_given()) return;
     491              : 
     492              : //      get finite volume geometry
     493            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     494              : 
     495              : //      loop Sub Control Volumes (SCV)
     496            0 :         for(size_t ip = 0; ip < geo.num_scv(); ++ip)
     497              :         {
     498              :         //      get current SCV
     499            0 :                 const typename TFVGeom::SCV& scv = geo.scv(ip);
     500              : 
     501              :         //      get associated node
     502            0 :                 const int co = scv.node_id();
     503              : 
     504              :         //      Add to local rhs
     505            0 :                 d(_C_, co) += m_imSource[ip] * scv.volume();
     506              :         }
     507              : }
     508              : 
     509              : 
     510              : //      computes the linearized defect w.r.t to the velocity
     511              : template<typename TDomain>
     512              : template <typename TElem, typename TFVGeom>
     513            0 : void ConvectionDiffusionFVCR<TDomain>::
     514              : lin_def_velocity(const LocalVector& u,
     515              :                      std::vector<std::vector<MathVector<dim> > > vvvLinDef[],
     516              :                      const size_t nip)
     517              : {
     518              : //      get finite volume geometry
     519            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     520              : 
     521              : //      get conv shapes
     522              : //      const IConvectionShapes<dim>& convShape = get_updated_conv_shapes(geo);
     523              : 
     524              : //      reset the values for the linearized defect
     525            0 :         for(size_t ip = 0; ip < nip; ++ip)
     526            0 :                 for(size_t c = 0; c < vvvLinDef[ip].size(); ++c)
     527            0 :                         for(size_t sh = 0; sh < vvvLinDef[ip][c].size(); ++sh)
     528              :                                 vvvLinDef[ip][c][sh] = 0.0;
     529              : 
     530              : //  loop Sub Control Volume Faces (SCVF)
     531            0 :         for(size_t ip = 0; ip < geo.num_scvf(); ++ip)
     532              :         {
     533              :         // get current SCVF
     534            0 :                 const typename TFVGeom::SCVF& scvf = geo.scvf(ip);
     535              : 
     536              :         //      sum up contributions of convection shapes
     537              :                 MathVector<dim> linDefect;
     538              :                 VecSet(linDefect, 0.0);
     539            0 :                 for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     540              :         //              VecScaleAppend(linDefect, u(_C_,sh), convShape.D_vel(ip, sh));
     541              : 
     542              :         //      add parts for both sides of scvf
     543            0 :                 vvvLinDef[ip][_C_][scvf.from()] += linDefect;
     544            0 :                 vvvLinDef[ip][_C_][scvf.to()] -= linDefect;
     545              :         }
     546            0 : }
     547              : 
     548              : //      computes the linearized defect w.r.t to the velocity
     549              : template<typename TDomain>
     550              : template <typename TElem, typename TFVGeom>
     551            0 : void ConvectionDiffusionFVCR<TDomain>::
     552              : lin_def_diffusion(const LocalVector& u,
     553              :                       std::vector<std::vector<MathMatrix<dim,dim> > > vvvLinDef[],
     554              :                       const size_t nip)
     555              : {
     556              : //  get finite volume geometry
     557            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     558              : 
     559              : //      get conv shapes
     560              : //      const IConvectionShapes<dim>& convShape = get_updated_conv_shapes(geo);
     561              : 
     562              : //      reset the values for the linearized defect
     563            0 :         for(size_t ip = 0; ip < nip; ++ip)
     564            0 :                 for(size_t c = 0; c < vvvLinDef[ip].size(); ++c)
     565            0 :                         for(size_t sh = 0; sh < vvvLinDef[ip][c].size(); ++sh)
     566              :                                 vvvLinDef[ip][c][sh] = 0.0;
     567              : 
     568              : //  loop Sub Control Volume Faces (SCVF)
     569            0 :         for(size_t ip = 0; ip < geo.num_scvf(); ++ip)
     570              :         {
     571              :         // get current SCVF
     572            0 :                 const typename TFVGeom::SCVF& scvf = geo.scvf(ip);
     573              : 
     574              :         //      compute gradient at ip
     575              :                 MathVector<dim> grad_u;   VecSet(grad_u, 0.0);
     576            0 :                 for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     577              :                         VecScaleAppend(grad_u, u(_C_,sh), scvf.global_grad(sh));
     578              : 
     579              :         //      compute the lin defect at this ip
     580              :                 MathMatrix<dim,dim> linDefect;
     581              : 
     582              :         //      part coming from -\nabla u * \vec{n}
     583            0 :                 for(size_t k=0; k < (size_t)dim; ++k)
     584            0 :                         for(size_t j = 0; j < (size_t)dim; ++j)
     585            0 :                                 linDefect(j,k) = (scvf.normal())[j] * grad_u[k];
     586              : 
     587              :         //      add contribution from convection shapes
     588              :         //      if(convShape.non_zero_deriv_diffusion())
     589              :                 //      for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     590              :                         //      MatAdd(linDefect, convShape.D_diffusion(ip, sh), u(_C_, sh));
     591              : 
     592              :         //      add contributions
     593            0 :                 vvvLinDef[ip][_C_][scvf.from()] -= linDefect;
     594              :                 vvvLinDef[ip][_C_][scvf.to()  ] += linDefect;
     595              :         }
     596            0 : }
     597              : 
     598              : //      computes the linearized defect w.r.t to the reaction rate
     599              : template<typename TDomain>
     600              : template <typename TElem, typename TFVGeom>
     601            0 : void ConvectionDiffusionFVCR<TDomain>::
     602              : lin_def_reaction_rate(const LocalVector& u,
     603              :                           std::vector<std::vector<number> > vvvLinDef[],
     604              :                           const size_t nip)
     605              : {
     606              : //  get finite volume geometry
     607            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     608              : 
     609              : //      loop Sub Control Volumes (SCV)
     610            0 :         for(size_t ip = 0; ip < geo.num_scv(); ++ip)
     611              :         {
     612              :         //      get current SCV
     613            0 :                 const typename TFVGeom::SCV& scv = geo.scv(ip);
     614              : 
     615              :         //      get associated node
     616            0 :                 const int co = scv.node_id();
     617              : 
     618              :         //      set lin defect
     619            0 :                 vvvLinDef[ip][_C_][co] = u(_C_, co) * scv.volume();
     620              :         }
     621            0 : }
     622              : 
     623              : //      computes the linearized defect w.r.t to the reaction
     624              : template<typename TDomain>
     625              : template <typename TElem, typename TFVGeom>
     626            0 : void ConvectionDiffusionFVCR<TDomain>::
     627              : lin_def_reaction(const LocalVector& u,
     628              :                      std::vector<std::vector<number> > vvvLinDef[],
     629              :                      const size_t nip)
     630              : {
     631              : //  get finite volume geometry
     632            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     633              : 
     634              : //      loop Sub Control Volumes (SCV)
     635            0 :         for(size_t ip = 0; ip < geo.num_scv(); ++ip)
     636              :         {
     637              :         //      get current SCV
     638            0 :                 const typename TFVGeom::SCV& scv = geo.scv(ip);
     639              : 
     640              :         //      get associated node
     641            0 :                 const int co = scv.node_id();
     642              : 
     643              :         //      set lin defect
     644            0 :                 vvvLinDef[ip][_C_][co] = scv.volume();
     645              :         }
     646            0 : }
     647              : 
     648              : //      computes the linearized defect w.r.t to the source
     649              : template<typename TDomain>
     650              : template <typename TElem, typename TFVGeom>
     651            0 : void ConvectionDiffusionFVCR<TDomain>::
     652              : lin_def_source(const LocalVector& u,
     653              :                    std::vector<std::vector<number> > vvvLinDef[],
     654              :                    const size_t nip)
     655              : {
     656              : //  get finite volume geometry
     657            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     658              : 
     659              : //      loop Sub Control Volumes (SCV)
     660            0 :         for(size_t ip = 0; ip < geo.num_scv(); ++ip)
     661              :         {
     662              :         //      get current SCV
     663            0 :                 const typename TFVGeom::SCV& scv = geo.scv(ip);
     664              : 
     665              :         //      get associated node
     666            0 :                 const int co = scv.node_id();
     667              : 
     668              :         //      set lin defect
     669            0 :                 vvvLinDef[ip][_C_][co] = scv.volume();
     670              :         }
     671            0 : }
     672              : 
     673              : //      computes the linearized defect w.r.t to the mass scale
     674              : template<typename TDomain>
     675              : template <typename TElem, typename TFVGeom>
     676            0 : void ConvectionDiffusionFVCR<TDomain>::
     677              : lin_def_mass_scale(const LocalVector& u,
     678              :                        std::vector<std::vector<number> > vvvLinDef[],
     679              :                        const size_t nip)
     680              : {
     681              : //  get finite volume geometry
     682            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     683              : 
     684              : //      loop Sub Control Volumes (SCV)
     685            0 :         for(size_t co = 0; co < geo.num_scv(); ++co)
     686              :         {
     687              :         //      get current SCV
     688            0 :                 const typename TFVGeom::SCV& scv = geo.scv(co);
     689              : 
     690              :         //      Check associated node
     691              :                 UG_ASSERT(co == scv.node_id(), "Only one shape per SCV");
     692              : 
     693              :         //      set lin defect
     694            0 :                 vvvLinDef[co][_C_][co] = u(_C_, co) * scv.volume();
     695              :         }
     696            0 : }
     697              : 
     698              : //      computes the linearized defect w.r.t to the mass scale
     699              : template<typename TDomain>
     700              : template <typename TElem, typename TFVGeom>
     701            0 : void ConvectionDiffusionFVCR<TDomain>::
     702              : lin_def_mass(const LocalVector& u,
     703              :                        std::vector<std::vector<number> > vvvLinDef[],
     704              :                        const size_t nip)
     705              : {
     706              : //  get finite volume geometry
     707            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     708              : 
     709              : //      loop Sub Control Volumes (SCV)
     710            0 :         for(size_t co = 0; co < geo.num_scv(); ++co)
     711              :         {
     712              :         //      get current SCV
     713            0 :                 const typename TFVGeom::SCV& scv = geo.scv(co);
     714              : 
     715              :         //      Check associated node
     716              :                 UG_ASSERT(co == scv.node_id(), "Only one shape per SCV");
     717              : 
     718              :         //      set lin defect
     719            0 :                 vvvLinDef[co][_C_][co] = scv.volume();
     720              :         }
     721            0 : }
     722              : 
     723              : //      computes the linearized defect w.r.t to the velocity
     724              : template<typename TDomain>
     725              : template <typename TElem, typename TFVGeom>
     726            0 : void ConvectionDiffusionFVCR<TDomain>::
     727              : ex_value(number vValue[],
     728              :          const MathVector<dim> vGlobIP[],
     729              :          number time, int si,
     730              :          const LocalVector& u,
     731              :          GridObject* elem,
     732              :          const MathVector<dim> vCornerCoords[],
     733              :          const MathVector<TFVGeom::dim> vLocIP[],
     734              :          const size_t nip,
     735              :          bool bDeriv,
     736              :          std::vector<std::vector<number> > vvvDeriv[])
     737              : {
     738              : //  get finite volume geometry
     739            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     740              : 
     741              : //      reference element
     742              :         typedef typename reference_element_traits<TElem>::reference_element_type
     743              :                         ref_elem_type;
     744              : 
     745              : //      number of shape functions
     746              :         static const size_t numSH =     ref_elem_type::numCorners;
     747              : 
     748              : //      CRFV SCVF ip
     749            0 :         if(vLocIP == geo.scvf_local_ips())
     750              :         {
     751              :         //      Loop Sub Control Volume Faces (SCVF)
     752            0 :                 for(size_t ip = 0; ip < geo.num_scvf(); ++ip)
     753              :                 {
     754              :                 //      Get current SCVF
     755              :                         const typename TFVGeom::SCVF& scvf = geo.scvf(ip);
     756              : 
     757              :                 //      compute concentration at ip
     758            0 :                         vValue[ip] = 0.0;
     759            0 :                         for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     760            0 :                                 vValue[ip] += u(_C_, sh) * scvf.shape(sh);
     761              : 
     762              :                 //      compute derivative w.r.t. to unknowns iff needed
     763            0 :                         if(bDeriv)
     764            0 :                                 for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     765            0 :                                         vvvDeriv[ip][_C_][sh] = scvf.shape(sh);
     766              :                 }
     767              :         }
     768              : //      CRFV SCV ip
     769            0 :         else if(vLocIP == geo.scv_local_ips())
     770              :         {
     771              :         //      solution at ip
     772            0 :                 for(size_t sh = 0; sh < numSH; ++sh)
     773            0 :                         vValue[sh] = u(_C_, sh);
     774              : 
     775              :         //      set derivatives if needed
     776            0 :                 if(bDeriv)
     777            0 :                         for(size_t sh = 0; sh < numSH; ++sh)
     778            0 :                                 for(size_t sh2 = 0; sh2 < numSH; ++sh2)
     779            0 :                                         vvvDeriv[sh][_C_][sh2] = (sh==sh2) ? 1.0 : 0.0;
     780              :         }
     781              : //      general case
     782              :         else
     783              :         {
     784              :         //      get trial space
     785            0 :                 LagrangeP1<ref_elem_type> rTrialSpace = Provider<LagrangeP1<ref_elem_type> >::get();
     786              : 
     787              :         //      storage for shape function at ip
     788              :                 number vShape[numSH];
     789              : 
     790              :         //      loop ips
     791            0 :                 for(size_t ip = 0; ip < nip; ++ip)
     792              :                 {
     793              :                 //      evaluate at shapes at ip
     794            0 :                         rTrialSpace.shapes(vShape, vLocIP[ip]);
     795              : 
     796              :                 //      compute concentration at ip
     797            0 :                         vValue[ip] = 0.0;
     798            0 :                         for(size_t sh = 0; sh < numSH; ++sh)
     799            0 :                                 vValue[ip] += u(_C_, sh) * vShape[sh];
     800              : 
     801              :                 //      compute derivative w.r.t. to unknowns iff needed
     802              :                 //      \todo: maybe store shapes directly in vvvDeriv
     803            0 :                         if(bDeriv)
     804            0 :                                 for(size_t sh = 0; sh < numSH; ++sh)
     805            0 :                                         vvvDeriv[ip][_C_][sh] = vShape[sh];
     806              :                 }
     807              :         }
     808            0 : }
     809              : 
     810              : //      computes the linearized defect w.r.t to the velocity
     811              : template<typename TDomain>
     812              : template <typename TElem, typename TFVGeom>
     813            0 : void ConvectionDiffusionFVCR<TDomain>::
     814              : ex_grad(MathVector<dim> vValue[],
     815              :         const MathVector<dim> vGlobIP[],
     816              :         number time, int si,
     817              :         const LocalVector& u,
     818              :         GridObject* elem,
     819              :         const MathVector<dim> vCornerCoords[],
     820              :         const MathVector<TFVGeom::dim> vLocIP[],
     821              :         const size_t nip,
     822              :         bool bDeriv,
     823              :         std::vector<std::vector<MathVector<dim> > > vvvDeriv[])
     824              : {
     825              : //      Get finite volume geometry
     826            0 :         static const TFVGeom& geo = GeomProvider<TFVGeom>::get();
     827              : 
     828              : //      reference element
     829              :         typedef typename reference_element_traits<TElem>::reference_element_type
     830              :                         ref_elem_type;
     831              : 
     832              : //      reference dimension
     833              :         static const int refDim = ref_elem_type::dim;
     834              : 
     835              : //      number of shape functions
     836              :         static const size_t numSH =     ref_elem_type::numCorners;
     837              : 
     838              : //      CRFV SCVF ip
     839            0 :         if(vLocIP == geo.scvf_local_ips())
     840              :         {
     841              :         //      Loop Sub Control Volume Faces (SCVF)
     842            0 :                 for(size_t ip = 0; ip < geo.num_scvf(); ++ip)
     843              :                 {
     844              :                 //      Get current SCVF
     845              :                         const typename TFVGeom::SCVF& scvf = geo.scvf(ip);
     846              : 
     847            0 :                         VecSet(vValue[ip], 0.0);
     848            0 :                         for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     849              :                                 VecScaleAppend(vValue[ip], u(_C_, sh), scvf.global_grad(sh));
     850              : 
     851            0 :                         if(bDeriv)
     852            0 :                                 for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     853            0 :                                         vvvDeriv[ip][_C_][sh] = scvf.global_grad(sh);
     854              :                 }
     855              :         }
     856              : //      general case
     857              :         else
     858              :         {
     859              :         //      get trial space
     860            0 :                 LagrangeP1<ref_elem_type>& rTrialSpace = Provider<LagrangeP1<ref_elem_type> >::get();
     861              : 
     862              :         //      storage for shape function at ip
     863            0 :                 MathVector<refDim> vLocGrad[numSH];
     864              :                 MathVector<refDim> locGrad;
     865              : 
     866              :         //      Reference Mapping
     867              :                 MathMatrix<dim, refDim> JTInv;
     868            0 :                 ReferenceMapping<ref_elem_type, dim> mapping(vCornerCoords);
     869              : 
     870              :         //      loop ips
     871            0 :                 for(size_t ip = 0; ip < nip; ++ip)
     872              :                 {
     873              :                 //      evaluate at shapes at ip
     874            0 :                         rTrialSpace.grads(vLocGrad, vLocIP[ip]);
     875              : 
     876              :                 //      compute grad at ip
     877              :                         VecSet(locGrad, 0.0);
     878            0 :                         for(size_t sh = 0; sh < numSH; ++sh)
     879              :                                 VecScaleAppend(locGrad, u(_C_, sh), vLocGrad[sh]);
     880              : 
     881              :                 //      compute global grad
     882            0 :                         mapping.jacobian_transposed_inverse(JTInv, vLocIP[ip]);
     883            0 :                         MatVecMult(vValue[ip], JTInv, locGrad);
     884              : 
     885              :                 //      compute derivative w.r.t. to unknowns iff needed
     886            0 :                         if(bDeriv)
     887            0 :                                 for(size_t sh = 0; sh < numSH; ++sh)
     888            0 :                                         MatVecMult(vvvDeriv[ip][_C_][sh], JTInv, vLocGrad[sh]);
     889              :                 }
     890              :         }
     891            0 : };
     892              : 
     893              : ////////////////////////////////////////////////////////////////////////////////
     894              : //      upwind
     895              : ////////////////////////////////////////////////////////////////////////////////
     896              : 
     897              : template<typename TDomain>
     898            0 : void ConvectionDiffusionFVCR<TDomain>::
     899            0 : set_upwind(SmartPtr<IConvectionShapes<dim> > shapes) {m_spConvShape = shapes;}
     900              : 
     901              : //      computes the linearized defect w.r.t to the velocity
     902              : template<typename TDomain>
     903              : const typename ConvectionDiffusionFVCR<TDomain>::conv_shape_type&
     904            0 : ConvectionDiffusionFVCR<TDomain>::
     905              : get_updated_conv_shapes(const FVGeometryBase& geo)
     906              : {
     907              : //      compute upwind shapes for transport equation
     908              : //      \todo: we should move this computation into the preparation part of the
     909              : //                      disc, to only compute the shapes once, reusing them several times.
     910            0 :         if(m_imVelocity.data_given())
     911              :         {
     912              :         //      get diffusion at ips
     913              :                 const MathMatrix<dim, dim>* vDiffusion = NULL;
     914            0 :                 if(m_imDiffusion.data_given()) vDiffusion = m_imDiffusion.values();
     915              : 
     916              :         //      update convection shapes
     917            0 :                 if(!m_spConvShape->update(&geo, m_imVelocity.values(), vDiffusion, true))
     918              :                 {
     919              :                         UG_LOG("ERROR in 'ConvectionDiffusionFV1::add_jac_A_elem': "
     920              :                                         "Cannot compute convection shapes.\n");
     921              :                 }
     922              :         }
     923              : 
     924              : //      return a const (!!) reference to the upwind
     925            0 :         return *const_cast<const IConvectionShapes<dim>*>(m_spConvShape.get());
     926              : }
     927              : 
     928              : 
     929              : ////////////////////////////////////////////////////////////////////////////////
     930              : //      register assemble functions
     931              : ////////////////////////////////////////////////////////////////////////////////
     932              : 
     933              : #ifdef UG_DIM_1
     934              : template<>
     935            0 : void ConvectionDiffusionFVCR<Domain1d>::
     936              : register_all_funcs(bool bHang)
     937              : {
     938            0 :         UG_THROW("Crouxeiz-Raviart only senseful in dimension >= 2");
     939              : }
     940              : #endif
     941              : 
     942              : #ifdef UG_DIM_2
     943              : template<>
     944            0 : void ConvectionDiffusionFVCR<Domain2d>::
     945              : register_all_funcs(bool bHang)
     946              : {
     947              : //      switch assemble functions
     948            0 :         if(!bHang)
     949              :         {
     950            0 :                 register_func<Triangle, CRFVGeometry<Triangle, dim> >();
     951            0 :                 register_func<Quadrilateral, CRFVGeometry<Quadrilateral, dim> >();
     952              :         }
     953              :         else
     954              :         {
     955            0 :                 register_func<Triangle, HCRFVGeometry<Triangle, dim> >();
     956            0 :                 register_func<Quadrilateral, HCRFVGeometry<Quadrilateral, dim> >();
     957              :         }
     958            0 : }
     959              : #endif
     960              : 
     961              : #ifdef UG_DIM_3
     962              : template<>
     963            0 : void ConvectionDiffusionFVCR<Domain3d>::
     964              : register_all_funcs(bool bHang)
     965              : {
     966              : //      switch assemble functions
     967            0 :         if(!bHang)
     968              :         {
     969            0 :                 register_func<Tetrahedron, CRFVGeometry<Tetrahedron, dim> >();
     970            0 :                 register_func<Prism, CRFVGeometry<Prism, dim> >();
     971            0 :                 register_func<Pyramid, CRFVGeometry<Pyramid, dim> >();
     972            0 :                 register_func<Hexahedron, CRFVGeometry<Hexahedron, dim> >();
     973              :         }
     974              :         else
     975              :         {
     976            0 :                 register_func<Tetrahedron, HCRFVGeometry<Tetrahedron, dim> >();
     977            0 :                 register_func<Prism, HCRFVGeometry<Prism, dim> >();
     978            0 :                 register_func<Pyramid, HCRFVGeometry<Pyramid, dim> >();
     979            0 :                 register_func<Hexahedron, HCRFVGeometry<Hexahedron, dim> >();
     980              :         }
     981            0 : }
     982              : #endif
     983              : 
     984              : template<typename TDomain>
     985              : template<typename TElem, typename TFVGeom>
     986            0 : void ConvectionDiffusionFVCR<TDomain>::
     987              : register_func()
     988              : {
     989              :         ReferenceObjectID id = geometry_traits<TElem>::REFERENCE_OBJECT_ID;
     990              :         typedef this_type T;
     991              :         static const int refDim = reference_element_traits<TElem>::dim;
     992              : 
     993              :         this->clear_add_fct(id);
     994              :         this->set_prep_elem_loop_fct(id, &T::template prep_elem_loop<TElem, TFVGeom>);
     995              :         this->set_prep_elem_fct(      id, &T::template prep_elem<TElem, TFVGeom>);
     996              :         this->set_fsh_elem_loop_fct( id, &T::template fsh_elem_loop<TElem, TFVGeom>);
     997              :         this->set_add_jac_A_elem_fct(id, &T::template add_jac_A_elem<TElem, TFVGeom>);
     998              :         this->set_add_jac_M_elem_fct(id, &T::template add_jac_M_elem<TElem, TFVGeom>);
     999              :         this->set_add_def_A_elem_fct(id, &T::template add_def_A_elem<TElem, TFVGeom>);
    1000              :         this->set_add_def_M_elem_fct(id, &T::template add_def_M_elem<TElem, TFVGeom>);
    1001              :         this->set_add_rhs_elem_fct(  id, &T::template add_rhs_elem<TElem, TFVGeom>);
    1002              : 
    1003              : //      set computation of linearized defect w.r.t velocity
    1004            0 :         m_imVelocity. set_fct(id, this, &T::template lin_def_velocity<TElem, TFVGeom>);
    1005            0 :         m_imDiffusion.set_fct(id, this, &T::template lin_def_diffusion<TElem, TFVGeom>);
    1006            0 :         m_imReactionRate. set_fct(id, this, &T::template lin_def_reaction_rate<TElem, TFVGeom>);
    1007            0 :         m_imReaction. set_fct(id, this, &T::template lin_def_reaction<TElem, TFVGeom>);
    1008            0 :         m_imSource.       set_fct(id, this, &T::template lin_def_source<TElem, TFVGeom>);
    1009            0 :         m_imMassScale.set_fct(id, this, &T::template lin_def_mass_scale<TElem, TFVGeom>);
    1010            0 :         m_imMass.       set_fct(id, this, &T::template lin_def_mass<TElem, TFVGeom>);
    1011              : 
    1012              : //      exports
    1013            0 :         m_exValue->     template set_fct<T,refDim>(id, this, &T::template ex_value<TElem, TFVGeom>);
    1014            0 :         m_exGrad->template set_fct<T,refDim>(id, this, &T::template ex_grad<TElem, TFVGeom>);
    1015            0 : }
    1016              : 
    1017              : ////////////////////////////////////////////////////////////////////////////////
    1018              : //      explicit template instantiations
    1019              : ////////////////////////////////////////////////////////////////////////////////
    1020              : 
    1021              : #ifdef UG_DIM_1
    1022              : template class ConvectionDiffusionFVCR<Domain1d>;
    1023              : #endif
    1024              : #ifdef UG_DIM_2
    1025              : template class ConvectionDiffusionFVCR<Domain2d>;
    1026              : #endif
    1027              : #ifdef UG_DIM_3
    1028              : template class ConvectionDiffusionFVCR<Domain3d>;
    1029              : #endif
    1030              : 
    1031              : } // end namespace ConvectionDiffusionPlugin
    1032              : } // namespace ug
    1033              : 
        

Generated by: LCOV version 2.0-1