COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
BlockAccumulator.hpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2011 von Karman Institute for Fluid Dynamics, Belgium
2 //
3 // This software is distributed under the terms of the
4 // GNU Lesser General Public License version 3 (LGPLv3).
5 // See doc/lgpl.txt and doc/gpl.txt for the license text.
6 
7 
8 #ifndef cf3_solver_actions_Proto_BlockAccumulator_hpp
9 #define cf3_solver_actions_Proto_BlockAccumulator_hpp
10 
11 #include <boost/mpl/assert.hpp>
12 #include <boost/proto/core.hpp>
13 #include <boost/proto/traits.hpp>
14 
15 
16 #include "math/MatrixTypes.hpp"
17 
18 #include "math/LSS/System.hpp"
20 #include "math/LSS/Matrix.hpp"
21 
22 #include "LSSWrapper.hpp"
23 #include "Terminals.hpp"
24 
27 
28 namespace cf3 {
29 namespace solver {
30 namespace actions {
31 namespace Proto {
32 
33 namespace detail {
35  template<Uint I>
36  struct SafeNbNodes
37  {
38  static const Uint value = I;
39  };
40 
41  template<>
42  struct SafeNbNodes<0>
43  {
44  static const Uint value = 1;
45  };
46 
47  template<Uint I>
48  inline void assert_nb_nodes()
49  {
50  }
51 
52  template<>
53  inline void assert_nb_nodes<0>()
54  {
55  throw common::ShouldNotBeHere(FromHere(), "Number of element nodes was found to be zero.");
56  }
57 }
58 
59 
62 {
63 };
64 
67 
70 {
71 };
72 
75 
77 template<typename TagT>
79  boost::proto::terminal< LSSWrapperImpl<TagT> >
80 {
81 };
82 
84 template<typename SystemTagT>
86 {
87  template<typename Tag, int Dummy = 0> struct case_ : boost::proto::not_<boost::proto::_> {};
88 
89  template<int Dummy> struct case_<boost::proto::tag::assign, Dummy> : boost::proto::assign<BlockLhsGrammar<SystemTagT> , boost::proto::_ > {};
90  template<int Dummy> struct case_<boost::proto::tag::plus_assign, Dummy> : boost::proto::plus_assign<BlockLhsGrammar<SystemTagT> , boost::proto::_ > {};
91  template<int Dummy> struct case_<boost::proto::tag::minus_assign, Dummy> : boost::proto::minus_assign<BlockLhsGrammar<SystemTagT> , boost::proto::_ > {};
92 };
93 
95 inline void do_assign_op_matrix(boost::proto::tag::assign, math::LSS::Matrix& lss_matrix, const math::LSS::BlockAccumulator& block_accumulator)
96 {
97  lss_matrix.set_values(block_accumulator);
98 }
99 
101 inline void do_assign_op_matrix(boost::proto::tag::plus_assign, math::LSS::Matrix& lss_matrix, const math::LSS::BlockAccumulator& block_accumulator)
102 {
103  lss_matrix.add_values(block_accumulator);
104 }
105 
107 inline void do_assign_op_rhs(boost::proto::tag::assign, math::LSS::Vector& lss_rhs, const math::LSS::BlockAccumulator& block_accumulator)
108 {
109  lss_rhs.set_rhs_values(block_accumulator);
110 }
111 
113 inline void do_assign_op_rhs(boost::proto::tag::plus_assign, math::LSS::Vector& lss_rhs, const math::LSS::BlockAccumulator& block_accumulator)
114 {
115  lss_rhs.add_rhs_values(block_accumulator);
116 }
117 
119 template<typename TagT, typename TargetT>
120 inline void do_assign_op(TagT, Real& lhs, TargetT& lss_matrix, const math::LSS::BlockAccumulator& block_accumulator)
121 {
122  BOOST_MPL_ASSERT_MSG(
123  false
124  , UNSUPPORTED_ASSIGNMENT_OPERATION
125  , (TagT)
126  );
127 }
128 
130 template<typename SystemTagT, typename OpTagT>
132 
133 template<typename OpTagT>
135 {
136  template<typename LSST, typename RhsT, typename DataT>
137  void operator()(LSST& lss, const RhsT& rhs, const DataT& data) const
138  {
139  // TODO: We take some shortcuts here that assume the same shape function for every variable. Storage order for the system is i.e. uvp, uvp, ...
140  static const Uint mat_size = DataT::EMatrixSizeT::value;
141  detail::assert_nb_nodes<DataT::nb_lss_nodes>();
143  static const Uint nb_dofs = mat_size / nb_nodes;
144  math::LSS::BlockAccumulator& block_accumulator = data.block_accumulator;
145  lss.convert_to_lss(data);
146 
147  for(Uint row = 0; row != mat_size; ++row)
148  {
149  // This converts u1,u2...pn to u1v1p1...
150  const Uint block_row = (row % nb_nodes)*nb_dofs + row / nb_nodes;
151  for(Uint col = 0; col != mat_size; ++col)
152  {
153  const Uint block_col = (col % nb_nodes)*nb_dofs + col / nb_nodes;
154  block_accumulator.mat(block_row, block_col) = rhs(row, col);
155  }
156  }
157  do_assign_op_matrix(OpTagT(), lss.matrix(), block_accumulator);
158  }
159 };
160 
161 template<typename OpTagT>
163 {
164  template<typename LSST, typename RhsT, typename DataT>
165  void operator()(LSST& lss, const RhsT& rhs, const DataT& data) const
166  {
167  // TODO: We take some shortcuts here that assume the same shape function for every variable. Storage order for the system is i.e. uvp, uvp, ...
168  static const Uint mat_size = DataT::EMatrixSizeT::value;
169  detail::assert_nb_nodes<DataT::nb_lss_nodes>();
171  static const Uint nb_dofs = mat_size / nb_nodes;
172  math::LSS::BlockAccumulator& block_accumulator = data.block_accumulator;
173  lss.convert_to_lss(data);
174 
175  for(Uint i = 0; i != mat_size; ++i)
176  {
177  // This converts u1,u2...pn to u1v1p1...
178  const Uint block_idx = (i % nb_nodes)*nb_dofs + i / nb_nodes;
179  block_accumulator.rhs[block_idx] = rhs[i];
180  }
181 
182  do_assign_op_rhs(OpTagT(), lss.rhs(), block_accumulator);
183  }
184 };
185 
188  boost::proto::transform< BlockAccumulator >
189 {
190  template<typename ExprT, typename State, typename DataT>
191  struct impl : boost::proto::transform_impl<ExprT, State, DataT>
192  {
194  typedef void result_type;
195 
197  typedef typename boost::proto::tag_of<ExprT>::type OpT;
198 
200  typedef typename boost::remove_reference
201  <
202  typename boost::proto::result_of::value
203  <
204  typename boost::proto::result_of::left<ExprT>::type
205  >::type
206  >::type::tag_type SystemTagT;
207 
208  result_type operator ()(
209  typename impl::expr_param expr // The assignment expression
210  , typename impl::state_param state // should be the element matrix, i.e. RHS already evaluated
211  , typename impl::data_param data // data associated with element loop
212  ) const
213  {
214  BlockAssignmentOp<SystemTagT, OpT>()(boost::proto::value( boost::proto::left(expr) ), state, data);
215  }
216  };
217 };
218 
220 boost::proto::transform< RHSAccumulator >
221 {
222  template<typename ExprT, typename State, typename DataT>
223  struct impl : boost::proto::transform_impl<ExprT, State, DataT>
224  {
226  typedef void result_type;
227 
228  template<typename LSST, typename RhsT>
229  void assign_single_variable(LSST& lss_term, const RhsT& rhs, typename impl::data_param data, const Uint var_offset) const
230  {
231  math::LSS::System& lss = lss_term.lss();
232  // TODO: We take some shortcuts here that assume the same shape function for every variable. Storage order for the system is i.e. uvp, uvp, ...
233  typedef typename boost::remove_reference<DataT>::type DataUnrefT;
234  static const Uint mat_size = DataUnrefT::EMatrixSizeT::value;
235  typedef typename DataUnrefT::SupportT SupportT;
236  detail::assert_nb_nodes<DataUnrefT::nb_lss_nodes>();
238  static const Uint nb_dofs = mat_size / nb_nodes;
239  math::LSS::BlockAccumulator& block_accumulator = data.block_accumulator;
240  lss_term.convert_to_lss(data);
241 
242  for(Uint i = 0; i != var_offset; ++i)
243  {
244  const Uint block_idx = (i % nb_nodes)*nb_dofs + i / nb_nodes;
245  block_accumulator.rhs[block_idx] = 0.;
246  }
247  const Uint var_end = var_offset + rhs.size();
248  for(Uint i = var_offset; i != var_end; ++i)
249  {
250  const Uint block_idx = (i % nb_nodes)*nb_dofs + i / nb_nodes;
251  block_accumulator.rhs[block_idx] = rhs[i];
252  }
253  for(Uint i = var_end; i != mat_size; ++i)
254  {
255  const Uint block_idx = (i % nb_nodes)*nb_dofs + i / nb_nodes;
256  block_accumulator.rhs[block_idx] = 0.;
257  }
258  do_assign_op_rhs(boost::proto::tag::plus_assign(), *lss.rhs(), block_accumulator);
259  }
260 
261  result_type operator ()(
262  typename impl::expr_param expr // The assignment expression
263  , typename impl::state_param state // should be the element matrix, i.e. RHS already evaluated
264  , typename impl::data_param data // data associated with element loop
265  ) const
266  {
267  assign_single_variable(boost::proto::value( boost::proto::left( boost::proto::left(expr) ) ), state, data, data.var_data(boost::proto::value(boost::proto::right(boost::proto::left(expr)))).offset);
268  }
269  };
270 };
271 
273 template<typename GrammarT>
275  boost::proto::or_
276  <
277  boost::proto::when
278  <
279  boost::proto::or_< boost::proto::switch_< MatrixAssignOpsCases<SystemMatrixTag> >, boost::proto::switch_< MatrixAssignOpsCases<SystemRHSTag> > >,
280  BlockAccumulator( boost::proto::_expr, GrammarT(boost::proto::_right) )
281  >,
282  boost::proto::when
283  <
284  boost::proto::plus_assign< boost::proto::function< BlockLhsGrammar<SystemRHSTag>, FieldTypes >, boost::proto::_ >,
285  RHSAccumulator( boost::proto::_expr, GrammarT(boost::proto::_right) )
286  >
287  >
288 {
289 };
290 
291 } // namespace Proto
292 } // namespace actions
293 } // namespace solver
294 } // namespace cf3
295 
296 #endif // cf3_solver_actions_Proto_BlockAccumulator_hpp
void operator()(LSST &lss, const RhsT &rhs, const DataT &data) const
virtual void add_rhs_values(const BlockAccumulator &values)=0
Add a list of values to rhs.
result_type operator()(typename impl::expr_param expr, typename impl::state_param state, typename impl::data_param data) const
virtual void set_rhs_values(const BlockAccumulator &values)=0
Set a list of values to rhs.
external boost library namespace
void result_type
Contrary to general C++ assignment, assigning to a LSS doesn't return anything.
This header collects all the headers needed for the linear system solver, also including configure-ti...
void operator()(LSST &lss, const RhsT &rhs, const DataT &data) const
void do_assign_op(TagT, Real &lhs, TargetT &lss_matrix, const math::LSS::BlockAccumulator &block_accumulator)
Translate tag to operator.
virtual void set_values(const BlockAccumulator &values)=0
Set a list of values.
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > mat
virtual void add_values(const BlockAccumulator &values)=0
boost::remove_reference< typename boost::proto::result_of::value< typename boost::proto::result_of::left< ExprT >::type >::type >::type::tag_type SystemTagT
Tag indicating if we are modifying the RHS or the system matrix (stored in child 0 of the LHS of the ...
LSSWrapper< SystemRHSTag > SystemRHS
Represents an RHS.
Primitive transform to handle assignment to an LSS matrix.
void do_assign_op_matrix(boost::proto::tag::assign, math::LSS::Matrix &lss_matrix, const math::LSS::BlockAccumulator &block_accumulator)
Translate tag to operator.
Helper to get the number of LSS nodes, avoiding static divide-by-zero.
Grammar matching the LHS of an assignment op.
Grammar matching block accumulation expressions.
Allowed block assignment operations.
Top-level namespace for coolfluid.
Definition: Action.cpp:18
LSSWrapper< SystemMatrixTag > SystemMatrix
Represents a system matrix.
Handle< LSS::Vector > rhs()
Accessor to right hand side.
Definition: System.hpp:148
void do_assign_op_rhs(boost::proto::tag::assign, math::LSS::Vector &lss_rhs, const math::LSS::BlockAccumulator &block_accumulator)
Translate tag to operator.
void result_type
Contrary to general C++ assignment, assigning to a LSS doesn't return anything.
Helper struct for assignment to a matrix or RHS.
boost::proto::tag_of< ExprT >::type OpT
Tag type represents the actual operation type.
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
void assign_single_variable(LSST &lss_term, const RhsT &rhs, typename impl::data_param data, const Uint var_offset) const
result_type operator()(typename impl::expr_param expr, typename impl::state_param state, typename impl::data_param data) const
RealVector rhs
accessor to blockaccumulator's right hand side vector
#define FromHere()
Send comments to:
COOLFluiD Web Admin