LCOV - code coverage report
Current view: top level - ugbase/lib_disc/spatial_disc/elem_disc/neumann_boundary/fv1 - neumann_boundary_fv1.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 222 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 153 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2013-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 "neumann_boundary_fv1.h"
      34              : #include "lib_disc/spatial_disc/disc_util/fv1_geom.h"
      35              : #include "lib_disc/spatial_disc/disc_util/geom_provider.h"
      36              : 
      37              : namespace ug{
      38              : 
      39              : 
      40              : ////////////////////////////////////////////////////////////////////////////////
      41              : //      Constructor
      42              : ////////////////////////////////////////////////////////////////////////////////
      43              : 
      44              : template<typename TDomain>
      45            0 : NeumannBoundaryFV1<TDomain>::NeumannBoundaryFV1(const char* function)
      46            0 :  :NeumannBoundaryBase<TDomain>(function)
      47              : {
      48            0 :         register_all_funcs(false);
      49            0 : }
      50              : 
      51              : template<typename TDomain>
      52            0 : void NeumannBoundaryFV1<TDomain>::
      53              : prepare_setting(const std::vector<LFEID>& vLfeID, bool bNonRegularGrid)
      54              : {
      55            0 :         UG_COND_THROW(bNonRegularGrid && (TDomain::dim == 3),
      56              :                                   "NeumannBoundaryFV1: Hanging Nodes not implemented.");
      57              : 
      58            0 :         if(vLfeID.size() != 1)
      59            0 :                 UG_THROW("NeumannBoundary: Need exactly 1 function.");
      60              : 
      61            0 :         if(vLfeID[0].order() != 1 || vLfeID[0].type() != LFEID::LAGRANGE)
      62            0 :                 UG_THROW("NeumannBoundary: FV Scheme only implemented for 1st order Lagrange.");
      63            0 : }
      64              : 
      65              : template<typename TDomain>
      66            0 : void NeumannBoundaryFV1<TDomain>::
      67              : add(SmartPtr<CplUserData<number, dim> > data, const char* BndSubsets, const char* InnerSubsets)
      68              : {
      69            0 :         m_vNumberData.push_back(NumberData(data, BndSubsets, InnerSubsets));
      70            0 :         this->add_inner_subsets(InnerSubsets);
      71            0 : }
      72              : 
      73              : template<typename TDomain>
      74            0 : void NeumannBoundaryFV1<TDomain>::
      75              : add(SmartPtr<CplUserData<number, dim, bool> > user, const char* BndSubsets, const char* InnerSubsets)
      76              : {
      77            0 :         m_vBNDNumberData.push_back(BNDNumberData(user, BndSubsets, InnerSubsets));
      78            0 :         this->add_inner_subsets(InnerSubsets);
      79            0 : }
      80              : 
      81              : template<typename TDomain>
      82            0 : void NeumannBoundaryFV1<TDomain>::
      83              : add(SmartPtr<CplUserData<MathVector<dim>, dim> > user, const char* BndSubsets, const char* InnerSubsets)
      84              : {
      85            0 :         m_vVectorData.push_back(VectorData(user, BndSubsets, InnerSubsets));
      86            0 :         this->add_inner_subsets(InnerSubsets);
      87            0 : }
      88              : 
      89              : template<typename TDomain>
      90            0 : void NeumannBoundaryFV1<TDomain>::update_subset_groups()
      91              : {
      92            0 :         for(size_t i = 0; i < m_vNumberData.size(); ++i)
      93            0 :                 update_subset_groups(m_vNumberData[i]);
      94            0 :         for(size_t i = 0; i < m_vBNDNumberData.size(); ++i)
      95            0 :                 update_subset_groups(m_vBNDNumberData[i]);
      96            0 :         for(size_t i = 0; i < m_vVectorData.size(); ++i)
      97            0 :                 update_subset_groups(m_vVectorData[i]);
      98            0 : }
      99              : 
     100              : ////////////////////////////////////////////////////////////////////////////////
     101              : //      assembling functions
     102              : ////////////////////////////////////////////////////////////////////////////////
     103              : 
     104              : template<typename TDomain>
     105              : template<typename TElem, typename TFVGeom>
     106            0 : void NeumannBoundaryFV1<TDomain>::
     107              : prep_elem_loop(const ReferenceObjectID roid, const int si)
     108              : {
     109            0 :         update_subset_groups();
     110            0 :         m_si = si;
     111              : 
     112              : //      register subsetIndex at Geometry
     113            0 :         static TFVGeom& geo = GeomProvider<TFVGeom >::get();
     114              : 
     115              : //      request subset indices as boundary subset. This will force the
     116              : //      creation of boundary subsets when calling geo.update
     117              : 
     118            0 :         for(size_t i = 0; i < m_vNumberData.size(); ++i){
     119            0 :                 if(!m_vNumberData[i].InnerSSGrp.contains(m_si)) continue;
     120            0 :                 for(size_t s = 0; s < m_vNumberData[i].BndSSGrp.size(); ++s){
     121              :                         const int si = m_vNumberData[i].BndSSGrp[s];
     122            0 :                         geo.add_boundary_subset(si);
     123              :                 }
     124              :         }
     125            0 :         for(size_t i = 0; i < m_vBNDNumberData.size(); ++i){
     126            0 :                 if(!m_vBNDNumberData[i].InnerSSGrp.contains(m_si)) continue;
     127            0 :                 for(size_t s = 0; s < m_vBNDNumberData[i].BndSSGrp.size(); ++s){
     128              :                         const int si = m_vBNDNumberData[i].BndSSGrp[s];
     129            0 :                         geo.add_boundary_subset(si);
     130              :                 }
     131              :         }
     132            0 :         for(size_t i = 0; i < m_vVectorData.size(); ++i){
     133            0 :                 if(!m_vVectorData[i].InnerSSGrp.contains(m_si)) continue;
     134            0 :                 for(size_t s = 0; s < m_vVectorData[i].BndSSGrp.size(); ++s){
     135              :                         const int si = m_vVectorData[i].BndSSGrp[s];
     136            0 :                         geo.add_boundary_subset(si);
     137              :                 }
     138              :         }
     139              : 
     140              : //      clear imports, since we will set them afterwards
     141              :         this->clear_imports();
     142              : 
     143              :         ReferenceObjectID id = geometry_traits<TElem>::REFERENCE_OBJECT_ID;
     144              : 
     145              : //      set lin defect fct for imports
     146            0 :         for(size_t data = 0; data < m_vNumberData.size(); ++data)
     147              :         {
     148            0 :                 if(!m_vNumberData[data].InnerSSGrp.contains(m_si)) continue;
     149            0 :                 m_vNumberData[data].import.set_fct(id,
     150              :                                                    &m_vNumberData[data],
     151              :                                                    &NumberData::template lin_def<TElem, TFVGeom>);
     152              : 
     153            0 :                 this->register_import(m_vNumberData[data].import);
     154              :                 m_vNumberData[data].import.set_rhs_part();
     155              :         }
     156            0 : }
     157              : 
     158              : template<typename TDomain>
     159              : template<typename TElem, typename TFVGeom>
     160            0 : void NeumannBoundaryFV1<TDomain>::
     161              : prep_elem(const LocalVector& u, GridObject* elem, const ReferenceObjectID roid, const MathVector<dim> vCornerCoords[])
     162              : {
     163              : //  update Geometry for this element
     164            0 :         static TFVGeom& geo = GeomProvider<TFVGeom >::get();
     165              :         try{
     166            0 :                 geo.update(elem, vCornerCoords, &(this->subset_handler()));
     167              :         }
     168            0 :         UG_CATCH_THROW("NeumannBoundaryFV1::prep_elem: "
     169              :                                                 "Cannot update Finite Volume Geometry.");
     170              : 
     171            0 :         for(size_t i = 0; i < m_vNumberData.size(); ++i)
     172            0 :                 if(m_vNumberData[i].InnerSSGrp.contains(m_si))
     173            0 :                         m_vNumberData[i].template extract_bip<TElem, TFVGeom>(geo);
     174            0 : }
     175              : 
     176              : template<typename TDomain>
     177              : template<typename TElem, typename TFVGeom>
     178            0 : void NeumannBoundaryFV1<TDomain>::
     179              : add_rhs_elem(LocalVector& d, GridObject* elem, const MathVector<dim> vCornerCoords[])
     180              : {
     181            0 :         const static TFVGeom& geo = GeomProvider<TFVGeom >::get();
     182              :         typedef typename TFVGeom::BF BF;
     183              : 
     184              : //      Number Data
     185            0 :         for(size_t data = 0; data < m_vNumberData.size(); ++data){
     186            0 :                 if(!m_vNumberData[data].InnerSSGrp.contains(m_si)) continue;
     187              :                 size_t ip = 0;
     188            0 :                 for(size_t s = 0; s < m_vNumberData[data].BndSSGrp.size(); ++s){
     189              :                         const int si = m_vNumberData[data].BndSSGrp[s];
     190            0 :                         const std::vector<BF>& vBF = geo.bf(si);
     191              : 
     192            0 :                         for(size_t i = 0; i < vBF.size(); ++i, ++ip){
     193            0 :                                 const int co = vBF[i].node_id();
     194            0 :                                 d(_C_, co) -= m_vNumberData[data].import[ip]
     195            0 :                                                                     * vBF[i].volume();
     196              :                         }
     197              :                 }
     198              :         }
     199              : 
     200              : //      conditional Number Data
     201            0 :         for(size_t data = 0; data < m_vBNDNumberData.size(); ++data){
     202            0 :                 if(!m_vBNDNumberData[data].InnerSSGrp.contains(m_si)) continue;
     203            0 :                 for(size_t s = 0; s < m_vBNDNumberData[data].BndSSGrp.size(); ++s)   {
     204              :                         const int si = m_vBNDNumberData[data].BndSSGrp[s];
     205            0 :                         const std::vector<BF>& vBF = geo.bf(si);
     206              : 
     207            0 :                         for(size_t i = 0; i < vBF.size(); ++i){
     208            0 :                                 number val = 0.0;
     209            0 :                                 if(!(*m_vBNDNumberData[data].functor)(val, vBF[i].global_ip(), this->time(), si))
     210            0 :                                         continue;
     211              : 
     212            0 :                                 const int co = vBF[i].node_id();
     213            0 :                                 d(_C_, co) -= val * vBF[i].volume();
     214              :                         }
     215              :                 }
     216              :         }
     217              : 
     218              : //      vector data
     219            0 :         for(size_t data = 0; data < m_vVectorData.size(); ++data){
     220            0 :                 if(!m_vVectorData[data].InnerSSGrp.contains(m_si)) continue;
     221            0 :                 for(size_t s = 0; s < m_vVectorData[data].BndSSGrp.size(); ++s){
     222              :                         const int si = m_vVectorData[data].BndSSGrp[s];
     223            0 :                         const std::vector<BF>& vBF = geo.bf(si);
     224              : 
     225            0 :                         for(size_t i = 0; i < vBF.size(); ++i){
     226              :                                 MathVector<dim> val;
     227            0 :                                 (*m_vVectorData[data].functor)(val, vBF[i].global_ip(), this->time(), si);
     228              : 
     229            0 :                                 const int co = vBF[i].node_id();
     230            0 :                                 d(_C_, co) -= VecDot(val, vBF[i].normal());
     231              :                         }
     232              :                 }
     233              :         }
     234            0 : }
     235              : 
     236              : template<typename TDomain>
     237              : template<typename TElem, typename TGeom>
     238            0 : void NeumannBoundaryFV1<TDomain>::
     239              : fsh_elem_loop()
     240              : {
     241              : //      remove subsetIndex from Geometry
     242            0 :         static TGeom& geo = GeomProvider<TGeom >::get();
     243              : 
     244              : 
     245              : //      unrequest subset indices as boundary subset. This will force the
     246              : //      creation of boundary subsets when calling geo.update
     247              : 
     248            0 :         for(size_t i = 0; i < m_vNumberData.size(); ++i){
     249            0 :                 if(!m_vNumberData[i].InnerSSGrp.contains(m_si)) continue;
     250            0 :                 for(size_t s = 0; s < m_vNumberData[i].BndSSGrp.size(); ++s){
     251              :                         const int si = m_vNumberData[i].BndSSGrp[s];
     252            0 :                         geo.remove_boundary_subset(si);
     253            0 :                         geo.reset_curr_elem();
     254              :                 }
     255              :         }
     256              : 
     257            0 :         for(size_t i = 0; i < m_vBNDNumberData.size(); ++i){
     258            0 :                 if(!m_vBNDNumberData[i].InnerSSGrp.contains(m_si)) continue;
     259            0 :                 for(size_t s = 0; s < m_vBNDNumberData[i].BndSSGrp.size(); ++s){
     260              :                         const int si = m_vBNDNumberData[i].BndSSGrp[s];
     261            0 :                         geo.remove_boundary_subset(si);
     262            0 :                         geo.reset_curr_elem();
     263              :                 }
     264              :         }
     265              : 
     266            0 :         for(size_t i = 0; i < m_vVectorData.size(); ++i){
     267            0 :                 if(!m_vVectorData[i].InnerSSGrp.contains(m_si)) continue;
     268            0 :                 for(size_t s = 0; s < m_vVectorData[i].BndSSGrp.size(); ++s){
     269              :                         const int si = m_vVectorData[i].BndSSGrp[s];
     270            0 :                         geo.remove_boundary_subset(si);
     271            0 :                         geo.reset_curr_elem();
     272              :                 }
     273              :         }
     274            0 : }
     275              : 
     276              : 
     277              : ///////////////////////////////////////////////////////////////////////////////////////////////////
     278              : //   error estimation (begin)                                                                                                                                    //
     279              : 
     280              : //      prepares the loop over all elements of one type for the computation of the error estimator
     281              : template<typename TDomain>
     282              : template <typename TElem, typename TFVGeom>
     283            0 : void NeumannBoundaryFV1<TDomain>::
     284              : prep_err_est_elem_loop(const ReferenceObjectID roid, const int si)
     285              : {
     286              :         //      get the error estimator data object and check that it is of the right type
     287              :         //      we check this at this point in order to be able to dispense with this check later on
     288              :         //      (i.e. in prep_err_est_elem and compute_err_est_A_elem())
     289            0 :         if (this->m_spErrEstData.get() == NULL)
     290              :         {
     291            0 :                 UG_THROW("No ErrEstData object has been given to this ElemDisc!");
     292              :         }
     293              : 
     294            0 :         err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get());
     295              : 
     296            0 :         if (!err_est_data)
     297              :         {
     298            0 :                 UG_THROW("Dynamic cast to SideAndElemErrEstData failed."
     299              :                                 << std::endl << "Make sure you handed the correct type of ErrEstData to this discretization.");
     300              :         }
     301              : 
     302            0 :         update_subset_groups();
     303            0 :         m_si = si;
     304              : 
     305              : //      clear imports, since we will set them now
     306              :         this->clear_imports();
     307              : 
     308              :         ReferenceObjectID id = geometry_traits<TElem>::REFERENCE_OBJECT_ID;
     309              : 
     310              : //      set lin defect fct for imports
     311            0 :         for (size_t data = 0; data < m_vNumberData.size(); ++data)
     312              :         {
     313            0 :                 if (!m_vNumberData[data].InnerSSGrp.contains(m_si)) continue;
     314            0 :                 m_vNumberData[data].import.set_fct(id,
     315              :                                                                                    &m_vNumberData[data],
     316              :                                                                                    &NumberData::template lin_def<TElem, TFVGeom>);
     317              : 
     318            0 :                 this->register_import(m_vNumberData[data].import);
     319              :                 m_vNumberData[data].import.set_rhs_part();
     320              :         }
     321              : 
     322              : // get local IPs for imports
     323              :         static const int refDim = TElem::dim;
     324              : 
     325              :         size_t numSideIPs;
     326              :         const MathVector<refDim>* sideIPs;
     327              :         try
     328              :         {
     329              :                 numSideIPs = err_est_data->num_all_side_ips(roid);
     330            0 :                 sideIPs = err_est_data->template side_local_ips<refDim>(roid);
     331              : 
     332            0 :                 if (!sideIPs) return;   // is NULL if TElem is not of the same dim as TDomain
     333              :         }
     334            0 :         UG_CATCH_THROW("Integration points for error estimator cannot be set.");
     335              : 
     336            0 :         for (size_t i = 0; i < m_vNumberData.size(); ++i)
     337              :         {
     338            0 :                 if (m_vNumberData[i].InnerSSGrp.contains(m_si))
     339              :                         m_vNumberData[i].template set_local_ips<refDim>(sideIPs, numSideIPs);
     340              :         }
     341              : };
     342              : 
     343              : template<typename TDomain>
     344              : template<typename TElem, typename TFVGeom>
     345            0 : void NeumannBoundaryFV1<TDomain>::
     346              : prep_err_est_elem(const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[])
     347              : {
     348              : // get global IPs for imports
     349              :         size_t numSideIPs;
     350              :         MathVector<dim>* sideIPs;
     351              : 
     352              :         try
     353              :         {
     354            0 :                 err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get());
     355              : 
     356            0 :                 numSideIPs = err_est_data->num_all_side_ips(elem->reference_object_id());
     357            0 :                 sideIPs = err_est_data->all_side_global_ips(elem, vCornerCoords);
     358              :         }
     359            0 :         UG_CATCH_THROW("Global integration points for error estimator cannot be set.");
     360              : 
     361              : 
     362            0 :         for (size_t i = 0; i < m_vNumberData.size(); ++i)
     363              :         {
     364            0 :                 if (m_vNumberData[i].InnerSSGrp.contains(m_si))
     365              :                         m_vNumberData[i].set_global_ips(&sideIPs[0], numSideIPs);
     366              :         }
     367            0 : }
     368              : 
     369              : //      computes the error estimator contribution for one element
     370              : template<typename TDomain>
     371              : template <typename TElem, typename TFVGeom>
     372            0 : void NeumannBoundaryFV1<TDomain>::
     373              : compute_err_est_rhs_elem(GridObject* elem, const MathVector<dim> vCornerCoords[], const number& scale)
     374              : {
     375              :         typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
     376              : 
     377            0 :         err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get());
     378              : 
     379            0 :         if (err_est_data->surface_view().get() == NULL) {UG_THROW("Error estimator has NULL surface view.");}
     380            0 :         MultiGrid* pErrEstGrid = (MultiGrid*) (err_est_data->surface_view()->subset_handler()->multi_grid());
     381              : 
     382              : //      get the sides of the element
     383              :         typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::side_type>::secure_container side_list;
     384            0 :         pErrEstGrid->associated_elements_sorted(side_list, (TElem*) elem);
     385            0 :         if (side_list.size() != (size_t) ref_elem_type::numSides)
     386            0 :                 UG_THROW ("Mismatch of numbers of sides in 'ConvectionDiffusionFV1::compute_err_est_elem'");
     387              : 
     388              :         //      Number Data
     389            0 :         for (size_t data = 0; data < m_vNumberData.size(); ++data)
     390              :         {
     391            0 :                 if (!m_vNumberData[data].InnerSSGrp.contains(m_si)) continue;
     392              : 
     393              :                 // loop sides
     394            0 :                 for (size_t side = 0; side < side_list.size(); side++)
     395              :                 {
     396            0 :                         for (size_t ss = 0; ss < m_vNumberData[data].BndSSGrp.size(); ss++)
     397              :                         {
     398              :                                 // is the bnd cond subset index the same as the current side's?
     399            0 :                                 if (err_est_data->surface_view()->subset_handler()->get_subset_index(side_list[side])
     400            0 :                                         != m_vNumberData[data].BndSSGrp[ss]) continue;
     401              : 
     402            0 :                                 const size_t ipIndexStart = err_est_data->first_side_ips(elem->reference_object_id(), side);
     403              : 
     404            0 :                                 for (size_t sip = 0; sip < err_est_data->num_side_ips(side_list[side]); sip++)
     405              :                                 {
     406            0 :                                         size_t ip = ipIndexStart + sip;
     407              :                                         // sign must be negative, since the data represents efflux
     408            0 :                                         (*err_est_data)(side_list[side],sip) -= scale * m_vNumberData[data].import[ip];
     409              :                                 }
     410              :                         }
     411              :                 }
     412              :         }
     413              : 
     414              :         // store global side IPs
     415            0 :         ReferenceObjectID roid = elem->reference_object_id();
     416            0 :         MathVector<dim>* glob_ips = err_est_data->all_side_global_ips(elem, vCornerCoords);
     417              : 
     418              :         //      conditional Number Data
     419            0 :         for (size_t data = 0; data < m_vBNDNumberData.size(); ++data)
     420              :         {
     421            0 :                 if (!m_vBNDNumberData[data].InnerSSGrp.contains(m_si)) continue;
     422              : 
     423              :                 // loop sides
     424            0 :                 for (size_t side = 0; side < side_list.size(); side++)
     425              :                 {
     426            0 :                         for (size_t ss = 0; ss < m_vBNDNumberData[data].BndSSGrp.size(); ss++)
     427              :                         {
     428              :                                 // is the bnd cond subset index the same as the current side's?
     429            0 :                                 if (err_est_data->surface_view()->subset_handler()->get_subset_index(side_list[side])
     430            0 :                                         != m_vBNDNumberData[data].BndSSGrp[ss]) continue;
     431              : 
     432              :                                 int si = m_vBNDNumberData[data].BndSSGrp[ss];
     433              : 
     434              :                                 const size_t ipIndexStart = err_est_data->first_side_ips(roid, side);
     435              : 
     436            0 :                                 for (size_t sip = 0; sip < err_est_data->num_side_ips(side_list[side]); sip++)
     437              :                                 {
     438            0 :                                         size_t ip = ipIndexStart + sip;
     439            0 :                                         number val = 0.0;
     440            0 :                                         if (!(*m_vBNDNumberData[data].functor)(val, glob_ips[ip], this->time(), si)) continue;
     441              : 
     442              :                                         // sign must be negative, since the data represents efflux
     443            0 :                                         (*err_est_data)(side_list[side],sip) -= scale * val;
     444              :                                 }
     445              :                         }
     446              :                 }
     447              :         }
     448              : 
     449              :         //      vector data
     450            0 :         for (size_t data = 0; data < m_vVectorData.size(); ++data)
     451              :         {
     452            0 :                 if (!m_vVectorData[data].InnerSSGrp.contains(m_si)) continue;
     453              : 
     454              :                 // loop sides
     455            0 :                 for (size_t side = 0; side < side_list.size(); side++)
     456              :                 {
     457              :                         MathVector<dim> fd, normal;
     458              : 
     459              :                         // normal on side
     460            0 :                         SideNormal<ref_elem_type,dim>(normal, side, vCornerCoords);
     461            0 :                         VecNormalize(normal, normal);
     462              : 
     463            0 :                         for (size_t ss = 0; ss < m_vVectorData[data].BndSSGrp.size(); ss++)
     464              :                         {
     465              :                                 // is the bnd cond subset index the same as the current side's?
     466            0 :                                 if (err_est_data->surface_view()->subset_handler()->get_subset_index(side_list[side])
     467            0 :                                         != m_vVectorData[data].BndSSGrp[ss]) continue;
     468              : 
     469              :                                 int si = m_vBNDNumberData[data].BndSSGrp[ss];
     470              : 
     471              :                                 const size_t ipIndexStart = err_est_data->first_side_ips(roid, side);
     472              : 
     473            0 :                                 for (size_t sip = 0; sip < err_est_data->num_side_ips(side_list[side]); sip++)
     474              :                                 {
     475            0 :                                         size_t ip = ipIndexStart + sip;
     476            0 :                                         (*m_vVectorData[data].functor)(fd, glob_ips[ip], this->time(), si);
     477              : 
     478              :                                         // sign must be negative, since the data represents efflux
     479            0 :                                         (*err_est_data)(side_list[side],sip) -= scale * VecDot(fd, normal);
     480              :                                 }
     481              :                         }
     482              :                 }
     483              :         }
     484            0 : }
     485              : 
     486              : //      postprocesses the loop over all elements of one type in the computation of the error estimator
     487              : template<typename TDomain>
     488              : template <typename TElem, typename TFVGeom>
     489            0 : void NeumannBoundaryFV1<TDomain>::
     490              : fsh_err_est_elem_loop()
     491              : {
     492              :         // finish the element loop in the same way as the actual discretization
     493            0 :         this->template fsh_elem_loop<TElem, TFVGeom> ();
     494            0 : }
     495              : 
     496              : //   error estimation (end)                                                                                                                                      //
     497              : ///////////////////////////////////////////////////////////////////////////////////////////////////
     498              : 
     499              : 
     500              : ////////////////////////////////////////////////////////////////////////////////
     501              : // Number Data
     502              : ////////////////////////////////////////////////////////////////////////////////
     503              : 
     504              : 
     505              : template<typename TDomain>
     506              : template<typename TElem, typename TFVGeom>
     507            0 : void NeumannBoundaryFV1<TDomain>::NumberData::
     508              : lin_def(const LocalVector& u,
     509              :             std::vector<std::vector<number> > vvvLinDef[],
     510              :             const size_t nip)
     511              : {
     512              : //  get finite volume geometry
     513            0 :         const static TFVGeom& geo = GeomProvider<TFVGeom>::get();
     514              :         typedef typename TFVGeom::BF BF;
     515              : 
     516            0 :         for(size_t s = 0; s < this->BndSSGrp.size(); ++s)
     517              :         {
     518              :                 const int si = this->BndSSGrp[s];
     519            0 :                 const std::vector<BF>& vBF = geo.bf(si);
     520            0 :                 for(size_t i = 0; i < vBF.size(); ++i){
     521            0 :                         const int co = vBF[i].node_id();
     522            0 :                         vvvLinDef[i][_C_][co] -= vBF[i].volume();
     523              :                 }
     524              :         }
     525            0 : }
     526              : 
     527              : template<typename TDomain>
     528              : template<typename TElem, typename TFVGeom>
     529            0 : void NeumannBoundaryFV1<TDomain>::NumberData::
     530              : extract_bip(const TFVGeom& geo)
     531              : {
     532              :         typedef typename TFVGeom::BF BF;
     533              :         static const int locDim = TElem::dim;
     534              : 
     535              :         std::vector<MathVector<locDim> >* vLocIP = local_ips<locDim>();
     536              : 
     537              :         vLocIP->clear();
     538              :         vGloIP.clear();
     539            0 :         for(size_t s = 0; s < this->BndSSGrp.size(); s++)
     540              :         {
     541              :                 const int si = this->BndSSGrp[s];
     542              :                 const std::vector<BF>& vBF = geo.bf(si);
     543            0 :                 for(size_t i = 0; i < vBF.size(); ++i)
     544              :                 {
     545              :                         const BF& bf = vBF[i];
     546            0 :                         vLocIP->push_back(bf.local_ip());
     547            0 :                         vGloIP.push_back(bf.global_ip());
     548              :                 }
     549              :         }
     550              : 
     551              : //      either both are empty or none is empty
     552              :         UG_ASSERT((vLocIP->empty() && vGloIP.empty()) || (!(vLocIP->empty() || vGloIP.empty())),
     553              :                           "Either vLocIP and vGloIP both have to be empty or both have to be filled!");
     554              : 
     555            0 :         if(vLocIP->empty()){
     556            0 :                 import.template set_local_ips<locDim>(NULL, 0);
     557            0 :                 import.set_global_ips(NULL, 0);
     558              :         }
     559              :         else{
     560            0 :                 import.template set_local_ips<locDim>(&(*vLocIP)[0], vLocIP->size());
     561            0 :                 import.set_global_ips(&vGloIP[0], vGloIP.size());
     562              :         }
     563            0 : }
     564              : 
     565              : template<typename TDomain>
     566              : template <int refDim>
     567              : std::vector<MathVector<refDim> >* NeumannBoundaryFV1<TDomain>::NumberData::local_ips()
     568              : {
     569              :         switch (refDim)
     570              :         {
     571            0 :                 case 1: return (std::vector<MathVector<refDim> >*)(&vLocIP_dim1);
     572            0 :                 case 2: return (std::vector<MathVector<refDim> >*)(&vLocIP_dim2);
     573            0 :                 case 3: return (std::vector<MathVector<refDim> >*)(&vLocIP_dim3);
     574              :         }
     575              : }
     576              : 
     577              : ////////////////////////////////////////////////////////////////////////////////
     578              : //      register assemble functions
     579              : ////////////////////////////////////////////////////////////////////////////////
     580              : 
     581              : #ifdef UG_DIM_1
     582              : template<>
     583            0 : void NeumannBoundaryFV1<Domain1d>::register_all_funcs(bool bHang)
     584              : {
     585            0 :         register_func<RegularEdge, FV1Geometry<RegularEdge, dim> >();
     586            0 : }
     587              : #endif
     588              : 
     589              : #ifdef UG_DIM_2
     590              : template<>
     591            0 : void NeumannBoundaryFV1<Domain2d>::register_all_funcs(bool bHang)
     592              : {
     593            0 :         register_func<RegularEdge, FV1Geometry<RegularEdge, dim> >();
     594            0 :         register_func<Triangle, FV1Geometry<Triangle, dim> >();
     595            0 :         register_func<Quadrilateral, FV1Geometry<Quadrilateral, dim> >();
     596            0 : }
     597              : #endif
     598              : 
     599              : #ifdef UG_DIM_3
     600              : template<>
     601            0 : void NeumannBoundaryFV1<Domain3d>::register_all_funcs(bool bHang)
     602              : {
     603            0 :         if(!bHang){
     604            0 :                 register_func<RegularEdge, FV1Geometry<RegularEdge, dim> >();
     605            0 :                 register_func<Triangle, FV1Geometry<Triangle, dim> >();
     606            0 :                 register_func<Quadrilateral, FV1Geometry<Quadrilateral, dim> >();
     607            0 :                 register_func<Tetrahedron, FV1Geometry<Tetrahedron, dim> >();
     608            0 :                 register_func<Prism, FV1Geometry<Prism, dim> >();
     609            0 :                 register_func<Pyramid, FV1Geometry<Pyramid, dim> >();
     610            0 :                 register_func<Hexahedron, FV1Geometry<Hexahedron, dim> >();
     611            0 :                 register_func<Octahedron, FV1Geometry<Octahedron, dim> >();
     612              :         }
     613            0 :         else UG_THROW("NeumannBoundaryFV1: Hanging Nodes not implemented.");
     614            0 : }
     615              : #endif
     616              : 
     617              : template<typename TDomain>
     618              : template<typename TElem, typename TFVGeom>
     619            0 : void NeumannBoundaryFV1<TDomain>::register_func()
     620              : {
     621              :         ReferenceObjectID id = geometry_traits<TElem>::REFERENCE_OBJECT_ID;
     622              :         typedef this_type T;
     623              : 
     624              :         this->clear_add_fct(id);
     625              : 
     626              :         this->set_prep_elem_loop_fct(id, &T::template prep_elem_loop<TElem, TFVGeom>);
     627              :         this->set_prep_elem_fct(      id, &T::template prep_elem<TElem, TFVGeom>);
     628              :         this->set_add_rhs_elem_fct(   id, &T::template add_rhs_elem<TElem, TFVGeom>);
     629              :         this->set_fsh_elem_loop_fct( id, &T::template fsh_elem_loop<TElem, TFVGeom>);
     630              : 
     631              :         this->set_add_jac_A_elem_fct(         id, &T::template add_jac_A_elem<TElem, TFVGeom>);
     632              :         this->set_add_jac_M_elem_fct(         id, &T::template add_jac_M_elem<TElem, TFVGeom>);
     633              :         this->set_add_def_A_elem_fct(         id, &T::template add_def_A_elem<TElem, TFVGeom>);
     634              :         this->set_add_def_M_elem_fct(         id, &T::template add_def_M_elem<TElem, TFVGeom>);
     635              : 
     636              :         // error estimator parts
     637              :         this->set_prep_err_est_elem_loop(id, &T::template prep_err_est_elem_loop<TElem, TFVGeom>);
     638              :         this->set_prep_err_est_elem(id, &T::template prep_err_est_elem<TElem, TFVGeom>);
     639              :         this->set_compute_err_est_rhs_elem(id, &T::template compute_err_est_rhs_elem<TElem, TFVGeom>);
     640              :         this->set_fsh_err_est_elem_loop(id, &T::template fsh_err_est_elem_loop<TElem, TFVGeom>);
     641            0 : }
     642              : 
     643              : ////////////////////////////////////////////////////////////////////////////////
     644              : //      explicit template instantiations
     645              : ////////////////////////////////////////////////////////////////////////////////
     646              : 
     647              : #ifdef UG_DIM_1
     648              : template class NeumannBoundaryFV1<Domain1d>;
     649              : #endif
     650              : #ifdef UG_DIM_2
     651              : template class NeumannBoundaryFV1<Domain2d>;
     652              : #endif
     653              : #ifdef UG_DIM_3
     654              : template class NeumannBoundaryFV1<Domain3d>;
     655              : #endif
     656              : 
     657              : } // namespace ug
     658              : 
        

Generated by: LCOV version 2.0-1