Go to the documentation of this file.00001 #ifndef VIENNAFEM_ASSEMBLER_HPP
00002 #define VIENNAFEM_ASSEMBLER_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00032 #include "viennamath/manipulation/apply_coordinate_system.hpp"
00033 #include "viennamath/runtime/numerical_quadrature.hpp"
00034 #include "viennamath/manipulation/eval.hpp"
00035
00036
00037 #include "viennadata/api.hpp"
00038
00039
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
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
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
00095 full_test_functions[current_index++] = make_full_function(scalar_test_functions[i], pde_system.unknown(0).size(), j);
00096 }
00097
00098 }
00099
00100
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
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
00110 for (std::size_t j=0; j<pde_system.unknown(0).size(); ++j)
00111 {
00112
00113 full_trial_functions[current_index++] = make_full_function(scalar_trial_functions[i], pde_system.unknown(0).size(), j);
00114 }
00115
00116 }
00117
00118
00119 log_test_and_trial_space(scalar_test_functions,
00120 scalar_trial_functions,
00121 pde_system);
00122
00123
00124
00125
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
00162 }
00163
00164 private:
00165 CellType const & cell_;
00166 };
00167
00169 template <typename T>
00170 bool is_uniform_basis(T const &) { return true; }
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
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
00217 local_weak_form = make_local_weak_form<CellTag>(transformed_weak_form, pde_system);
00218 }
00219
00220
00221
00222 viennamath::numerical_quadrature integrator = viennafem::make_quadrature_rule(pde_system, domain);
00223
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
00231
00232
00233
00234
00235 viennamath::rt_traversal_wrapper<> updater( new cell_updater<CellType, typename EquationType::interface_type>(*cell_iter) );
00236
00237
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
00252
00253 if (global_index_i == -1)
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)
00271 {
00272 if (pde_system.unknown(0).size() == 1)
00273 {
00274 linear_system(global_index_i) -=
00275 viennadata::access<BoundaryKeyType, double>(bnd_key)(*vocit)
00276 * integrator(local_weak_form[local_index_i][local_index_j].lhs());
00277 }
00278 else
00279 {
00280
00281 std::vector<double> const & bnd_values = viennadata::access<BoundaryKeyType, std::vector<double> >(bnd_key)(*vocit);
00282
00283 if (bnd_values.size() > 1)
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
00294
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
00306
00307 linear_system(global_index_i) += integrator(local_weak_form[local_index_i][0].rhs());
00308 }
00309 }
00310
00311 }
00312
00313 };
00314
00315 }
00316 }
00317 #endif