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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Andreas Vogel
       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_fe.h"
      34              : 
      35              : #include "lib_disc/spatial_disc/disc_util/fe_geom.h"
      36              : #include "lib_disc/spatial_disc/disc_util/geom_provider.h"
      37              : #include "lib_disc/local_finite_element/lagrange/lagrange.h"
      38              : #include "lib_disc/local_finite_element/lagrange/lagrangep1.h"
      39              : #include "lib_disc/quadrature/gauss/gauss_quad.h"
      40              : 
      41              : namespace ug{
      42              : namespace ConvectionDiffusionPlugin{
      43              : 
      44              : ////////////////////////////////////////////////////////////////////////////////
      45              : //      general
      46              : ////////////////////////////////////////////////////////////////////////////////
      47              : 
      48              : template<typename TDomain>
      49            0 : ConvectionDiffusionFE<TDomain>::
      50              : ConvectionDiffusionFE(const char* functions, const char* subsets)
      51              :  : ConvectionDiffusionBase<TDomain>(functions,subsets),
      52            0 :         m_bQuadOrderUserDef(false)
      53              : {
      54              :         this->clear_add_fct();
      55            0 : }
      56              : 
      57              : template<typename TDomain>
      58            0 : void ConvectionDiffusionFE<TDomain>::set_quad_order(size_t order)
      59              : {
      60            0 :         m_quadOrder = order;
      61            0 :         m_bQuadOrderUserDef = true;
      62            0 : }
      63              : 
      64              : template<typename TDomain>
      65            0 : void ConvectionDiffusionFE<TDomain>::
      66              : prepare_setting(const std::vector<LFEID>& vLfeID, bool bNonRegularGrid)
      67              : {
      68              :         //      check number of fcts
      69            0 :         UG_COND_THROW(vLfeID.size() != 1, "ConvectionDiffusion:" <<
      70              :                                 "Wrong number of functions given. Need exactly "<<1);
      71              : 
      72              :         //      check that not ADAPTIVE
      73            0 :         UG_COND_THROW(vLfeID[0].order() < 0, "ConvectionDiffusion: "<<
      74              :                                 "Adaptive order not implemented.");
      75              : 
      76              :         //      set order
      77            0 :         m_lfeID = vLfeID[0];
      78            0 :         if(!m_bQuadOrderUserDef) m_quadOrder = 2*m_lfeID.order()+1;
      79              : 
      80            0 :         register_all_funcs(m_lfeID, m_quadOrder);
      81            0 : }
      82              : 
      83              : template<typename TDomain>
      84            0 : bool ConvectionDiffusionFE<TDomain>::
      85              : use_hanging() const
      86            0 : { return false; }
      87              : 
      88              : ////////////////////////////////////////////////////////////////////////////////
      89              : // Assembling functions
      90              : ////////////////////////////////////////////////////////////////////////////////
      91              : 
      92              : template<typename TDomain>
      93              : template<typename TElem, typename TFEGeom>
      94            0 : void ConvectionDiffusionFE<TDomain>::
      95              : prep_elem_loop(const ReferenceObjectID roid, const int si)
      96              : {
      97              :         // Check for explicit terms.
      98            0 :         UG_COND_THROW(m_imSourceExpl.data_given() || m_imReactionExpl.data_given() || m_imReactionRateExpl.data_given(),
      99              :                         "ConvectionDiffusionFE: Explicit terms not implemented.");
     100              : 
     101              :         // Request geometry.
     102            0 :         TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     103              : 
     104              :         //      Prepare geometry for type and order.
     105              :         try{
     106            0 :                 geo.update_local(roid, m_lfeID, m_quadOrder);
     107            0 :         } UG_CATCH_THROW("ConvectionDiffusion::prep_elem_loop:" <<
     108              :                                         " Cannot update Finite Element Geometry.");
     109              : 
     110              :         //      Set local positions.
     111              :         static const int refDim = TElem::dim;
     112            0 :         m_imDiffusion.template set_local_ips<refDim>(geo.local_ips(), geo.num_ip(), false);
     113            0 :         m_imVelocity.template  set_local_ips<refDim>(geo.local_ips(), geo.num_ip(), false);
     114            0 :         m_imFlux.template               set_local_ips<refDim>(geo.local_ips(), geo.num_ip(), false);
     115            0 :         m_imSource.template    set_local_ips<refDim>(geo.local_ips(), geo.num_ip(), false);
     116            0 :         m_imVectorSource.template set_local_ips<refDim>(geo.local_ips(), geo.num_ip(), false);
     117            0 :         m_imReactionRate.template  set_local_ips<refDim>(geo.local_ips(), geo.num_ip(), false);
     118            0 :         m_imReaction.template  set_local_ips<refDim>(geo.local_ips(), geo.num_ip(), false);
     119            0 :         m_imMassScale.template set_local_ips<refDim>(geo.local_ips(), geo.num_ip(), false);
     120            0 :         m_imMass.template          set_local_ips<refDim>(geo.local_ips(), geo.num_ip(), false);
     121            0 : }
     122              : 
     123              : template<typename TDomain>
     124              : template<typename TElem, typename TFEGeom>
     125            0 : void ConvectionDiffusionFE<TDomain>::
     126              : fsh_elem_loop()
     127            0 : {}
     128              : 
     129              : template<typename TDomain>
     130              : template<typename TElem, typename TFEGeom>
     131            0 : void ConvectionDiffusionFE<TDomain>::
     132              : prep_elem(const LocalVector& u, GridObject* elem, const ReferenceObjectID roid, const MathVector<dim> vCornerCoords[])
     133              : {
     134              : //      request geometry
     135            0 :         TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     136              : 
     137              :         try{
     138              :                 geo.update(elem, vCornerCoords);
     139              :         }
     140            0 :         UG_CATCH_THROW("ConvectionDiffusion::prep_elem:"
     141              :                                         " Cannot update Finite Element Geometry.");
     142              : 
     143              : //      set global positions for rhs
     144            0 :         m_imDiffusion.  set_global_ips(geo.global_ips(), geo.num_ip());
     145            0 :         m_imVelocity.   set_global_ips(geo.global_ips(), geo.num_ip());
     146            0 :         m_imFlux.               set_global_ips(geo.global_ips(), geo.num_ip());
     147            0 :         m_imSource.     set_global_ips(geo.global_ips(), geo.num_ip());
     148            0 :         m_imVectorSource.set_global_ips(geo.global_ips(), geo.num_ip());
     149            0 :         m_imReactionRate.set_global_ips(geo.global_ips(), geo.num_ip());
     150            0 :         m_imReaction.   set_global_ips(geo.global_ips(), geo.num_ip());
     151            0 :         m_imMassScale.  set_global_ips(geo.global_ips(), geo.num_ip());
     152            0 :         m_imMass.               set_global_ips(geo.global_ips(), geo.num_ip());
     153            0 : }
     154              : 
     155              : template<typename TDomain>
     156              : template<typename TElem, typename TFEGeom>
     157            0 : void ConvectionDiffusionFE<TDomain>::
     158              : add_jac_A_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     159              : {
     160              : //      request geometry
     161            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     162              : 
     163              :         MathVector<dim> v, Dgrad;
     164              : 
     165              : //      loop integration points
     166            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     167              :         {
     168              :         //      loop trial space
     169            0 :                 for(size_t j = 0; j < geo.num_sh(); ++j)
     170              :                 {
     171              :                 //      Diffusion
     172            0 :                         if(m_imDiffusion.data_given())
     173              :                                 MatVecMult(Dgrad, m_imDiffusion[ip], geo.global_grad(ip, j));
     174              :                         else
     175              :                                 VecSet(Dgrad, 0.0);
     176              : 
     177              :                 //  Convection
     178            0 :                         if(m_imVelocity.data_given())
     179            0 :                                 VecScaleAppend(Dgrad, -1*geo.shape(ip,j), m_imVelocity[ip]);
     180              : 
     181              :                 //      no explicit dependency on m_imFlux
     182              : 
     183              :                 //      loop test space
     184            0 :                         for(size_t i = 0; i < geo.num_sh(); ++i)
     185              :                         {
     186              :                         //      compute integrand
     187              :                                 number integrand = VecDot(Dgrad, geo.global_grad(ip, i));
     188              : 
     189              :                         //      Reaction
     190            0 :                                 if(m_imReactionRate.data_given())
     191            0 :                                         integrand += m_imReactionRate[ip] * geo.shape(ip, j) * geo.shape(ip, i);
     192              : 
     193              :                         //      no explicit dependency on m_imReaction
     194              : 
     195              :                         //      multiply by weight
     196            0 :                                 integrand *= geo.weight(ip);
     197              : 
     198              :                         //      add to local matrix
     199            0 :                                 J(_C_, i, _C_, j) += integrand;
     200              :                         }
     201              :                 }
     202              :         }
     203            0 : }
     204              : 
     205              : 
     206              : template<typename TDomain>
     207              : template<typename TElem, typename TFEGeom>
     208            0 : void ConvectionDiffusionFE<TDomain>::
     209              : add_jac_M_elem(LocalMatrix& J, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     210              : {
     211              : //      request geometry
     212            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     213              : 
     214            0 :         if(!m_imMassScale.data_given()) return;
     215              : 
     216              : //      loop integration points
     217            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     218              :         {
     219              :         //      loop test space
     220            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     221              :                 {
     222              :                 //      loop trial space
     223            0 :                         for(size_t j= 0; j < geo.num_sh(); ++j)
     224              :                         {
     225              :                         //      add to local matrix
     226            0 :                                 J(_C_, i, _C_, j) += geo.shape(ip, i) *geo.shape(ip, j)
     227            0 :                                                                          * geo.weight(ip) * m_imMassScale[ip];
     228              : 
     229              :                         //      no explicit dependency on m_imMass
     230              :                         }
     231              :                 }
     232              :         }
     233              : }
     234              : 
     235              : 
     236              : template<typename TDomain>
     237              : template<typename TElem, typename TFEGeom>
     238            0 : void ConvectionDiffusionFE<TDomain>::
     239              : add_def_A_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     240              : {
     241              : //      request geometry
     242            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     243              : 
     244              :         number integrand, shape_u;
     245              :         MathMatrix<dim,dim> D;
     246              :         MathVector<dim> v, Dgrad_u, grad_u;
     247              : 
     248              : //      loop integration points
     249            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     250              :         {
     251              :         //      get current u and grad_u
     252              :                 VecSet(grad_u, 0.0);
     253              :                 shape_u = 0.0;
     254            0 :                 for(size_t j = 0; j < geo.num_sh(); ++j)
     255              :                 {
     256              :                         VecScaleAppend(grad_u, u(_C_,j), geo.global_grad(ip, j));
     257            0 :                         shape_u += u(_C_,j) * geo.shape(ip, j);
     258              :                 }
     259              : 
     260              :         //      Diffusion
     261            0 :                 if(m_imDiffusion.data_given())
     262              :                         MatVecMult(Dgrad_u, m_imDiffusion[ip], grad_u);
     263              :                 else
     264              :                         VecSet(Dgrad_u, 0.0);
     265              : 
     266              :         //      Convection
     267            0 :                 if(m_imVelocity.data_given())
     268            0 :                         VecScaleAppend(Dgrad_u, -1*shape_u, m_imVelocity[ip]);
     269              : 
     270              :         //      Convection
     271            0 :                 if(m_imFlux.data_given())
     272              :                         VecScaleAppend(Dgrad_u, 1.0, m_imFlux[ip]);
     273              : 
     274              :         //      loop test spaces
     275            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     276              :                 {
     277              :                 //      compute integrand
     278              :                         integrand = VecDot(Dgrad_u, geo.global_grad(ip, i));
     279              : 
     280              :                 //      add Reaction Rate
     281            0 :                         if(m_imReactionRate.data_given())
     282            0 :                                 integrand += m_imReactionRate[ip] * shape_u * geo.shape(ip, i);
     283              : 
     284              :                 //      add Reaction
     285            0 :                         if(m_imReaction.data_given())
     286            0 :                                 integrand += m_imReaction[ip] * geo.shape(ip, i);
     287              : 
     288              :                 //      multiply by integration weight
     289            0 :                         integrand *= geo.weight(ip);
     290              : 
     291              :                 //      add to local defect
     292            0 :                         d(_C_, i) += integrand;
     293              :                 }
     294              :         }
     295            0 : }
     296              : 
     297              : 
     298              : template<typename TDomain>
     299              : template<typename TElem, typename TFEGeom>
     300            0 : void ConvectionDiffusionFE<TDomain>::
     301              : add_def_M_elem(LocalVector& d, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     302              : {
     303              : //      request geometry
     304            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     305              : 
     306              :         number shape_u = 0.0;
     307              : 
     308            0 :         if(!m_imMassScale.data_given() && !m_imMass.data_given()) return;
     309              : 
     310              : //      loop integration points
     311            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     312              :         {
     313              :         //      compute value of current solution at ip
     314            0 :                 if(m_imMassScale.data_given()){
     315              :                         shape_u = 0.0;
     316            0 :                         for(size_t j = 0; j < geo.num_sh(); ++j)
     317            0 :                                 shape_u += u(_C_,j) * geo.shape(ip, j);
     318              :                 }
     319              : 
     320              :         //      loop test spaces
     321            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     322              :                 {
     323              :                 //      compute contribution
     324              :                         number val = 0.0;
     325              : 
     326              :                 //      add MassScaling
     327            0 :                         if(m_imMassScale.data_given())
     328            0 :                                 val += shape_u * m_imMassScale[ip];
     329              : 
     330              :                 //      add Maxx
     331            0 :                         if(m_imMass.data_given())
     332            0 :                                 val += m_imMass[ip];
     333              : 
     334              :                 //      add to local defect
     335            0 :                         d(_C_, i) +=  val * geo.shape(ip, i) * geo.weight(ip);
     336              :                 }
     337              :         }
     338              : };
     339              : 
     340              : template<typename TDomain>
     341              : template<typename TElem, typename TFEGeom>
     342            0 : void ConvectionDiffusionFE<TDomain>::
     343              : add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector<dim> vCornerCoords[])
     344              : {
     345              : //      request geometry
     346            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     347              : 
     348              : //      skip if no source present
     349            0 :         if(!m_imSource.data_given() && !m_imVectorSource.data_given()) return;
     350              : 
     351              : //      loop integration points
     352            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     353              :         {
     354              :         //      loop test spaces
     355              : 
     356              :                 // only do this if (volume) source is given
     357            0 :                 if(m_imSource.data_given()) {
     358            0 :                         for(size_t i = 0; i < geo.num_sh(); ++i)
     359              :                         {
     360              :                         //      add contribution to local defect
     361            0 :                                 d(_C_, i) += m_imSource[ip] * geo.shape(ip, i) * geo.weight(ip);
     362              :                         }
     363              :                 }
     364              : 
     365              :                 //      only do this if vector source is given
     366            0 :                 if(m_imVectorSource.data_given()) {
     367            0 :                         for(size_t i = 0; i < geo.num_sh(); ++i)
     368              :                         {
     369              :                         //      add contribution to local defect
     370            0 :                                 d(_C_, i) += geo.weight(ip) * VecDot(m_imVectorSource[ip], geo.global_grad(ip, i));
     371              :                         }
     372              :                 }
     373              :         }
     374              : }
     375              : 
     376              : // ////////////////////////////////
     377              : //   error estimation (begin)   ///
     378              : 
     379              : //      prepares the loop over all elements of one type for the computation of the error estimator
     380              : template<typename TDomain>
     381              : template<typename TElem, typename TFEGeom>
     382            0 : void ConvectionDiffusionFE<TDomain>::
     383              : prep_err_est_elem_loop(const ReferenceObjectID roid, const int si)
     384              : {
     385              :         //      get the error estimator data object and check that it is of the right type
     386              :         //      we check this at this point in order to be able to dispense with this check later on
     387              :         //      (i.e. in prep_err_est_elem and compute_err_est_A_elem())
     388            0 :         UG_COND_THROW(this->m_spErrEstData.get() == NULL,
     389              :                                   "No ErrEstData object has been given to this ElemDisc!");
     390              : 
     391            0 :         err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get());
     392              : 
     393            0 :         UG_COND_THROW(!err_est_data, "Dynamic cast to SideAndElemErrEstData failed." << std::endl
     394              :                                   << "Make sure you handed the correct type of ErrEstData to this discretization.");
     395              : 
     396              : 
     397              : //      set local positions
     398              :         static const int refDim = TElem::dim;
     399              : 
     400              :         // get local IPs
     401              :         size_t numSideIPs, numElemIPs;
     402              :         const MathVector<refDim>* sideIPs;
     403              :         const MathVector<refDim>* elemIPs;
     404              :         try
     405              :         {
     406              :                 numSideIPs = err_est_data->num_all_side_ips(roid);
     407            0 :                 numElemIPs = err_est_data->num_elem_ips(roid);
     408            0 :                 sideIPs = err_est_data->template side_local_ips<refDim>(roid);
     409            0 :                 elemIPs = err_est_data->template elem_local_ips<refDim>(roid);
     410              : 
     411            0 :                 if (!sideIPs || !elemIPs) return;       // are NULL if TElem is not of the same dim as TDomain
     412              :         }
     413            0 :         UG_CATCH_THROW("Integration points for error estimator cannot be set.");
     414              : 
     415              :         // set local IPs in imports
     416            0 :         m_imDiffusion.template          set_local_ips<refDim>(sideIPs, numSideIPs, false);
     417            0 :         m_imVelocity.template           set_local_ips<refDim>(sideIPs, numSideIPs, false);
     418            0 :         m_imFlux.template                       set_local_ips<refDim>(sideIPs, numSideIPs, false);
     419            0 :         m_imSource.template             set_local_ips<refDim>(elemIPs, numElemIPs, false);
     420            0 :         m_imVectorSource.template       set_local_ips<refDim>(sideIPs, numSideIPs, false);
     421            0 :         m_imReactionRate.template       set_local_ips<refDim>(elemIPs, numElemIPs, false);
     422            0 :         m_imReaction.template           set_local_ips<refDim>(elemIPs, numElemIPs, false);
     423            0 :         m_imMassScale.template          set_local_ips<refDim>(elemIPs, numElemIPs, false);
     424            0 :         m_imMass.template                       set_local_ips<refDim>(elemIPs, numElemIPs, false);
     425              : 
     426              :         // store values of shape functions in local IPs
     427              :         LagrangeP1<typename reference_element_traits<TElem>::reference_element_type> trialSpace
     428            0 :                                 = Provider<LagrangeP1<typename reference_element_traits<TElem>::reference_element_type> >::get();
     429              : 
     430            0 :         m_shapeValues.resize(numElemIPs, numSideIPs, trialSpace.num_sh());
     431            0 :         for (size_t ip = 0; ip < numElemIPs; ip++)
     432            0 :                 trialSpace.shapes(m_shapeValues.shapesAtElemIP(ip), elemIPs[ip]);
     433            0 :         for (size_t ip = 0; ip < numSideIPs; ip++)
     434            0 :                 trialSpace.shapes(m_shapeValues.shapesAtSideIP(ip), sideIPs[ip]);
     435              : }
     436              : 
     437              : template<typename TDomain>
     438              : template<typename TElem, typename TFEGeom>
     439            0 : void ConvectionDiffusionFE<TDomain>::
     440              : prep_err_est_elem(const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     441              : {
     442            0 :         err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get());
     443              : 
     444              : //      request geometry
     445            0 :         TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     446              : 
     447              :         try{
     448              :                 geo.update(elem, vCornerCoords);
     449              :         }
     450            0 :         UG_CATCH_THROW("ConvectionDiffusion::prep_elem:"
     451              :                                         " Cannot update Finite Element Geometry.");
     452              : 
     453              : //      roid
     454            0 :         ReferenceObjectID roid = elem->reference_object_id();
     455              : 
     456              : //      set global positions
     457              :         size_t numSideIPs, numElemIPs;
     458              :         const MathVector<dim>* sideIPs;
     459              :         const MathVector<dim>* elemIPs;
     460              : 
     461              :         try
     462              :         {
     463              :                 numSideIPs = err_est_data->num_all_side_ips(roid);
     464            0 :                 numElemIPs = err_est_data->num_elem_ips(roid);
     465              : 
     466            0 :                 sideIPs = err_est_data->all_side_global_ips(elem, vCornerCoords);
     467            0 :                 elemIPs = err_est_data->elem_global_ips(elem, vCornerCoords);
     468              :         }
     469            0 :         UG_CATCH_THROW("Global integration points for error estimator cannot be set.");
     470              : 
     471            0 :         m_imDiffusion.                  set_global_ips(&sideIPs[0], numSideIPs);
     472            0 :         m_imVelocity.                   set_global_ips(&sideIPs[0], numSideIPs);
     473            0 :         m_imFlux.                               set_global_ips(&sideIPs[0], numSideIPs);
     474            0 :         m_imSource.                             set_global_ips(&elemIPs[0], numElemIPs);
     475            0 :         m_imVectorSource.               set_global_ips(&sideIPs[0], numSideIPs);
     476            0 :         m_imReactionRate.               set_global_ips(&elemIPs[0], numElemIPs);
     477            0 :         m_imReaction.                   set_global_ips(&elemIPs[0], numElemIPs);
     478            0 :         m_imMassScale.                  set_global_ips(&elemIPs[0], numElemIPs);
     479            0 :         m_imMass.                               set_global_ips(&elemIPs[0], numElemIPs);
     480            0 : }
     481              : 
     482              : //      computes the error estimator contribution (stiffness part) for one element
     483              : template<typename TDomain>
     484              : template<typename TElem, typename TFEGeom>
     485            0 : void ConvectionDiffusionFE<TDomain>::
     486              : compute_err_est_A_elem(const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[], const number& scale)
     487              : {
     488              :         typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
     489              : 
     490            0 :         err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get());
     491            0 :         UG_COND_THROW(err_est_data->surface_view().get() == NULL, "Error estimator has NULL surface view.");
     492              : 
     493            0 :         MultiGrid* pErrEstGrid = (MultiGrid*) (err_est_data->surface_view()->subset_handler()->multi_grid());
     494              : 
     495              :         // Request geometry.
     496            0 :         static const TFEGeom& geo = GeomProvider<TFEGeom>::get();
     497              : 
     498              : 
     499              : // SIDE TERMS //
     500              : 
     501              : //      get the sides of the element
     502              :         //      We have to cast elem to a pointer of type SideAndElemErrEstData::elem_type
     503              :         //      for the SideAndElemErrEstData::operator() to work properly.
     504              :         //      This cannot generally be achieved by casting to TElem*, since this method is also registered for
     505              :         //      lower-dimensional types TElem, and must therefore be compilable, even if it is never EVER to be executed.
     506              :         //      The way we achieve this here, is by calling associated_elements_sorted() which has an implementation for
     507              :         //      all possible types. Whatever comes out of it is of course complete nonsense if (and only if)
     508              :         //      SideAndElemErrEstData::elem_type != TElem. To be on the safe side, we throw an error if the number of
     509              :         //      entries in the list is not as it should be.
     510              : 
     511              :         typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::side_type>::secure_container side_list;
     512            0 :         pErrEstGrid->associated_elements_sorted(side_list, (TElem*) elem);
     513              : 
     514            0 :         UG_COND_THROW (side_list.size() != (size_t) ref_elem_type::numSides,
     515              :                                  "Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'");
     516              : 
     517              :         //      Some auxiliary variables.
     518              :         MathVector<dim> fluxDensity, gradC, normal;
     519              : 
     520              :         // FIXME: The computation of the gradient has to be reworked.
     521              :         // In the case of P1 shape functions, it is valid. For Q1 shape functions, however,
     522              :         // the gradient is not constant (but bilinear) on the element - and along the sides.
     523              :         // We cannot use the FVGeom here. Instead, we need to calculate the gradient in each IP!
     524              : 
     525              :         // Calculate grad(u) as average (over scvf).
     526              :         VecSet(gradC, 0.0);
     527            0 :         for(size_t ii = 0; ii < geo.num_ip(); ++ii)
     528              :         {
     529            0 :                 for (size_t j=0; j<m_shapeValues.num_sh(); j++)
     530            0 :                                 VecScaleAppend(gradC, u(_C_,j), geo.global_grad(ii, j));
     531              :         }
     532            0 :         VecScale(gradC, gradC, (1.0/geo.num_ip()));
     533              : 
     534              :         // Calculate flux through the sides.
     535              :         size_t passedIPs = 0;
     536            0 :         for (size_t side=0; side < (size_t) ref_elem_type::numSides; side++)
     537              :         {
     538              :                 // normal on side
     539            0 :                 SideNormal<ref_elem_type,dim>(normal, side, vCornerCoords);
     540            0 :                 VecNormalize(normal, normal);
     541              : 
     542              :                 try
     543              :                 {
     544            0 :                         for (size_t sip = 0; sip < err_est_data->num_side_ips(side_list[side]); sip++)
     545              :                         {
     546            0 :                                 size_t ip = passedIPs + sip;
     547              : 
     548              :                                 VecSet(fluxDensity, 0.0);
     549              : 
     550              :                         // diffusion //
     551            0 :                                 if (m_imDiffusion.data_given())
     552              :                                         MatVecScaleMultAppend(fluxDensity, -1.0, m_imDiffusion[ip], gradC);
     553              : 
     554              :                         // convection //
     555            0 :                                 if (m_imVelocity.data_given())
     556              :                                 {
     557              :                                         number val = 0.0;
     558            0 :                                         for (size_t sh = 0; sh < m_shapeValues.num_sh(); sh++)
     559            0 :                                                 val += u(_C_,sh) * m_shapeValues.shapeAtSideIP(sh,sip);
     560              : 
     561              :                                         VecScaleAppend(fluxDensity, val, m_imVelocity[ip]);
     562              :                                 }
     563              : 
     564              :                         // general flux //
     565            0 :                                 if (m_imFlux.data_given())
     566              :                                         VecAppend(fluxDensity, m_imFlux[ip]);
     567              : 
     568            0 :                                 (*err_est_data)(side_list[side],sip) += scale * VecDot(fluxDensity, normal);
     569              :                         }
     570              : 
     571            0 :                         passedIPs += err_est_data->num_side_ips(side_list[side]);
     572              :                 }
     573            0 :                 UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl
     574              :                                 << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData.");
     575              :         }
     576              : 
     577              : // VOLUME TERMS //
     578              : 
     579              :         typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::elem_type>::secure_container elem_list;
     580              :         pErrEstGrid->associated_elements_sorted(elem_list, (TElem*) elem);
     581            0 :         UG_COND_THROW (elem_list.size() != 1, "Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'");
     582              : 
     583              :         try
     584              :         {
     585            0 :                 for (size_t ip = 0; ip < err_est_data->num_elem_ips(elem->reference_object_id()); ip++)
     586              :                 {
     587              :                         number total = 0.0;
     588              : 
     589              :                 // diffusion // TODO ONLY FOR (PIECEWISE) CONSTANT DIFFUSION TENSOR SO FAR!
     590              :                 // div(D*grad(c))
     591              :                 // nothing to do, as c is piecewise linear and div(D*grad(c)) disappears
     592              :                 // if D is diagonal and c bilinear, this should also vanish (confirm this!)
     593              : 
     594              :                 // convection // TODO ONLY FOR (PIECEWISE) CONSTANT OR DIVERGENCE-FREE
     595              :                                           //      VELOCITY FIELDS SO FAR!
     596              :                 // div(v*c) = div(v)*c + v*grad(c) -- gradC has been calculated above
     597            0 :                         if (m_imVelocity.data_given())
     598            0 :                                 total += VecDot(m_imVelocity[ip], gradC);
     599              : 
     600              :                 // general flux // TODO ONLY FOR DIVERGENCE-FREE FLUX FIELD SO FAR!
     601              :                 // nothing to do
     602              : 
     603              :                 // reaction //
     604            0 :                         if (m_imReactionRate.data_given())
     605              :                         {
     606              :                                 number val = 0.0;
     607            0 :                                 for (size_t sh = 0; sh < geo.num_sh(); sh++)
     608            0 :                                         val += u(_C_,sh) * m_shapeValues.shapeAtElemIP(sh,ip);
     609              : 
     610            0 :                                 total += m_imReactionRate[ip] * val;
     611              :                         }
     612              : 
     613            0 :                         if (m_imReaction.data_given())
     614              :                         {
     615            0 :                                 total += m_imReaction[ip];
     616              :                         }
     617              : 
     618            0 :                         (*err_est_data)(elem_list[0],ip) += scale * total;
     619              :                 }
     620              :         }
     621            0 :         UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl
     622              :                         << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData.");
     623            0 : }
     624              : 
     625              : //      computes the error estimator contribution (mass part) for one element
     626              : template<typename TDomain>
     627              : template<typename TElem, typename TFEGeom>
     628            0 : void ConvectionDiffusionFE<TDomain>::
     629              : compute_err_est_M_elem(const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[], const number& scale)
     630              : {
     631              : // note: mass parts only enter volume term
     632              : 
     633            0 :         err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get());
     634            0 :         UG_COND_THROW(err_est_data->surface_view().get() == NULL,
     635              :                                 "Error estimator has NULL surface view.");
     636              : 
     637            0 :         MultiGrid* pErrEstGrid = (MultiGrid*) (err_est_data->surface_view()->subset_handler()->multi_grid());
     638              : 
     639              :         typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::elem_type>::secure_container elem_list;
     640            0 :         pErrEstGrid->associated_elements_sorted(elem_list, (TElem*) elem);
     641            0 :         UG_COND_THROW (elem_list.size() != 1,
     642              :                               "Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'");
     643              : 
     644              : //      request geometry
     645            0 :         static const TFEGeom& geo = GeomProvider<TFEGeom>::get();
     646              : 
     647              : //      loop integration points
     648              :         try
     649              :         {
     650            0 :                 for (size_t ip = 0; ip < err_est_data->num_elem_ips(elem->reference_object_id()); ip++)
     651              :                 {
     652              :                         number total = 0.0;
     653              : 
     654              :                 // mass scale //
     655            0 :                         if (m_imMassScale.data_given())
     656              :                         {
     657              :                                 number val = 0.0;
     658            0 :                                 for (size_t sh = 0; sh < geo.num_sh(); sh++)
     659            0 :                                         val += u(_C_,sh) * m_shapeValues.shapeAtElemIP(sh,ip);
     660              : 
     661            0 :                                 total += m_imMassScale[ip] * val;
     662              :                         }
     663              : 
     664              :                 // mass //
     665            0 :                         if (m_imMass.data_given())
     666              :                         {
     667            0 :                                 total += m_imMass[ip];
     668              :                         }
     669              : 
     670            0 :                         (*err_est_data)(elem_list[0],ip) += scale * total;
     671              :                 }
     672              :         }
     673            0 :         UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl
     674              :                         << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData.");
     675            0 : }
     676              : 
     677              : //      computes the error estimator contribution (rhs part) for one element
     678              : template<typename TDomain>
     679              : template<typename TElem, typename TFEGeom>
     680            0 : void ConvectionDiffusionFE<TDomain>::
     681              : compute_err_est_rhs_elem(GridObject* elem, const MathVector<dim> vCornerCoords[], const number& scale)
     682              : {
     683              :         typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
     684              : 
     685            0 :         err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get());
     686            0 :         UG_COND_THROW(err_est_data->surface_view().get() == NULL, "Error estimator has NULL surface view.");
     687              : 
     688            0 :         MultiGrid* pErrEstGrid = (MultiGrid*) (err_est_data->surface_view()->subset_handler()->multi_grid());
     689              : 
     690              : // SIDE TERMS //
     691              : 
     692              : //      get the sides of the element
     693              :         typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::side_type>::secure_container side_list;
     694            0 :         pErrEstGrid->associated_elements_sorted(side_list, (TElem*) elem);
     695              : 
     696            0 :         UG_COND_THROW(side_list.size() != (size_t) ref_elem_type::numSides,
     697              :                                   "Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'");
     698              : 
     699              : // loop sides
     700              :         size_t passedIPs = 0;
     701            0 :         for (size_t side = 0; side < (size_t) ref_elem_type::numSides; side++)
     702              :         {
     703              :                 // normal on side
     704              :                 MathVector<dim> normal;
     705            0 :                 SideNormal<ref_elem_type,dim>(normal, side, vCornerCoords);
     706            0 :                 VecNormalize(normal, normal);
     707              : 
     708              :                 try
     709              :                 {
     710            0 :                         for (size_t sip = 0; sip < err_est_data->num_side_ips(side_list[side]); sip++)
     711              :                         {
     712            0 :                                 size_t ip = passedIPs + sip;
     713              : 
     714              :                         // vector source //
     715            0 :                                 if (m_imVectorSource.data_given())
     716            0 :                                         (*err_est_data)(side_list[side],sip) += scale * VecDot(m_imVectorSource[ip], normal);
     717              :                         }
     718              : 
     719            0 :                         passedIPs += err_est_data->num_side_ips(side_list[side]);
     720              :                 }
     721            0 :                 UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl
     722              :                                 << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData.");
     723              :         }
     724              : 
     725              : // VOLUME TERMS //
     726              : 
     727            0 :         if (!m_imSource.data_given()) return;
     728              : 
     729              :         typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::elem_type>::secure_container elem_list;
     730              :         pErrEstGrid->associated_elements_sorted(elem_list, (TElem*) elem);
     731              : 
     732            0 :         UG_COND_THROW (elem_list.size() != 1,
     733              :                                  "Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'");
     734              : 
     735              : // source //
     736              :         try
     737              :         {
     738            0 :                 for (size_t ip = 0; ip < err_est_data->num_elem_ips(elem->reference_object_id()); ip++)
     739            0 :                         (*err_est_data)(elem_list[0],ip) += scale * m_imSource[ip];
     740              :         }
     741            0 :         UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl
     742              :                         << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData.");
     743              : }
     744              : 
     745              : //      postprocesses the loop over all elements of one type in the computation of the error estimator
     746              : template<typename TDomain>
     747              : template<typename TElem, typename TFEGeom>
     748            0 : void ConvectionDiffusionFE<TDomain>::
     749              : fsh_err_est_elem_loop()
     750              : {
     751              : //      finish the element loop in the same way as the actual discretization
     752              :         this->template fsh_elem_loop<TElem, TFEGeom> ();
     753            0 : };
     754              : 
     755              : //    error estimation (end)     ///
     756              : // /////////////////////////////////
     757              : 
     758              : 
     759              : //      computes the linearized defect w.r.t to the velocity
     760              : template<typename TDomain>
     761              : template <typename TElem, typename TFEGeom>
     762            0 : void ConvectionDiffusionFE<TDomain>::
     763              : lin_def_velocity(const LocalVector& u,
     764              :                      std::vector<std::vector<MathVector<dim> > > vvvLinDef[],
     765              :                      const size_t nip)
     766              : {
     767              : //      request geometry
     768            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     769              : 
     770              : //      loop integration points
     771            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     772              :         {
     773              :         //      get current u and grad_u
     774              :                 number shape_u = 0.0;
     775            0 :                 for(size_t j = 0; j < geo.num_sh(); ++j)
     776            0 :                         shape_u += u(_C_,j) * geo.shape(ip, j);
     777              : 
     778              :         //      loop test spaces
     779            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     780              :                 {
     781              :                 //      add to local defect
     782            0 :                         VecScale(vvvLinDef[ip][_C_][i], geo.global_grad(ip, i),
     783            0 :                                                                                 (-1)* geo.weight(ip) * shape_u);
     784              :                 }
     785              :         }
     786            0 : }
     787              : 
     788              : //      computes the linearized defect w.r.t to the flux
     789              : template<typename TDomain>
     790              : template <typename TElem, typename TFEGeom>
     791            0 : void ConvectionDiffusionFE<TDomain>::
     792              : lin_def_flux(const LocalVector& u,
     793              :              std::vector<std::vector<MathVector<dim> > > vvvLinDef[],
     794              :              const size_t nip)
     795              : {
     796              : //      request geometry
     797            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     798              : 
     799              : //      loop integration points
     800            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     801              :         {
     802              :         //      loop test spaces
     803            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     804              :                 {
     805              :                 //      add to local defect
     806            0 :                         VecScale(vvvLinDef[ip][_C_][i], geo.global_grad(ip, i),
     807              :                                                                                 (-1)* geo.weight(ip));
     808              :                 }
     809              :         }
     810            0 : }
     811              : 
     812              : //      computes the linearized defect w.r.t to the velocity
     813              : template<typename TDomain>
     814              : template <typename TElem, typename TFEGeom>
     815            0 : void ConvectionDiffusionFE<TDomain>::
     816              : lin_def_diffusion(const LocalVector& u,
     817              :                       std::vector<std::vector<MathMatrix<dim,dim> > > vvvLinDef[],
     818              :                       const size_t nip)
     819              : {
     820              : //      request geometry
     821            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     822              : 
     823              :         MathVector<dim> grad_u;
     824              : 
     825              : //      loop integration points
     826            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     827              :         {
     828              :         //      get current u and grad_u
     829              :                 VecSet(grad_u, 0.0);
     830            0 :                 for(size_t j = 0; j < geo.num_sh(); ++j)
     831              :                         VecScaleAppend(grad_u, u(_C_,j), geo.global_grad(ip, j));
     832              : 
     833              :         //      loop test spaces
     834            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     835              :                 {
     836            0 :                         for(size_t k = 0; k < (size_t)dim; ++k)
     837            0 :                                 for(size_t j = 0; j < (size_t)dim; ++j)
     838            0 :                                         (vvvLinDef[ip][_C_][i])(k,j) = grad_u[j] * geo.global_grad(ip, i)[k]
     839            0 :                                                                                                 * geo.weight(ip);
     840              :                 }
     841              :         }
     842            0 : }
     843              : 
     844              : //      computes the linearized defect w.r.t to the reaction
     845              : template<typename TDomain>
     846              : template <typename TElem, typename TFEGeom>
     847            0 : void ConvectionDiffusionFE<TDomain>::
     848              : lin_def_reaction(const LocalVector& u,
     849              :                      std::vector<std::vector<number> > vvvLinDef[],
     850              :                      const size_t nip)
     851              : {
     852              : //      request geometry
     853            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     854              : 
     855              : //      loop integration points
     856            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     857              :         {
     858              :         //      loop test spaces
     859            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     860              :                 {
     861              :                 //      compute contribution
     862            0 :                         const number val = geo.shape(ip, i) * geo.weight(ip);
     863              : 
     864              :                 //      add to local defect
     865            0 :                         vvvLinDef[ip][_C_][i] = val;
     866              :                 }
     867              :         }
     868            0 : }
     869              : 
     870              : //      computes the linearized defect w.r.t to the reaction
     871              : template<typename TDomain>
     872              : template <typename TElem, typename TFEGeom>
     873            0 : void ConvectionDiffusionFE<TDomain>::
     874              : lin_def_reaction_rate(const LocalVector& u,
     875              :                          std::vector<std::vector<number> > vvvLinDef[],
     876              :                          const size_t nip)
     877              : {
     878              : //      request geometry
     879            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     880              : 
     881              : //      loop integration points
     882            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     883              :         {
     884              :         //      compute value of current solution at ip
     885              :                 number shape_u = 0.0;
     886            0 :                 for(size_t j = 0; j < geo.num_sh(); ++j)
     887            0 :                         shape_u += u(_C_,j) * geo.shape(ip, j);
     888              : 
     889              :         //      loop test spaces
     890            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     891              :                 {
     892              :                 //      compute contribution
     893            0 :                         const number val = shape_u * geo.shape(ip, i) * geo.weight(ip);
     894              : 
     895              :                 //      add to local defect
     896            0 :                         vvvLinDef[ip][_C_][i] = val;
     897              :                 }
     898              :         }
     899            0 : }
     900              : 
     901              : 
     902              : //      computes the linearized defect w.r.t to the source
     903              : template<typename TDomain>
     904              : template <typename TElem, typename TFEGeom>
     905            0 : void ConvectionDiffusionFE<TDomain>::
     906              : lin_def_source(const LocalVector& u,
     907              :                    std::vector<std::vector<number> > vvvLinDef[],
     908              :                    const size_t nip)
     909              : {
     910              : //      request geometry
     911            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     912              : 
     913              : //      loop integration points
     914            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     915              :         {
     916              :         //      loop test spaces
     917            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     918              :                 {
     919              :                 //      add contribution to local defect
     920            0 :                         vvvLinDef[ip][_C_][i] = geo.shape(ip, i) * geo.weight(ip);
     921              :                 }
     922              :         }
     923            0 : }
     924              : 
     925              : //      computes the linearized defect w.r.t to the "vector source"
     926              : template<typename TDomain>
     927              : template <typename TElem, typename TFEGeom>
     928            0 : void ConvectionDiffusionFE<TDomain>::
     929              : lin_def_vector_source(const LocalVector& u,
     930              :                            std::vector<std::vector<MathVector<dim> > > vvvLinDef[],
     931              :                            const size_t nip)
     932              : {
     933              : //      request geometry
     934            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     935              : 
     936              : //      loop integration points
     937            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     938              :         {
     939              :         //      loop test spaces
     940            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     941              :                 {
     942              :                 //      add to local defect
     943            0 :                         VecScale(vvvLinDef[ip][_C_][i], geo.global_grad(ip, i),
     944              :                                                                                  geo.weight(ip));
     945              :                 }
     946              :         }
     947            0 : }
     948              : 
     949              : //      computes the linearized defect w.r.t to the mass scale
     950              : template<typename TDomain>
     951              : template <typename TElem, typename TFEGeom>
     952            0 : void ConvectionDiffusionFE<TDomain>::
     953              : lin_def_mass_scale(const LocalVector& u,
     954              :                        std::vector<std::vector<number> > vvvLinDef[],
     955              :                        const size_t nip)
     956              : {
     957              : //      request geometry
     958            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     959              : 
     960              : //      loop integration points
     961            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     962              :         {
     963              :         //      compute value of current solution at ip
     964              :                 number shape_u = 0.0;
     965            0 :                 for(size_t j = 0; j < geo.num_sh(); ++j)
     966            0 :                         shape_u += u(_C_,j) * geo.shape(ip, j);
     967              : 
     968              :         //      loop test spaces
     969            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     970              :                 {
     971              :                 //      compute contribution
     972            0 :                         const number val = shape_u * geo.shape(ip, i) * geo.weight(ip);
     973              : 
     974              :                 //      add to local defect
     975            0 :                         vvvLinDef[ip][_C_][i] = val;
     976              :                 }
     977              :         }
     978            0 : }
     979              : 
     980              : //      computes the linearized defect w.r.t to the mass scale
     981              : template<typename TDomain>
     982              : template <typename TElem, typename TFEGeom>
     983            0 : void ConvectionDiffusionFE<TDomain>::
     984              : lin_def_mass(const LocalVector& u,
     985              :                 std::vector<std::vector<number> > vvvLinDef[],
     986              :                 const size_t nip)
     987              : {
     988              : //      request geometry
     989            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
     990              : 
     991              : //      loop integration points
     992            0 :         for(size_t ip = 0; ip < geo.num_ip(); ++ip)
     993              :         {
     994              :         //      loop test spaces
     995            0 :                 for(size_t i = 0; i < geo.num_sh(); ++i)
     996              :                 {
     997              :                 //      compute contribution
     998            0 :                         const number val = geo.shape(ip, i) * geo.weight(ip);
     999              : 
    1000              :                 //      add to local defect
    1001            0 :                         vvvLinDef[ip][_C_][i] = val;
    1002              :                 }
    1003              :         }
    1004            0 : }
    1005              : 
    1006              : //      computes the linearized defect w.r.t to the velocity
    1007              : template<typename TDomain>
    1008              : template <typename TElem, typename TFEGeom>
    1009            0 : void ConvectionDiffusionFE<TDomain>::
    1010              : ex_value(number vValue[],
    1011              :          const MathVector<dim> vGlobIP[],
    1012              :          number time, int si,
    1013              :          const LocalVector& u,
    1014              :          GridObject* elem,
    1015              :          const MathVector<dim> vCornerCoords[],
    1016              :          const MathVector<TFEGeom::dim> vLocIP[],
    1017              :          const size_t nip,
    1018              :          bool bDeriv,
    1019              :          std::vector<std::vector<number> > vvvDeriv[])
    1020              : {
    1021              : //      request geometry
    1022            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
    1023              : 
    1024              : //      reference element
    1025              :         typedef typename reference_element_traits<TElem>::reference_element_type
    1026              :                         ref_elem_type;
    1027              : 
    1028              : //      reference dimension
    1029              :         static const int refDim = reference_element_traits<TElem>::dim;
    1030              : 
    1031              : //      reference object id
    1032              :         static const ReferenceObjectID roid = ref_elem_type::REFERENCE_OBJECT_ID;
    1033              : 
    1034              : //      FE ip
    1035            0 :         if(vLocIP == geo.local_ips())
    1036              :         {
    1037              :         //      Loop ips
    1038            0 :                 for(size_t ip = 0; ip < geo.num_ip(); ++ip)
    1039              :                 {
    1040              :                 //      compute concentration at ip
    1041            0 :                         vValue[ip] = 0.0;
    1042            0 :                         for(size_t sh = 0; sh < geo.num_sh(); ++sh)
    1043            0 :                                 vValue[ip] += u(_C_, sh) * geo.shape(ip, sh);
    1044              : 
    1045              :                 //      compute derivative w.r.t. to unknowns iff needed
    1046            0 :                         if(bDeriv)
    1047            0 :                                 for(size_t sh = 0; sh < geo.num_sh(); ++sh)
    1048            0 :                                         vvvDeriv[ip][_C_][sh] = geo.shape(ip, sh);
    1049              :                 }
    1050              :         }
    1051              : //      general case
    1052              :         else
    1053              :         {
    1054              :         //      request for trial space
    1055              :                 try{
    1056              :                 const LocalShapeFunctionSet<refDim>& rTrialSpace
    1057            0 :                          = LocalFiniteElementProvider::get<refDim>(roid, m_lfeID);
    1058              : 
    1059              :         //      number of shape functions
    1060            0 :                 const size_t numSH = rTrialSpace.num_sh();
    1061              : 
    1062              :         //      storage for shape function at ip
    1063            0 :                 std::vector<number> vShape(numSH);
    1064              : 
    1065              :         //      loop ips
    1066            0 :                 for(size_t ip = 0; ip < nip; ++ip)
    1067              :                 {
    1068              :                 //      evaluate at shapes at ip
    1069            0 :                         rTrialSpace.shapes(vShape, vLocIP[ip]);
    1070              : 
    1071              :                 //      compute concentration at ip
    1072            0 :                         vValue[ip] = 0.0;
    1073            0 :                         for(size_t sh = 0; sh < numSH; ++sh)
    1074            0 :                                 vValue[ip] += u(_C_, sh) * vShape[sh];
    1075              : 
    1076              :                 //      compute derivative w.r.t. to unknowns iff needed
    1077              :                 //      \todo: maybe store shapes directly in vvvDeriv
    1078            0 :                         if(bDeriv)
    1079            0 :                                 for(size_t sh = 0; sh < numSH; ++sh)
    1080            0 :                                         vvvDeriv[ip][_C_][sh] = vShape[sh];
    1081              :                 }
    1082              : 
    1083            0 :                 }
    1084            0 :                 UG_CATCH_THROW("ConvectionDiffusion::ex_value: trial space missing.");
    1085              :         }
    1086            0 : }
    1087              : 
    1088              : template<typename TDomain>
    1089              : template <typename TElem, typename TFEGeom>
    1090            0 : void ConvectionDiffusionFE<TDomain>::
    1091              : ex_grad(MathVector<dim> vValue[],
    1092              :         const MathVector<dim> vGlobIP[],
    1093              :         number time, int si,
    1094              :         const LocalVector& u,
    1095              :         GridObject* elem,
    1096              :         const MathVector<dim> vCornerCoords[],
    1097              :         const MathVector<TFEGeom::dim> vLocIP[],
    1098              :         const size_t nip,
    1099              :         bool bDeriv,
    1100              :         std::vector<std::vector<MathVector<dim> > > vvvDeriv[])
    1101              : {
    1102              : //      request geometry
    1103            0 :         const TFEGeom& geo = GeomProvider<TFEGeom>::get(m_lfeID, m_quadOrder);
    1104              : 
    1105              : //      reference element
    1106              :         typedef typename reference_element_traits<TElem>::reference_element_type
    1107              :                         ref_elem_type;
    1108              : 
    1109              : //      reference dimension
    1110              :         static const int refDim = reference_element_traits<TElem>::dim;
    1111              : 
    1112              : //      reference object id
    1113              :         static const ReferenceObjectID roid = ref_elem_type::REFERENCE_OBJECT_ID;
    1114              : 
    1115              : //      FE
    1116            0 :         if(vLocIP == geo.local_ips())
    1117              :         {
    1118              :         //      Loop ip
    1119            0 :                 for(size_t ip = 0; ip < geo.num_ip(); ++ip)
    1120              :                 {
    1121            0 :                         VecSet(vValue[ip], 0.0);
    1122            0 :                         for(size_t sh = 0; sh < geo.num_sh(); ++sh)
    1123              :                                 VecScaleAppend(vValue[ip], u(_C_, sh), geo.global_grad(ip, sh));
    1124              : 
    1125            0 :                         if(bDeriv)
    1126            0 :                                 for(size_t sh = 0; sh < geo.num_sh(); ++sh)
    1127            0 :                                         vvvDeriv[ip][_C_][sh] = geo.global_grad(ip, sh);
    1128              :                 }
    1129              :         }
    1130              : //      general case
    1131              :         else
    1132              :         {
    1133              :         //      request for trial space
    1134              :                 try{
    1135              :                 const LocalShapeFunctionSet<refDim>& rTrialSpace
    1136            0 :                          = LocalFiniteElementProvider::get<refDim>(roid, m_lfeID);
    1137              : 
    1138              :         //      number of shape functions
    1139            0 :                 const size_t numSH = rTrialSpace.num_sh();
    1140              : 
    1141              :         //      storage for shape function at ip
    1142            0 :                 std::vector<MathVector<refDim> > vLocGrad(numSH);
    1143              :                 MathVector<refDim> locGrad;
    1144              : 
    1145              :         //      Reference Mapping
    1146              :                 MathMatrix<dim, refDim> JTInv;
    1147            0 :                 ReferenceMapping<ref_elem_type, dim> mapping(vCornerCoords);
    1148              : 
    1149              :         //      loop ips
    1150            0 :                 for(size_t ip = 0; ip < nip; ++ip)
    1151              :                 {
    1152              :                 //      evaluate at shapes at ip
    1153            0 :                         rTrialSpace.grads(vLocGrad, vLocIP[ip]);
    1154              : 
    1155              :                 //      compute grad at ip
    1156              :                         VecSet(locGrad, 0.0);
    1157            0 :                         for(size_t sh = 0; sh < numSH; ++sh)
    1158              :                                 VecScaleAppend(locGrad, u(_C_, sh), vLocGrad[sh]);
    1159              : 
    1160              :                 //      compute global grad
    1161            0 :                         mapping.jacobian_transposed_inverse(JTInv, vLocIP[ip]);
    1162            0 :                         MatVecMult(vValue[ip], JTInv, locGrad);
    1163              : 
    1164              :                 //      compute derivative w.r.t. to unknowns iff needed
    1165            0 :                         if(bDeriv)
    1166            0 :                                 for(size_t sh = 0; sh < numSH; ++sh)
    1167            0 :                                         MatVecMult(vvvDeriv[ip][_C_][sh], JTInv, vLocGrad[sh]);
    1168              :                 }
    1169            0 :                 }
    1170            0 :                 UG_CATCH_THROW("ConvectionDiffusion::ex_grad: trial space missing.");
    1171              :         }
    1172            0 : };
    1173              : 
    1174              : ////////////////////////////////////////////////////////////////////////////////
    1175              : //      register assemble functions
    1176              : ////////////////////////////////////////////////////////////////////////////////
    1177              : 
    1178              : #ifdef UG_DIM_1
    1179              : template<>
    1180            0 : void ConvectionDiffusionFE<Domain1d>::
    1181              : register_all_funcs(const LFEID& lfeid, const int quadOrder)
    1182              : {
    1183              : //      RegularEdge
    1184            0 :         register_func<RegularEdge, DimFEGeometry<dim> >();
    1185            0 : }
    1186              : #endif
    1187              : 
    1188              : #ifdef UG_DIM_2
    1189              : template<>
    1190            0 : void ConvectionDiffusionFE<Domain2d>::
    1191              : register_all_funcs(const LFEID& lfeid, const int quadOrder)
    1192              : {
    1193            0 :         register_func<RegularEdge, DimFEGeometry<dim, 1> >();
    1194              : 
    1195              :         const int order = lfeid.order();
    1196            0 :         if(quadOrder != 2*order+1 || lfeid.type() != LFEID::LAGRANGE)
    1197              :         {
    1198            0 :                 register_func<Triangle, DimFEGeometry<dim> >();
    1199            0 :                 register_func<Quadrilateral, DimFEGeometry<dim> >();
    1200            0 :                 return;
    1201              :         }
    1202              : 
    1203              : //      special compiled cases
    1204              : 
    1205              : //      Triangle
    1206            0 :         switch(order)
    1207              :         {
    1208            0 :                 case 1: {typedef FEGeometry<Triangle, dim, LagrangeLSFS<ReferenceTriangle, 1>, GaussQuadrature<ReferenceTriangle, 3> > FEGeom;
    1209            0 :                                  register_func<Triangle, FEGeom >(); break;}
    1210            0 :                 case 2: {typedef FEGeometry<Triangle, dim, LagrangeLSFS<ReferenceTriangle, 2>, GaussQuadrature<ReferenceTriangle, 5> > FEGeom;
    1211            0 :                                  register_func<Triangle, FEGeom >(); break;}
    1212            0 :                 case 3: {typedef FEGeometry<Triangle, dim, LagrangeLSFS<ReferenceTriangle, 3>, GaussQuadrature<ReferenceTriangle, 7> > FEGeom;
    1213            0 :                                  register_func<Triangle, FEGeom >(); break;}
    1214            0 :                 default: register_func<Triangle, DimFEGeometry<dim> >();  break;
    1215              :         }
    1216              : 
    1217              : //      Quadrilateral
    1218            0 :         switch(order) {
    1219            0 :                 case 1: {typedef FEGeometry<Quadrilateral, dim, LagrangeLSFS<ReferenceQuadrilateral, 1>, GaussQuadrature<ReferenceQuadrilateral, 3> > FEGeom;
    1220            0 :                                  register_func<Quadrilateral, FEGeom >(); break;}
    1221            0 :                 case 2: {typedef FEGeometry<Quadrilateral, dim, LagrangeLSFS<ReferenceQuadrilateral, 2>, GaussQuadrature<ReferenceQuadrilateral, 7> > FEGeom;
    1222            0 :                                  register_func<Quadrilateral, FEGeom >(); break;}
    1223            0 :                 case 3: {typedef FEGeometry<Quadrilateral, dim, LagrangeLSFS<ReferenceQuadrilateral, 3>, GaussQuadrature<ReferenceQuadrilateral, 11> > FEGeom;
    1224            0 :                                  register_func<Quadrilateral, FEGeom >(); break;}
    1225            0 :                 default: register_func<Quadrilateral, DimFEGeometry<dim> >();  break;
    1226              :         }
    1227              : }
    1228              : #endif
    1229              : 
    1230              : #ifdef UG_DIM_3
    1231              : template<>
    1232            0 : void ConvectionDiffusionFE<Domain3d>::
    1233              : register_all_funcs(const LFEID& lfeid, const int quadOrder)
    1234              : {
    1235            0 :         register_func<RegularEdge, DimFEGeometry<dim, 1> >();
    1236            0 :         register_func<Triangle, DimFEGeometry<dim, 2> >();
    1237            0 :         register_func<Quadrilateral, DimFEGeometry<dim, 2> >();
    1238              : 
    1239              :         const int order = lfeid.order();
    1240            0 :         if(quadOrder != 2*order+1 || lfeid.type() != LFEID::LAGRANGE)
    1241              :         {
    1242            0 :                 register_func<Tetrahedron, DimFEGeometry<dim> >();
    1243            0 :                 register_func<Prism, DimFEGeometry<dim> >();
    1244            0 :                 register_func<Pyramid, DimFEGeometry<dim> >();
    1245            0 :                 register_func<Hexahedron, DimFEGeometry<dim> >();
    1246            0 :                 register_func<Octahedron, DimFEGeometry<dim> >();
    1247            0 :                 return;
    1248              :         }
    1249              : 
    1250              : //      special compiled cases
    1251              : 
    1252              : //      Tetrahedron
    1253            0 :         switch(order)
    1254              :         {
    1255            0 :                 case 1: {typedef FEGeometry<Tetrahedron, dim, LagrangeLSFS<ReferenceTetrahedron, 1>, GaussQuadrature<ReferenceTetrahedron, 3> > FEGeom;
    1256            0 :                                  register_func<Tetrahedron, FEGeom >(); break;}
    1257            0 :                 case 2: {typedef FEGeometry<Tetrahedron, dim, LagrangeLSFS<ReferenceTetrahedron, 2>, GaussQuadrature<ReferenceTetrahedron, 5> > FEGeom;
    1258            0 :                                  register_func<Tetrahedron, FEGeom >(); break;}
    1259            0 :                 case 3: {typedef FEGeometry<Tetrahedron, dim, LagrangeLSFS<ReferenceTetrahedron, 3>, GaussQuadrature<ReferenceTetrahedron, 7> > FEGeom;
    1260            0 :                                  register_func<Tetrahedron, FEGeom >(); break;}
    1261            0 :                 default: register_func<Tetrahedron, DimFEGeometry<dim> >();  break;
    1262              :         }
    1263              : 
    1264              : //      Prism
    1265              :         switch(order) {
    1266            0 :                 default: register_func<Prism, DimFEGeometry<dim> >();  break;
    1267              :         }
    1268              : 
    1269              : //      Pyramid
    1270              :         switch(order)
    1271              :         {
    1272            0 :                 default: register_func<Pyramid, DimFEGeometry<dim> >();  break;
    1273              :         }
    1274              : 
    1275              : //      Octahedron
    1276              :         switch(order)
    1277              :         {
    1278            0 :                 default: register_func<Octahedron, DimFEGeometry<dim> >();  break;
    1279              :         }
    1280              : 
    1281              : //      Hexahedron
    1282            0 :         switch(order)
    1283              :         {
    1284            0 :                 case 1: {typedef FEGeometry<Hexahedron, dim, LagrangeLSFS<ReferenceHexahedron, 1>, GaussQuadrature<ReferenceHexahedron, 3> > FEGeom;
    1285            0 :                                  register_func<Hexahedron, FEGeom >(); break;}
    1286            0 :                 case 2: {typedef FEGeometry<Hexahedron, dim, LagrangeLSFS<ReferenceHexahedron, 2>, GaussQuadrature<ReferenceHexahedron, 7> > FEGeom;
    1287            0 :                                  register_func<Hexahedron, FEGeom >(); break;}
    1288            0 :                 case 3: {typedef FEGeometry<Hexahedron, dim, LagrangeLSFS<ReferenceHexahedron, 3>, GaussQuadrature<ReferenceHexahedron, 11> > FEGeom;
    1289            0 :                                  register_func<Hexahedron, FEGeom >(); break;}
    1290            0 :                 default: register_func<Hexahedron, DimFEGeometry<dim> >();  break;
    1291              :         }
    1292              : }
    1293              : #endif
    1294              : 
    1295              : template <typename TDomain>
    1296              : template <typename TElem, typename TFEGeom>
    1297            0 : void ConvectionDiffusionFE<TDomain>::register_func()
    1298              : {
    1299              :         ReferenceObjectID id = geometry_traits<TElem>::REFERENCE_OBJECT_ID;
    1300              :         typedef this_type T;
    1301              :         static const int refDim = reference_element_traits<TElem>::dim;
    1302              : 
    1303              :         this->clear_add_fct(id);
    1304              :         this->set_prep_elem_loop_fct(id, &T::template prep_elem_loop<TElem, TFEGeom>);
    1305              :         this->set_prep_elem_fct(      id, &T::template prep_elem<TElem, TFEGeom>);
    1306              :         this->set_fsh_elem_loop_fct( id, &T::template fsh_elem_loop<TElem, TFEGeom>);
    1307              :         this->set_add_jac_A_elem_fct(id, &T::template add_jac_A_elem<TElem, TFEGeom>);
    1308              :         this->set_add_jac_M_elem_fct(id, &T::template add_jac_M_elem<TElem, TFEGeom>);
    1309              :         this->set_add_def_A_elem_fct(id, &T::template add_def_A_elem<TElem, TFEGeom>);
    1310              :         this->set_add_def_M_elem_fct(id, &T::template add_def_M_elem<TElem, TFEGeom>);
    1311              :         this->set_add_rhs_elem_fct(  id, &T::template add_rhs_elem<TElem, TFEGeom>);
    1312              : 
    1313              : // error estimator parts
    1314              :         this->set_prep_err_est_elem_loop(id, &T::template prep_err_est_elem_loop<TElem, TFEGeom>);
    1315              :         this->set_prep_err_est_elem(id, &T::template prep_err_est_elem<TElem, TFEGeom>);
    1316              :         this->set_compute_err_est_A_elem(id, &T::template compute_err_est_A_elem<TElem, TFEGeom>);
    1317              :         this->set_compute_err_est_M_elem(id, &T::template compute_err_est_M_elem<TElem, TFEGeom>);
    1318              :         this->set_compute_err_est_rhs_elem(id, &T::template compute_err_est_rhs_elem<TElem, TFEGeom>);
    1319              :         this->set_fsh_err_est_elem_loop(id, &T::template fsh_err_est_elem_loop<TElem, TFEGeom>);
    1320              : 
    1321              : //      set computation of linearized defect w.r.t velocity
    1322            0 :         m_imDiffusion.          set_fct(id, this, &T::template lin_def_diffusion<TElem, TFEGeom>);
    1323            0 :         m_imVelocity.           set_fct(id, this, &T::template lin_def_velocity<TElem, TFEGeom>);
    1324            0 :         m_imFlux.                       set_fct(id, this, &T::template lin_def_flux<TElem, TFEGeom>);
    1325            0 :         m_imReactionRate.       set_fct(id, this, &T::template lin_def_reaction_rate<TElem, TFEGeom>);
    1326            0 :         m_imReaction.           set_fct(id, this, &T::template lin_def_reaction<TElem, TFEGeom>);
    1327            0 :         m_imSource.                     set_fct(id, this, &T::template lin_def_source<TElem, TFEGeom>);
    1328            0 :         m_imVectorSource.       set_fct(id, this, &T::template lin_def_vector_source<TElem, TFEGeom>);
    1329            0 :         m_imMassScale.          set_fct(id, this, &T::template lin_def_mass_scale<TElem, TFEGeom>);
    1330            0 :         m_imMass.                       set_fct(id, this, &T::template lin_def_mass<TElem, TFEGeom>);
    1331              : 
    1332              : //      exports
    1333            0 :         m_exValue->  template set_fct<T,refDim>(id, this, &T::template ex_value<TElem, TFEGeom>);
    1334            0 :         m_exGrad->   template set_fct<T,refDim>(id, this, &T::template ex_grad<TElem, TFEGeom>);
    1335            0 : }
    1336              : 
    1337              : ////////////////////////////////////////////////////////////////////////////////
    1338              : //      explicit template instantiations
    1339              : ////////////////////////////////////////////////////////////////////////////////
    1340              : 
    1341              : #ifdef UG_DIM_1
    1342              : template class ConvectionDiffusionFE<Domain1d>;
    1343              : #endif
    1344              : #ifdef UG_DIM_2
    1345              : template class ConvectionDiffusionFE<Domain2d>;
    1346              : #endif
    1347              : #ifdef UG_DIM_3
    1348              : template class ConvectionDiffusionFE<Domain3d>;
    1349              : #endif
    1350              : 
    1351              : } // end namespace ConvectionDiffusionPlugin
    1352              : } // namespace ug
    1353              : 
        

Generated by: LCOV version 2.0-1