• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List

/export/development/ViennaFEM/viennafem/detail/assembler.hpp

Go to the documentation of this file.
00001 #ifndef VIENNAFEM_ASSEMBLER_HPP
00002 #define VIENNAFEM_ASSEMBLER_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2012, Institute for Microelectronics,
00006                        Institute for Analysis and Scientific Computing,
00007                        TU Wien.
00008                              -----------------
00009                ViennaFEM - The Vienna Finite Element Method Library
00010                              -----------------
00011 
00012    Author:     Karl Rupp                          rupp@iue.tuwien.ac.at
00013 
00014    License:    MIT (X11), see file LICENSE in the ViennaFEM base directory
00015 ============================================================================ */
00016 
00017 //ViennaFEM includes:
00018 #include "viennafem/forwards.h"
00019 #include "viennafem/cell_quan.hpp"
00020 #include "viennafem/transform.hpp"
00021 #include "viennafem/bases/all.hpp"
00022 #include "viennafem/transform/dtdx_triangle.hpp"
00023 #include "viennafem/transform/dtdx_tetrahedron.hpp"
00024 #include "viennafem/weak_form.hpp"
00025 #include "viennafem/linear_pde_system.hpp"
00026 #include "viennafem/linear_pde_options.hpp"
00027 #include "viennafem/mapping.hpp"
00028 #include "viennafem/quadrature/quad.hpp"
00029 #include "viennafem/log/api.hpp"
00030 
00031 //ViennaMath includes:
00032 #include "viennamath/manipulation/apply_coordinate_system.hpp"
00033 #include "viennamath/runtime/numerical_quadrature.hpp"
00034 #include "viennamath/manipulation/eval.hpp"
00035 
00036 //ViennaData includes:
00037 #include "viennadata/api.hpp"
00038 
00039 //ViennaGrid includes:
00040 #include "viennagrid/domain.hpp"
00041 
00046 namespace viennafem
00047 {
00048   
00049   namespace detail
00050   {
00059     template <typename ExpressionType>
00060     std::vector<ExpressionType> make_full_function(ExpressionType const & func, std::size_t length, std::size_t index)
00061     {
00062       std::vector<ExpressionType> result(length);
00063       for (std::size_t i=0; i<length; ++i)
00064         result[i] = 0.0;
00065       
00066       result[index] = func;
00067       
00068       return result;
00069     }
00070     
00072     template <typename CellTag, typename EquationType, typename PDESystemType>
00073     std::vector< std::vector<EquationType> > make_local_weak_form(EquationType const & transformed_weak_form, PDESystemType const & pde_system)
00074     {
00075       typedef typename EquationType::value_type      Expression;
00076       typedef typename Expression::interface_type    InterfaceType;
00077       typedef typename reference_cell_for_basis<CellTag, viennafem::lagrange_tag<1> >::type    ReferenceCell;
00078       
00079 
00080       //test functions:
00081       std::vector<Expression> scalar_test_functions = viennafem::basis_factory<InterfaceType>::get(pde_system.option(0).test_space_id(), ReferenceCell());
00082       for (std::size_t i = 0; i<scalar_test_functions.size(); ++i)
00083         std::cout << "Test function " << i << ": " << scalar_test_functions[i] << std::endl;
00084       
00085       std::size_t local_size_i = pde_system.unknown(0).size() * scalar_test_functions.size();
00086 
00087       //std::cout << "Test functions: " << std::endl;
00088       std::vector< std::vector<Expression> > full_test_functions(local_size_i);
00089       std::size_t current_index = 0;
00090       for (std::size_t i=0; i<scalar_test_functions.size(); ++i)
00091       {
00092         for (std::size_t j=0; j<pde_system.unknown(0).size(); ++j)
00093         {  
00094           //std::cout << "No. " << current_index << ": ";
00095           full_test_functions[current_index++] = make_full_function(scalar_test_functions[i], pde_system.unknown(0).size(), j);
00096         }
00097         //std::cout << std::endl;
00098       }
00099 
00100       //trial functions:
00101       std::vector<Expression> scalar_trial_functions = viennafem::basis_factory<InterfaceType>::get(pde_system.option(0).trial_space_id(), ReferenceCell());
00102       std::size_t local_size_j = pde_system.unknown(0).size() * scalar_trial_functions.size();
00103         
00104       //std::cout << "Trial functions: " << std::endl;
00105       std::vector< std::vector<Expression> > full_trial_functions(local_size_i);
00106       current_index = 0;
00107       for (std::size_t i=0; i<scalar_trial_functions.size(); ++i)
00108       {
00109         //std::cout << "No. i: ";
00110         for (std::size_t j=0; j<pde_system.unknown(0).size(); ++j)
00111         {  
00112           //std::cout << "No. " << current_index << ": ";
00113           full_trial_functions[current_index++] = make_full_function(scalar_trial_functions[i], pde_system.unknown(0).size(), j);
00114         }
00115         //std::cout << std::endl;
00116       }
00117 
00118       // a bit of logging:
00119       log_test_and_trial_space(scalar_test_functions,
00120                               scalar_trial_functions,
00121                               pde_system);
00122 
00123       //plug functions into weak form to obtain local form:
00124       //local_size_i = 3;
00125       //local_size_j = 3;
00126       
00127       std::vector<std::vector< EquationType > >  local_weak_form(local_size_i);
00128       for (std::size_t i=0; i<local_size_i; ++i)
00129         local_weak_form[i].resize(local_size_j);
00130       
00131       for (std::size_t i = 0; i<local_size_i; ++i)
00132       {
00133         for (std::size_t j = 0; j<local_size_j; ++j)
00134         {
00135           local_weak_form[i][j] = viennafem::insert_test_and_trial_functions( transformed_weak_form,
00136                                                                               pde_system,
00137                                                                               full_test_functions[i],
00138                                                                               full_trial_functions[j]);
00139         }
00140       }
00141       
00142       return local_weak_form;    
00143     }
00144     
00146     template <typename CellType, typename InterfaceType>
00147     struct cell_updater : public viennamath::rt_traversal_interface<>
00148     {
00149       public:
00150         cell_updater(CellType const & cell) : cell_(cell) {}
00151         
00152         void operator()(InterfaceType const * e) const 
00153         {
00154           if (viennamath::callback_if_castable< viennafem::cell_quan<CellType, InterfaceType> >::apply(e, *this))
00155             return;
00156         }
00157         
00158         void operator()(viennafem::cell_quan<CellType, InterfaceType> const & cq) const
00159         {
00160           cq.update(cell_);
00161           //std::cout << "cell_quan updated!" << std::endl;
00162         }
00163         
00164       private:
00165         CellType const & cell_;
00166     };
00167 
00169     template <typename T>
00170     bool is_uniform_basis(T const &) { return true; }   //TODO: Extend
00171     
00173     struct pde_assembler_internal
00174     {
00175       
00176       template <typename EquationType, typename PDESystemType, typename DomainType, typename LinearSystemT>
00177       void operator()(EquationType const & transformed_weak_form,
00178                       PDESystemType const & pde_system,
00179                       DomainType & domain,
00180                       LinearSystemT & linear_system
00181                     ) const
00182       {
00183         typedef typename DomainType::config_type              Config;
00184         typedef typename Config::cell_tag                     CellTag;
00185         
00186         typedef typename viennagrid::result_of::point<Config>::type                            PointType;
00187         typedef typename viennagrid::result_of::ncell<Config, CellTag::dim>::type              CellType;
00188 
00189         typedef typename viennagrid::result_of::ncell_range<DomainType, 0>::type               VertexContainer;
00190         typedef typename viennagrid::result_of::iterator<VertexContainer>::type                VertexIterator;
00191 
00192         typedef typename viennagrid::result_of::ncell_range<DomainType, CellTag::dim>::type    CellContainer;
00193         typedef typename viennagrid::result_of::iterator<CellContainer>::type                  CellIterator;
00194 
00195         typedef typename viennagrid::result_of::ncell_range<CellType, 0>::type                 VertexOnCellContainer;
00196         typedef typename viennagrid::result_of::iterator<VertexOnCellContainer>::type          VertexOnCellIterator;
00197 
00198         typedef typename PDESystemType::boundary_key_type  BoundaryKeyType;
00199         typedef std::vector<long>                          MappingContainer;
00200         
00201         typedef typename EquationType::value_type          Expression;
00202         
00203         BoundaryKeyType bnd_key(pde_system.option(0).data_id());
00204         
00205       #ifdef VIENNAFEM_DEBUG
00206         std::cout << "ViennaFEM: pde_assembler_internal(): Number of components: " << pde_system.unknown(0).size() << std::endl;
00207       #endif
00208 
00209         
00210         //Set up element representations:
00211         std::vector<std::vector< EquationType > > local_weak_form;
00212         bool basis_is_uniform = is_uniform_basis(pde_system);
00213         
00214         if (basis_is_uniform)
00215         {
00216           //std::cout << "Using globally uniform basis";
00217           local_weak_form = make_local_weak_form<CellTag>(transformed_weak_form, pde_system);
00218         }
00219             
00220         //Integrator setup:
00221         
00222         viennamath::numerical_quadrature integrator = viennafem::make_quadrature_rule(pde_system, domain);
00223         //viennamath::numerical_quadrature integrator(new viennafem::rt_gauss_quad_element<ReferenceCell, 3, typename EquationType::interface_type>());
00224         
00225         CellContainer cells = viennagrid::ncells<CellTag::dim>(domain);
00226         for (CellIterator cell_iter = cells.begin();
00227             cell_iter != cells.end();
00228             ++cell_iter)
00229         {
00230           //if (!basis_is_uniform)
00231           //  local_weak_form = make_local_weak_form(transformed_weak_form, pde_system, *cell_iter);
00232           
00233           //update cell_quantities:
00234           //std::cout << "Updating cell quantities..." << std::endl;
00235           viennamath::rt_traversal_wrapper<> updater( new cell_updater<CellType, typename EquationType::interface_type>(*cell_iter) );
00236           
00237           //write back to global matrix:
00238           long global_index_i = 0;
00239           long global_index_j = 0;
00240           long local_index_i = 0;
00241           long local_index_j = 0;
00242 
00243           MappingContainer map_indices_i = mapping_indices(pde_system, *cell_iter, 0);
00244           MappingContainer map_indices_j = mapping_indices(pde_system, *cell_iter, 0);
00245           
00246           for (typename MappingContainer::const_iterator map_iter_i = map_indices_i.begin();
00247               map_iter_i != map_indices_i.end();
00248               ++map_iter_i, ++local_index_i)
00249           {                  
00250             global_index_i = *map_iter_i;
00251             //std::cout << "glob_i: " << global_index_i << std::endl;
00252             
00253             if (global_index_i == -1) // This is a Dirichlet node -> skip
00254               continue;
00255             
00256             VertexOnCellContainer vertices_on_cell = viennagrid::ncells<0>(*cell_iter);
00257             VertexOnCellIterator vocit = vertices_on_cell.begin();
00258             local_index_j = 0;
00259             for (typename MappingContainer::const_iterator map_iter_j = map_indices_j.begin();
00260                 map_iter_j != map_indices_j.end();
00261                 ++map_iter_j, ++local_index_j)
00262             {
00263               if ( (local_index_j % pde_system.unknown(0).size()) == 0 && (local_index_j > 0) )
00264                   ++vocit;
00265               
00266               local_weak_form[local_index_i][local_index_j].lhs().get()->recursive_traversal(updater);
00267               global_index_j = *map_iter_j;
00268               
00269 
00270               if (global_index_j == -1) // Dirichlet boundary
00271               {
00272                 if (pde_system.unknown(0).size() == 1) //scalar valued unknowns
00273                 {
00274                   linear_system(global_index_i) -=
00275                     viennadata::access<BoundaryKeyType, double>(bnd_key)(*vocit) //TODO: Better encapsulate boundary value access
00276                     * integrator(local_weak_form[local_index_i][local_index_j].lhs());
00277                 }
00278                 else //vector valued unknowns
00279                 {
00280                   //TODO: Better encapsulate boundary value access
00281                   std::vector<double> const & bnd_values = viennadata::access<BoundaryKeyType, std::vector<double> >(bnd_key)(*vocit);
00282                   
00283                   if (bnd_values.size() > 1) //allow homogeneous case without having the data vector initialized
00284                   {
00285                     linear_system(global_index_i) -=
00286                       bnd_values[local_index_j % pde_system.unknown(0).size()] 
00287                       * integrator(local_weak_form[local_index_i][local_index_j].lhs());
00288                   }
00289                 }
00290               }
00291               else
00292               {
00293                 //std::cout << " Evaluating LHS: " << local_weak_form[local_index_i][local_index_j].lhs() << std::endl;
00294                 //std::cout << "Adding to (" << global_index_i << ", " << global_index_j << "): " << integrator(local_weak_form[local_index_i][local_index_j].lhs()) << std::endl;
00295                 linear_system.add(
00296                     global_index_i, 
00297                     global_index_j, 
00298                     integrator(local_weak_form[local_index_i][local_index_j].lhs())
00299                 );
00300               }
00301             }
00302             
00303             local_weak_form[local_index_i][0].rhs().get()->recursive_traversal(updater);
00304             
00305             //std::cout << "Evaluating RHS: " << local_weak_form[local_index_i][0].rhs() << std::endl;
00306             
00307             linear_system(global_index_i) += integrator(local_weak_form[local_index_i][0].rhs());
00308           }
00309         }
00310         
00311       } //operator()
00312       
00313     };
00314   
00315   } //namespace detail
00316 }
00317 #endif

Generated on Wed Feb 29 2012 21:51:05 for ViennaFEM - The Vienna Finite Element Method Library by  doxygen 1.7.1