INMOST
A toolkit for distributed mathematical modeling
inmost_variable.h
1 
2 #ifndef INMOST_AUTODIFF_ETVAR_H_INCLUDED
3 #define INMOST_AUTODIFF_ETVAR_H_INCLUDED
4 #include "inmost_common.h"
5 #include "inmost_expression.h"
6 #include "inmost_mesh.h"
7 #include "inmost_autodiff.h"
8 #include "inmost_solver.h"
9 #include <sstream> //for debug
10 #include <new>
11 
12 #if defined(USE_AUTODIFF) && defined(USE_MESH)
13 
14 //TODO:
15 // 1. Incorporate tables
16 // 2. (ok, test) implement condition
17 // 3. (ok, test) implement stencil
18 // 4. (???) copying of basic_dynamic_variable
19 // 5. Consider optimization by checking zero variation multipliers, check that assembly do not degrade.
20 // 6. Document everything
21 // 7. change stencil_variable with foreach_variable and introduce function foreach(iterator beg, iterator end, arg)
22 // 8. enclose in namespace
23 // 9. maybe should not use const A & in classes, since some class may be destroyed prior use - investigate
24 
25 //This should stop Visual Studio from complaining of very long auto-generated class types
26 #ifdef _MSC_VER
27 #pragma warning(disable : 4503)
28 #endif
29 
30 
31 
32 namespace INMOST
33 {
34 
35  template<class Op, class A>
36  class unary_pool
37  {
38  A arg;
39  Op operand;
40 
41  unary_pool & operator = (unary_pool const & other) {arg = other.arg; operand.assign(other.operand,arg); return * this;}
42  public:
43  unary_pool(const A & parg) : arg(parg), operand(arg) {}
44  unary_pool(const A & parg, INMOST_DATA_REAL_TYPE pmult) : arg(parg), operand(arg,pmult) {}
45  unary_pool(const unary_pool & other) : arg(other.arg), operand(other.operand,arg) {}
46 
47  const shell_expression<A> & get_arg() {return arg;}
48  Op & get_op() {return operand;}
49  const Op & get_op() const {return operand;}
50  };
51 
52 
53 
54  template<class Op, class A, class B>
56  {
57 
58  A left;
59  B right;
60  Op operand;
61 
62  binary_pool & operator = (binary_pool const & other) {left = other.left; right = other.right; operand.assign(other.operand,left,right); return * this;}
63  public:
64  binary_pool(const A & pleft, const B & pright) : left(pleft), right(pright), operand(left,right) {}
65  binary_pool(const binary_pool & other) : left(other.left), right(other.right), operand(other.operand,left,right) {}
66 
67  const shell_expression<A> & get_left() {return left;}
68  const shell_expression<B> & get_right() {return right;}
69  Op & get_op() {return operand;}
70  const Op & get_op() const {return operand;}
71  ~binary_pool() {}
72  };
73 
74  template<class Op, class A, class B, class C>
76  {
77  A cond;
78  B left;
79  C right;
80  Op operand;
81 
82  ternary_pool & operator =(ternary_pool const & other) {cond = other.cond; left = other.left; right = other.right; operand.assign(other.operand,cond,left,right); return * this;}
83  public:
84  ternary_pool(const A & pcond, const B & pleft, const C & pright) : cond(pcond), left(pleft), right(pright), operand(cond,left,right) {}
85  ternary_pool(const ternary_pool & other) : cond(other.cond), left(other.left), right(other.right), operand(other.operand,cond,left,right) {}
86 
87  const shell_expression<A> & get_cond() {return cond;}
88  const shell_expression<B> & get_left() {return left;}
89  const shell_expression<C> & get_right() {return right;}
90  Op & get_op() {return operand;}
91  const Op & get_op() const {return operand;}
92  ~ternary_pool() {}
93  };
94 
95  template<class A, class ArgA>
96  class unary_pool_expression : public shell_expression<unary_pool_expression<A,ArgA> >
97  {
98  unary_pool<A,ArgA> pool;
99  public:
100  unary_pool_expression(const unary_pool<A,ArgA> & ppool) : pool(ppool) {}
101  unary_pool_expression(const unary_pool_expression & other) : pool(other.pool) {}
102  unary_pool_expression & operator = (unary_pool_expression const & other) {pool = other.pool; return * this;}
103  __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return pool.get_op().GetValue(); }
104  __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {pool.get_op().GetJacobian(mult,r);}
105  __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {pool.get_op().GetJacobian(mult,r);}
106  __INLINE void GetHessian(INMOST_DATA_REAL_TYPE multJ, Sparse::Row & J, INMOST_DATA_REAL_TYPE multH, Sparse::HessianRow & H) const {pool.get_op().GetHessian(multJ,J,multH,H);}
107  __INLINE void GetInterval(INMOST_DATA_ENUM_TYPE& beg, INMOST_DATA_ENUM_TYPE& end, INMOST_DATA_ENUM_TYPE& cnt) const { return pool.get_op().GetInterval(beg, end, cnt); }
108 
109  };
110 
111  template<class A, class ArgA, class ArgB>
112  class binary_pool_expression : public shell_expression<binary_pool_expression<A,ArgA,ArgB> >
113  {
115  public:
116  binary_pool_expression(const binary_pool<A,ArgA,ArgB> & ppool) : pool(ppool) {}
117  binary_pool_expression(const binary_pool_expression & other) : pool(other.pool) {}
118  binary_pool_expression & operator = (binary_pool_expression const & other) {pool = other.pool; return * this;}
119  __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return pool.get_op().GetValue(); }
120  __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {pool.get_op().GetJacobian(mult,r);}
121  __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {pool.get_op().GetJacobian(mult,r);}
122  __INLINE void GetHessian(INMOST_DATA_REAL_TYPE multJ, Sparse::Row & J, INMOST_DATA_REAL_TYPE multH, Sparse::HessianRow & H) const {pool.get_op().GetHessian(multJ,J,multH,H);}
123  __INLINE void GetInterval(INMOST_DATA_ENUM_TYPE& beg, INMOST_DATA_ENUM_TYPE& end, INMOST_DATA_ENUM_TYPE& cnt) const { return pool.get_op().GetInterval(beg, end, cnt); }
124  };
125 
126  template<class A, class ArgA, class ArgB, class ArgC>
127  class ternary_pool_expression : public shell_expression<ternary_pool_expression<A,ArgA,ArgB,ArgC> >
128  {
130  public:
131  ternary_pool_expression(const ternary_pool<A,ArgA,ArgB,ArgC> & ppool) : pool(ppool) {}
132  ternary_pool_expression(const ternary_pool_expression & other) : pool(other.pool) {}
133  ternary_pool_expression & operator = (ternary_pool_expression const & other) {pool = other.pool; return * this;}
134  __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return pool.get_op().GetValue(); }
135  __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {pool.get_op().GetJacobian(mult,r);}
136  __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {pool.get_op().GetJacobian(mult,r);}
137  __INLINE void GetHessian(INMOST_DATA_REAL_TYPE multJ, Sparse::Row & J, INMOST_DATA_REAL_TYPE multH, Sparse::HessianRow & H) const {pool.get_op().GetHessian(multJ,J,multH,H);}
138  __INLINE void GetInterval(INMOST_DATA_ENUM_TYPE& beg, INMOST_DATA_ENUM_TYPE& end, INMOST_DATA_ENUM_TYPE& cnt) const { return pool.get_op().GetInterval(beg, end, cnt); }
139  };
140 
142  {
143  public:
144  virtual INMOST_DATA_REAL_TYPE Value (const Storage & e) const = 0;
145  virtual multivar_expression Variable(const Storage & e) const = 0;
146  virtual void GetVariation(const Storage & e, Sparse::Row & r) const = 0;
147  virtual void GetVariation(const Storage & e, Sparse::RowMerger & r) const = 0;
148  virtual abstract_dynamic_variable * Copy() const = 0;
149  virtual ~abstract_dynamic_variable() {}
150  };
151 
152  template<typename RetType>
154  {
155  public:
156  virtual RetType operator()(const Storage & e) const = 0;
157  };
158 
159  template<>
161  {
162  const abstract_dynamic_variable & var;
163  public:
164  typedef multivar_expression type;
165  get_variable(const abstract_dynamic_variable & var) : var(var) {}
166  multivar_expression operator()(const Storage & e) const {return var.Variable(e);}
167  };
168 
169  template<>
170  class get_variable<INMOST_DATA_REAL_TYPE>
171  {
172  const abstract_dynamic_variable & var;
173  public:
174  typedef INMOST_DATA_REAL_TYPE type;
175  get_variable(const abstract_dynamic_variable & var) : var(var) {}
176  INMOST_DATA_REAL_TYPE operator()(const Storage & e) const {return var.Value(e);}
177  };
178 
179 
180 
181 
182 
183  template<class VariableType>
185  {
186  public:
187  typedef VariableType Var;
188  virtual INMOST_DATA_REAL_TYPE Value(const Storage & e) const = 0;
189  virtual multivar_expression Variable(const Storage & e) const = 0;
190  virtual VariableType operator[](const Storage & e) const = 0;
191  virtual void GetVariation(const Storage & e, Sparse::Row & r) const = 0;
192  virtual void GetVariation(const Storage & e, Sparse::RowMerger & r) const = 0;
193  virtual abstract_dynamic_variable * Copy() const = 0;
194  virtual ~basic_dynamic_variable() {}
195  };
196 
197  template<class VariableType, class Derived>
198  class shell_dynamic_variable : virtual public basic_dynamic_variable<VariableType>
199  {
200  public:
201  typedef VariableType Var;
202  virtual INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return static_cast<const Derived *>(this)->Value(e);}
203  virtual multivar_expression operator ()(const Storage & e) const {return static_cast<const Derived *>(this)->Variable(e);}
204  virtual VariableType operator[](const Storage & e) const {return (*static_cast<const Derived *>(this))[e];}
205  virtual void GetVariation(const Storage & e, Sparse::Row & r) const {static_cast<const Derived *>(this)->GetVariation(e,r);}
206  virtual void GetVariation(const Storage & e, Sparse::RowMerger & r) const {static_cast<const Derived *>(this)->GetVariation(e,r);}
207  operator Derived & () {return *static_cast<Derived *>(this);}
208  operator const Derived & () const {return *static_cast<const Derived *>(this);}
209  virtual abstract_dynamic_variable * Copy() const { return static_cast<const Derived *>(this)->Copy(); }
210  };
211 
212  class stored_variable_expression : public shell_dynamic_variable<multivar_expression,stored_variable_expression>
213  {
215  public:
216  stored_variable_expression() : var(NULL) {}
217  stored_variable_expression(const abstract_dynamic_variable & pvar) : var(pvar.Copy()) {}
218  stored_variable_expression(const stored_variable_expression & other) : var(other.var->Copy()) {}
219  ~stored_variable_expression() {delete var; var = NULL;}
220  stored_variable_expression operator =(stored_variable_expression const & other) {var = other.var->Copy(); return *this;}
221  stored_variable_expression operator =(const abstract_dynamic_variable & pvar) {var = pvar.Copy(); return *this;}
222  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return var->Value(e);}
223  multivar_expression Variable(const Storage & e) const {return var->Variable(e);}
224  multivar_expression operator [](const Storage & e) const {return var->Variable(e);}
225  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
226  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
227 
228  template<typename T>
230  abstract_dynamic_variable & retrieve_expression() {return *var;}
231  const abstract_dynamic_variable & retrieve_expression() const {return *var;}
232  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new stored_variable_expression(*this));}
233  };
234 
235 
236  class dynamic_variable : public shell_dynamic_variable<var_expression,dynamic_variable >
237  {
238  private:
239  const AbstractEntry * entry;
240  INMOST_DATA_ENUM_TYPE comp;
241  public:
242  dynamic_variable() :entry(NULL), comp(ENUMUNDEF) {}
243  dynamic_variable(Automatizator & aut, INMOST_DATA_ENUM_TYPE reg_index, INMOST_DATA_ENUM_TYPE comp = 0) : entry(reg_index==ENUMUNDEF?NULL:&aut.GetEntry(reg_index)), comp(comp) {}
244  dynamic_variable(const AbstractEntry * re, INMOST_DATA_ENUM_TYPE comp = 0) : entry(re), comp(comp) {}
245  dynamic_variable(const dynamic_variable & other) : entry(other.entry), comp(other.comp) {}
246  dynamic_variable & operator =(const dynamic_variable & other)
247  {
248  entry = other.entry;
249  comp = other.comp;
250  return * this;
251  }
252  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return entry->Value(e,comp);}
253  INMOST_DATA_ENUM_TYPE Index(const Storage & e) const {return entry->isValid(e) ? entry->Index(e,comp):ENUMUNDEF;}
254  multivar_expression Variable(const Storage & e) const
255  {
256  if( entry->isValid(e) )
257  return entry->Unknown(e,comp);
258  else
259  return entry->Value(e,comp);
260  }
261  var_expression operator [](const Storage & e) const {return var_expression(entry->Value(e,comp),entry->isValid(e)?entry->Index(e,comp):ENUMUNDEF);}
262  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
263  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
264  bool isUnknown(const Storage & e) const {return entry->isValid(e)?true:false;}
265  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new dynamic_variable(*this));}
266  };
267 
268  class const_variable : public shell_dynamic_variable<const_expression,const_variable>
269  {
270  private:
271  INMOST_DATA_REAL_TYPE value;
272  public:
273  const_variable(INMOST_DATA_REAL_TYPE _value) : value(_value) {}
274  const_variable(const const_variable & other) : value(other.value) {}
275  const_variable & operator =(const const_variable & other)
276  {
277  value = other.value;
278  return * this;
279  }
280  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {(void)e; return value;}
281  multivar_expression Variable(const Storage & e) const
282  {
283  (void)e;
284  return multivar_expression(value);
285  }
286  const_expression operator [](const Storage & e) const {(void)e; return const_expression(value);}
287  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
288  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
289  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new const_variable(*this));}
290  };
291 
292  class const_link_variable : public shell_dynamic_variable<const_expression,const_link_variable>
293  {
294  private:
295  const INMOST_DATA_REAL_TYPE * value;
296  public:
297  const_link_variable(const INMOST_DATA_REAL_TYPE * _value) : value(_value) {}
298  const_link_variable(const const_link_variable & other) : value(other.value) {}
299  const_link_variable & operator =(const const_link_variable & other)
300  {
301  value = other.value;
302  return * this;
303  }
304  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {(void)e; return *value;}
305  multivar_expression Variable(const Storage & e) const
306  {
307  (void)e;
308  return multivar_expression(*value);
309  }
310  const_expression operator [](const Storage & e) const {(void)e; return const_expression(*value);}
311  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
312  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
313  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new const_link_variable(*this));}
314  };
315 
316  class static_variable : public shell_dynamic_variable<const_expression,static_variable>
317  {
318  private:
319  Tag value_tag;
320  INMOST_DATA_ENUM_TYPE comp;
321  public:
322  static_variable(Tag t, INMOST_DATA_ENUM_TYPE pcomp = 0) : value_tag(t), comp(pcomp) {}
323  static_variable(const static_variable & other) : value_tag(other.value_tag), comp(other.comp) {}
324  static_variable & operator =(const static_variable & other)
325  {
326  value_tag = other.value_tag;
327  comp = other.comp;
328  return * this;
329  }
330  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return e->RealArray(value_tag)[comp];}
331  multivar_expression Variable(const Storage & e) const
332  {
333  return multivar_expression(e->RealArray(value_tag)[comp]);
334  }
335  const_expression operator [](const Storage & e) const {return const_expression(e->RealArray(value_tag)[comp]);}
336  Tag ValueTag() {return value_tag;}
337  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
338  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
339  bool isUnknown(const Storage & e) const {(void)e; return false;}
340  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new static_variable(*this));}
341  };
342 
343  class stored_variable : public shell_dynamic_variable<multivar_expression_reference,stored_variable>
344  {
345  private:
346  Tag variable_tag;
347  INMOST_DATA_ENUM_TYPE comp;
348  public:
349  stored_variable() : variable_tag(), comp(ENUMUNDEF) {}
350  stored_variable(Tag t, INMOST_DATA_ENUM_TYPE pcomp = 0) : variable_tag(t), comp(pcomp)
351  {
352  assert(t.GetDataType() == DATA_REAL || t.GetDataType() == DATA_VARIABLE);
353  }
354  stored_variable(const stored_variable & other) : variable_tag(other.variable_tag), comp(other.comp) {}
355  stored_variable & operator =(const stored_variable & other)
356  {
357  variable_tag = other.variable_tag;
358  comp = other.comp;
359  return * this;
360  }
361  INMOST_DATA_REAL_TYPE Value(const Storage & e) const
362  {
363  if( variable_tag.GetDataType() == DATA_VARIABLE )
364  return e->VariableArray(variable_tag)[comp].GetValue();
365  else if( variable_tag.GetDataType() == DATA_REAL )
366  return e->RealArray(variable_tag)[comp];
367  else throw NotImplemented;
368  }
369  multivar_expression Variable(const Storage & e) const
370  {
371  if( variable_tag.GetDataType() == DATA_VARIABLE )
372  return e->VariableArray(variable_tag)[comp];
373  else if( variable_tag.GetDataType() == DATA_REAL )
374  return variable(e->RealArray(variable_tag)[comp]);
375  else throw NotImplemented;
376  }
377  multivar_expression_reference operator [](const Storage & e) const
378  {
379  if( variable_tag.GetDataType() == DATA_VARIABLE )
380  return e->VariableArray(variable_tag)[comp];
381  else if( variable_tag.GetDataType() == DATA_REAL )
382  return multivar_expression_reference(e->RealArray(variable_tag)[comp],NULL);
383  else throw NotImplemented;
384  }
385  Tag VariableTag() {return variable_tag;}
386  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
387  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
388  bool isUnknown(const Storage & e) const {(void)e; return false;}
389  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new stored_variable(*this));}
390  };
391 
392  template<class A>
393  class stencil_expression : public shell_expression<stencil_expression<A> >
394  {
395  public:
398  typedef std::vector< argument > container;
399  private:
400  container arg;
401  INMOST_DATA_REAL_TYPE value;
402  public:
403  stencil_expression(const container & parg) : arg(parg)
404  {
405  value = 0.0;
406  for(typename container::iterator it = arg.begin(); it != arg.end(); ++it)
407  value += it->GetValue();
408  }
409  stencil_expression(const stencil_expression & other) : arg(other.arg), value(other.value) {}
410  __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
411  __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
412  {
413  for(typename container::iterator it = arg.begin(); it != arg.end(); ++it)
414  it->GetJacobian(mult,r);
415  }
416  __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
417  {
418  for(typename container::iterator it = arg.begin(); it != arg.end(); ++it)
419  it->GetJacobian(mult,r);
420  }
421  __INLINE void GetHessian(INMOST_DATA_REAL_TYPE multJ, Sparse::Row & J, INMOST_DATA_REAL_TYPE multH, Sparse::HessianRow & H) const
422  {
423  Sparse::Row tmpJ, curJ;
424  Sparse::HessianRow tmpH, curH;
425  for(typename container::iterator it = arg.begin(); it != arg.end(); ++it)
426  {
427  curJ.Clear();
428  curH.Clear();
429  it->GetHessian(multJ,curJ,multH,curH);
430  Sparse::Row::MergeSortedRows(1.0,curJ,1.0,J,tmpJ);
431  Sparse::HessianRow::MergeSortedRows(1.0,curH,1.0,H,tmpH);
432  J.Swap(tmpJ);
433  H.Swap(tmpH);
434  }
435  }
436  };
437 
438  template<class A>
439  class stencil_variable : public shell_dynamic_variable< stencil_expression<typename A::Var>, stencil_variable<A> >
440  {
441  private:
442  TagReferenceArray tag_elems;
443  TagRealArray tag_coefs;
444  A Arg;
445  public:
446  stencil_variable(Tag tag_elems, Tag tag_coefs, const shell_dynamic_variable<typename A::Var,A> & parg) : tag_elems(tag_elems), tag_coefs(tag_coefs), Arg(parg) {}
447  stencil_variable(const stencil_variable & other) : tag_elems(other.tag_elems), tag_coefs(other.tag_coefs), Arg(other.Arg) {}
448  stencil_variable & operator =(const stencil_variable & other) {tag_elems = other.tag_elems; tag_coefs = other.tag_coefs; Arg = other.Arg; return * this;}
449  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
450  multivar_expression Variable(const Storage & e) const
451  {
452  multivar_expression ret = (*this)[e];
453  return ret;
454  }
455  stencil_expression<typename A::Var> operator [](const Storage & e) const
456  {
457  typename stencil_expression<typename A::Var>::container tmp;
458  Storage::real_array coefs = tag_coefs[e];
459  Storage::reference_array elems = tag_elems[e];
460  assert(coefs.size() == elems.size());
461  tmp.resize(elems.size());
462  for(INMOST_DATA_ENUM_TYPE k = 0; k < elems.size(); ++k)
463  {
464  typename stencil_expression<typename A::Var>::argument arg(Arg[elems[k]],coefs[k]);
466  tmp[k] = pool;
467  }
469  }
470  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
471  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
472  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new stencil_variable(*this));}
473  };
474 
475  template<class A>
476  class table_variable : public shell_dynamic_variable< unary_pool_expression< function_expression<typename A::Var>,typename A::Var > , table_variable<A> >
477  {
478  A Arg;
479  const keyval_table & Table;
480  public:
481  table_variable(const shell_dynamic_variable<typename A::Var,A> & parg, const keyval_table & ptable) : Arg(parg), Table(ptable) {}
482  table_variable(const table_variable & other) : Arg(other.Arg), Table(other.Table) {}
483  table_variable & operator = (table_variable const & other) {Arg = other.Arg; Table = other.Table; return * this;}
484  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
485  multivar_expression Variable(const Storage & e) const
486  {
487  multivar_expression ret = (*this)[e];
488  return ret;
489  }
490  unary_pool_expression< function_expression<typename A::Var> ,typename A::Var > operator [](const Storage & e) const
491  {
492  typename A::Var arg = Arg[e];
493  unary_pool< function_expression<typename A::Var>, typename A::Var> pool(arg);
494  std::pair<INMOST_DATA_REAL_TYPE, INMOST_DATA_REAL_TYPE> both = Table.GetBoth(arg.GetValue());
495  pool.get_op().SetFunctionValue(both.first);
496  pool.get_op().SetFunctionDerivative(both.second);
497  return unary_pool_expression< function_expression<typename A::Var>, typename A::Var >(pool);
498  }
499  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
500  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
501  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new table_variable(*this));}
502  };
503 
506  template<class A, class B>
507  class etype_branch_variable : public shell_dynamic_variable< multivar_expression, etype_branch_variable<A,B> >
508  {
509  private:
510  A ArgA; //< Variable expression to be evaluated when type of provided element matches selected types.
511  B ArgB; //< Variable expression to be evaluated when type of provided element does not match selected types.
512  ElementType types_true; //< Selected types of elements.
513  public:
515  etype_branch_variable(ElementType _types_true, const A & _ArgA, const B & _ArgB) : types_true(_types_true), ArgA(_ArgA), ArgB(_ArgB) {}
517  etype_branch_variable(const etype_branch_variable & other) : types_true(other.types_true), ArgA(other.ArgA), ArgB(other.ArgB) {}
520  {
521  types_true = other.types_true;
522  ArgA = other.ArgA;
523  ArgB = other.ArgB;
524  return *this;
525  }
527  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
530  multivar_expression Variable(const Storage & e) const { return (*this)[e]; }
533  {
534  if( e->GetElementType() & types_true )
535  return ArgA[e];
536  else return ArgB[e];
537  }
539  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
541  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
543  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new etype_branch_variable(*this));}
544  };
545 
549  template<class A, class B>
550  class marker_branch_variable : public shell_dynamic_variable< multivar_expression, marker_branch_variable<A,B> >
551  {
552  private:
553  A ArgA; //< Variable expression to be evaluated when marker is set on the element.
554  B ArgB; //< Variable expression to be evaluated when marker is not set on the element.
555  MarkerType marker; //< Marker.
556  public:
558  marker_branch_variable(MarkerType _marker, const A & _ArgA, const B & _ArgB) : marker(_marker), ArgA(_ArgA), ArgB(_ArgB) {}
560  marker_branch_variable(const marker_branch_variable & other) : marker(other.marker), ArgA(other.ArgA), ArgB(other.ArgB) {}
563  {
564  marker = other.marker;
565  ArgA = other.ArgA;
566  ArgB = other.ArgB;
567  return *this;
568  }
570  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
573  multivar_expression Variable(const Storage & e) const { return (*this)[e]; }
576  {
577  if( isPrivate(marker) ? e->GetPrivateMarker(marker) : e->GetMarker(marker) )
578  return ArgA[e];
579  else return ArgB[e];
580  }
582  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
584  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
587  };
588 
589 
590 
591  template<class Expr, class A>
592  class unary_custom_variable : public shell_dynamic_variable< unary_pool_expression<Expr, typename A::Var >,unary_custom_variable<Expr,A> >
593  {
594  private:
595  A Arg;
596  public:
598  unary_custom_variable(const unary_custom_variable & other) : Arg(other.Arg) {}
599  unary_custom_variable & operator =(unary_custom_variable const & other) {Arg = other.Arg; return * this;}
600  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
601  multivar_expression Variable(const Storage & e) const
602  {
603  multivar_expression ret = (*this)[e];
604  return ret;
605  }
606  unary_pool_expression<Expr, typename A::Var > operator [](const Storage & e) const
607  {
610  }
611  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
612  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
613  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new unary_custom_variable(*this));}
614  };
615 
616  template<class Expr, class A>
617  class unary_const_custom_variable : public shell_dynamic_variable< unary_pool_expression<Expr, typename A::Var >,unary_const_custom_variable<Expr,A> >
618  {
619  private:
620  A Left;
621  INMOST_DATA_REAL_TYPE Right;
622  public:
623  unary_const_custom_variable(const shell_dynamic_variable<typename A::Var,A> & pleft, INMOST_DATA_REAL_TYPE pright)
624  : Left(pleft), Right(pright) {}
625  unary_const_custom_variable(const unary_const_custom_variable & other) : Left(other.Left), Right(other.Right) {}
626  unary_const_custom_variable & operator =(unary_const_custom_variable const & other) {Left = other.Left; Right = other.Right; return * this;}
627  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
628  multivar_expression Variable(const Storage & e) const
629  {
630  multivar_expression ret = (*this)[e];
631  return ret;
632  }
633  unary_pool_expression<Expr, typename A::Var > operator [](const Storage & e) const
634  {
635  unary_pool<Expr,typename A::Var> pool(Left[e],Right);
637  }
638  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
639  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
640  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new unary_const_custom_variable(*this));}
641  };
642 
643  template<class Expr, class A, class B>
644  class binary_custom_variable : public shell_dynamic_variable< binary_pool_expression<Expr, typename A::Var, typename B::Var >,binary_custom_variable<Expr,A,B> >
645  {
646  private:
647  A Left;
648  B Right;
649  public:
651  : Left(pleft), Right(pright) {}
652  binary_custom_variable(const binary_custom_variable & other) : Left(other.Left), Right(other.Right) {}
653  binary_custom_variable & operator =(binary_custom_variable const & other) {Left = other.Left; Right = other.Right; return * this;}
654  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
655  multivar_expression Variable(const Storage & e) const
656  {
657  multivar_expression ret = (*this)[e];
658  return ret;
659  }
661  {
664  }
665  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
666  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
667  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new binary_custom_variable(*this));}
668  };
669 
670  template<class Expr, class A, class B, class C>
671  class ternary_custom_variable : public shell_dynamic_variable< ternary_pool_expression<Expr, typename A::Var, typename B::Var, typename C::Var >,ternary_custom_variable<Expr,A,B,C> >
672  {
673  private:
674  A Cond;
675  B Left;
676  C Right;
677  public:
679  : Cond(pcond), Left(pleft), Right(pright) {}
680  ternary_custom_variable(const ternary_custom_variable & other) : Cond(other.Cond), Left(other.Left), Right(other.Right) {}
681  ternary_custom_variable & operator =(ternary_custom_variable const & other) {Cond = other.Cond; Left = other.Left; Right = other.Right; return * this;}
682  INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
683  multivar_expression Variable(const Storage & e) const
684  {
685  multivar_expression ret = (*this)[e];
686  return ret;
687  }
689  {
692  }
693  void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
694  void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
695  abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new ternary_custom_variable(*this));}
696  };
698 }
699 
700 template<class A, class B, class C>
701 __INLINE
727 template<class A> __INLINE INMOST::stencil_variable<A> stencil(INMOST::Tag tag_elems, INMOST::Tag tag_coefs, INMOST::shell_dynamic_variable<typename A::Var,A> const & Arg) { return INMOST::stencil_variable<A>(tag_elems,tag_coefs,Arg); }
728 template<class A> __INLINE INMOST::table_variable<A> get_table(INMOST::shell_dynamic_variable<typename A::Var,A> const & Arg, const INMOST::keyval_table & Table) {return INMOST::table_variable<A>(Arg,Table);}
729 template<class A> __INLINE INMOST::stencil_expression<A> stencil(INMOST::HandleType * elems, INMOST_DATA_REAL_TYPE * coefs, INMOST_DATA_ENUM_TYPE num, INMOST::shell_dynamic_variable<typename A::Var,A> const & Arg)
730 {
731  std::vector< INMOST::const_multiplication_expression<typename A::Var> > tmp;
732  for( INMOST_DATA_ENUM_TYPE k = 0; k < num; ++k) if( elems[k] != 0 )
733  tmp.push_back(INMOST::const_multiplication_expression<typename A::Var>(Arg[elems[k]],coefs[k]));
735 }
736 template<class A, class B> __INLINE INMOST::etype_branch_variable<A,B> etype_branch(INMOST::ElementType true_type, INMOST::shell_dynamic_variable<typename A::Var,A> const & iftrue, INMOST::shell_dynamic_variable<typename B::Var,B> const & iffalse) {return INMOST::etype_branch_variable<A,B>(true_type,iftrue,iffalse);}
737 template<class A, class B> __INLINE INMOST::marker_branch_variable<A,B> marker_branch(INMOST::MarkerType marker, INMOST::shell_dynamic_variable<typename A::Var,A> const & iftrue, INMOST::shell_dynamic_variable<typename B::Var,B> const & iffalse) {return INMOST::marker_branch_variable<A,B>(marker,iftrue,iffalse);}
738 __INLINE INMOST::const_link_variable extval(const INMOST_DATA_REAL_TYPE & pvar) {return INMOST::const_link_variable(&pvar);}
739 
740 #endif //defined(USE_AUTODIFF) && defined(USE_MESH)
741 
742 
743 
744 
745 #endif //INMOST_AUTODIFF_ETVAR_H_INCLUDED
746 
This class is used to organize unknowns in abstract way, it should be registered with and managed by ...
virtual unknown Unknown(const Storage &e, INMOST_DATA_ENUM_TYPE pos) const =0
Return unknown in vector of variables of the block at certain position.
virtual INMOST_DATA_REAL_TYPE Value(const Storage &e, INMOST_DATA_ENUM_TYPE pos) const =0
Return value in vector of unknowns of the block at certain position.
bool isValid(const Storage &e) const
Check that the block is valid on given element.
virtual INMOST_DATA_ENUM_TYPE Index(const Storage &e, INMOST_DATA_ENUM_TYPE pos) const =0
Return index in vector of indices of the block at certain position.
The Automatizator class helps in defining primary unknowns of the model and enhances user experience ...
AbstractEntry & GetEntry(INMOST_DATA_ENUM_TYPE ind)
Retrieve the block from automatizator by index.
Class to store the compressed symmetric matrix of a hessian row.
void Clear()
Clear all data of the current row.
static void MergeSortedRows(INMOST_DATA_REAL_TYPE alpha, const HessianRow &left, INMOST_DATA_REAL_TYPE beta, const HessianRow &right, HessianRow &output)
output = alpha * left + beta *right
This class may be used to sum multiple sparse rows.
Class to store the sparse matrix row.
void Swap(Row &other)
Exchange all the data with another row.
void Clear()
Clear all data of the current row.
static void MergeSortedRows(INMOST_DATA_REAL_TYPE alpha, const Row &left, INMOST_DATA_REAL_TYPE beta, const Row &right, Row &output)
Add up two rows.
Storage type for representing arrays of Element references.
Definition: inmost_data.h:338
Base class for Mesh, Element, and ElementSet classes.
Definition: inmost_data.h:310
__INLINE var_array VariableArray(const Tag &tag) const
Retrieve array of variables associated with Tag.
Definition: inmost_mesh.h:3900
__INLINE real_array RealArray(const Tag &tag) const
Retrieve array of real values associated with Tag.
Definition: inmost_mesh.h:3749
This class provides the access to the individual mesh datum and general information about it.
Definition: inmost_data.h:193
This class makes possible to evaluate different expressions on different element types.
etype_branch_variable(ElementType _types_true, const A &_ArgA, const B &_ArgB)
Constructor. Used by etype_branch function.
void GetVariation(const Storage &e, Sparse::RowMerger &r) const
Retrieve first derivatives of variable expression on provided element e, with supplimentary structure...
multivar_expression Variable(const Storage &e) const
Get value with derivatives of variable expression on provided element e.
etype_branch_variable & operator=(etype_branch_variable const &other)
Assignment operator.
abstract_dynamic_variable * Copy() const
Make a copy of this class, used to reproduce and store a tree of variable expressions.
INMOST_DATA_REAL_TYPE Value(const Storage &e) const
Get value of variable expression on provided element e.
etype_branch_variable(const etype_branch_variable &other)
Copy constructor.
multivar_expression operator[](const Storage &e) const
Build an expression associated with variable expression on provided element e.
void GetVariation(const Storage &e, Sparse::Row &r) const
Retrieve first derivatives of variable expression on provided element e, default approach.
This class makes possible to evaluate different expressions depending on the markers.
abstract_dynamic_variable * Copy() const
Make a copy of this class, used to reproduce and store a tree of variable expressions.
void GetVariation(const Storage &e, Sparse::RowMerger &r) const
Retrieve first derivatives of variable expression on provided element e, with supplimentary structure...
multivar_expression operator[](const Storage &e) const
Build an expression associated with variable expression on provided element e.
marker_branch_variable & operator=(marker_branch_variable const &other)
Assignment operator.
void GetVariation(const Storage &e, Sparse::Row &r) const
Retrieve first derivatives of variable expression on provided element e, default approach.
marker_branch_variable(const marker_branch_variable &other)
Copy constructor.
multivar_expression Variable(const Storage &e) const
Get value with derivatives of variable expression on provided element e.
marker_branch_variable(MarkerType _marker, const A &_ArgA, const B &_ArgB)
Constructor. Used by marker_branch function.
INMOST_DATA_REAL_TYPE Value(const Storage &e) const
Get value of variable expression on provided element e.
A class that represents a variable with multiple first order variations.