1/*
2 * mul.hpp
3 *
4 * Created on: Oct 22, 2015
5 * Author: i-bird
6 */
7
8#ifndef OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_MUL_HPP_
9#define OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_MUL_HPP_
10
11#include <typeinfo>
12#include "util/util_debug.hpp"
13#include "util/util_num.hpp"
14
15#define HAS_VAL 1
16#define HAS_POS_VAL 2
17
18//! Evaluate the constant field function
19template <unsigned int, typename T>
20struct has_val
21{
22 //! evaluate
23 static float call_val()
24 {
25 std::cerr << "Error the type " << demangle(typeid(T).name()) << "interpreted as constant field, does not have a function val() or val_pos(), please see the numeric examples in Finite Differences for more information\n";
26 return 0;
27 }
28};
29
30//! Evaluate the constant field function
31template <typename T>
32struct has_val<HAS_VAL,T>
33{
34 //! evaluate
35 static decltype(T::val()) call_val()
36 {
37 return T::val();
38 }
39};
40
41//! Multiplication expression
42template<typename v_expr>
43struct const_mul_functor_value
44{
45 //! Number of elements in the vector v_expr
46 typedef boost::mpl::size<v_expr> size;
47
48 //! Last element of sum
49 typedef typename boost::mpl::at<v_expr,boost::mpl::int_<size::value-1> >::type last;
50
51 //! sum functor
52 std::unordered_map<long int,typename last::stype> & cols;
53
54 //! grid size
55 const grid_sm<last::dims,void> & gs;
56
57 //! grid mapping
58 const grid_dist_id<last::dims,typename last::stype,aggregate<size_t>,typename last::b_grid::decomposition::extended_type> & g_map;
59
60 //! grid position
61 grid_dist_key_dx<last::dims> & kmap;
62
63 //! coefficent
64 typename last::stype coeff;
65
66 //! spacing
67 typename last::stype (& spacing)[last::dims];
68
69 /*! \brief constructor
70 *
71 * \param g_map mapping grid
72 * \param kmap grid point (row) where we evaluate the non-zero colums
73 * \param gs grid size
74 * \param spacing grid spacing
75 * \param cols non zero colums
76 * \param coeff multiplication coefficent
77 *
78 */
79 const_mul_functor_value(const grid_dist_id<last::dims,typename last::stype,aggregate<size_t>,typename last::b_grid::decomposition::extended_type> & g_map,
80 grid_dist_key_dx<last::dims> & kmap,
81 const grid_sm<last::dims,void> & gs,
82 typename last::stype (& spacing)[last::dims],
83 std::unordered_map<long int,typename last::stype> & cols,
84 typename last::stype coeff)
85 :cols(cols),gs(gs),g_map(g_map),kmap(kmap),coeff(coeff),spacing(spacing)
86 {};
87
88
89
90 //! It call this function for every constant expression in the mul
91 template<typename T>
92 void operator()(T& t)
93 {
94 typedef typename boost::mpl::at<v_expr, boost::mpl::int_<T::value> >::type cfield;
95
96 coeff *= has_val<is_const_field<cfield>::value * 1,cfield>::call_val();
97 }
98
99 /*! \brief Get the coefficent
100 *
101 * \return the coefficent
102 *
103 */
104 typename last::stype getCoeff()
105 {
106 return coeff;
107 }
108};
109
110/*! \brief It model an expression expr1 * expr2
111 *
112 * \warning expr1 MUST be a constant expression only expr2 depend form variable, this requirement ensure linearity in the solving variable of the equations
113 *
114 * \tparam expr1
115 * \tparam expr2
116 *
117 */
118template<typename ... expr >
119struct mul
120{
121 //! Transform from variadic template to boost mpl vector
122 typedef boost::mpl::vector<expr... > v_expr;
123
124 //! size of v_expr
125 typedef typename boost::mpl::size<v_expr>::type v_sz;
126
127 //! type on which this expression operate
128 typedef typename boost::mpl::at<v_expr, boost::mpl::int_<v_sz::type::value - 1> >::type Sys_eqs;
129
130 /*! \brief Calculate which colums of the Matrix are non zero
131 *
132 * \param g_map mapping grid
133 * \param kmap position where the multiplication is calculated
134 * \param gs Grid info
135 * \param spacing of the grid
136 * \param cols non-zero colums calculated by the function
137 * \param coeff coefficent (constant in front of the derivative)
138 *
139 */
140 inline static void value(const grid_dist_id<Sys_eqs::dims,typename Sys_eqs::stype,aggregate<size_t>,typename Sys_eqs::b_grid::decomposition::extended_type> & g_map,
141 grid_dist_key_dx<Sys_eqs::dims> & kmap,
142 const grid_sm<Sys_eqs::dims,void> & gs,
143 typename Sys_eqs::stype (& spacing )[Sys_eqs::dims],
144 std::unordered_map<long int,typename Sys_eqs::stype > & cols,
145 typename Sys_eqs::stype coeff)
146 {
147 const_mul_functor_value<v_expr> mfv(g_map,kmap,gs,spacing,cols,coeff);
148
149 //
150 boost::mpl::for_each_ref< boost::mpl::range_c<int,0,v_sz::type::value - 2> >(mfv);
151
152 //! Last element of multiplication
153 typedef typename boost::mpl::at< v_expr ,boost::mpl::int_<v_sz::value-2> >::type last_m;
154
155 last_m::value(g_map,kmap,gs,spacing,cols,mfv.coeff);
156 }
157
158 /*! \brief Calculate the position in the cell where the mul operator is performed
159 *
160 * it just return the position of the staggered property in the last expression
161 *
162 * \param pos position where we are calculating the derivative
163 * \param gs Grid info
164 * \param s_pos staggered position of the properties
165 *
166 */
167 inline static grid_key_dx<Sys_eqs::dims> position(grid_key_dx<Sys_eqs::dims> & pos,
168 const grid_sm<Sys_eqs::dims,void> & gs,
169 const comb<Sys_eqs::dims> (& s_pos)[Sys_eqs::nvar])
170 {
171 return boost::mpl::at<v_expr, boost::mpl::int_<v_sz::type::value - 2> >::type::position(pos,gs,s_pos);
172 }
173};
174
175
176#endif /* OPENFPM_NUMERICS_SRC_FINITEDIFFERENCE_MUL_HPP_ */
177