G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsExprHelper.h
Go to the documentation of this file.
1 
14 #pragma once
15 
17 #include <gsUtils/gsThreaded.h>
18 
19 namespace gismo
20 {
21 
25 template<class T>
26 class gsExprHelper
27 {
28 private:
29  gsExprHelper(const gsExprHelper &);
30 
31  gsExprHelper() : m_mirror(nullptr), mesh_ptr(nullptr),
32  mutSrc(nullptr), mutMap(nullptr)
33  { }
34 
35  explicit gsExprHelper(gsExprHelper * m)
36  : m_mirror(memory::make_shared_not_owned(m)),
37  mesh_ptr(m->mesh_ptr), mutSrc(nullptr), mutMap(nullptr)
38  { }
39 
40 private:
41  typedef util::gsThreaded<gsFuncData<T> > thFuncData;
42  typedef util::gsThreaded<gsMapData<T> > thMapData;
43  typedef std::map<const gsFunctionSet<T>*,thFuncData> FuncData;
44  typedef std::map<const gsFunctionSet<T>*,thMapData> MapData;
45  typedef std::pair<const gsFunctionSet<T>*,thMapData*> CFuncKey;
46  typedef std::map<CFuncKey,thFuncData> CFuncData;
47 
48  typedef typename FuncData::iterator FuncDataIt;
49  typedef typename MapData ::iterator MapDataIt;
50  typedef typename CFuncData ::iterator CFuncDataIt;
51 
52  util::gsThreaded<gsMatrix<T> > m_points;
53  FuncData m_fdata;
54  MapData m_mdata;
55  CFuncData m_cdata;
56 
57  memory::shared_ptr<gsExprHelper> m_mirror;
58 
59  const gsMultiBasis<T> * mesh_ptr;
60 
61  // mutable pair of variable and data,
62  // ie. not uniquely assigned to a gsFunctionSet
63  const gsFunctionSet<T> * mutSrc;
64  const gsFunctionSet<T> * mutMap;
65  thFuncData mutData;
66 
67  // Represents the current element
68  expr::gsFeElement<T> m_element;
69 
70 public:
71  typedef memory::unique_ptr<gsExprHelper> uPtr;
72  typedef memory::shared_ptr<gsExprHelper> Ptr;
73 
74  typedef const expr::gsGeometryMap<T> geometryMap;
75  typedef expr::gsFeElement<T> & element;
76  typedef const expr::gsFeVariable<T> variable;
77  typedef const expr::gsFeSpace<T> space;
78  typedef const expr::gsComposition<T> composition;
79  typedef const expr::gsNullExpr<T> nullExpr;
80 
81 public:
82 
83  ~gsExprHelper() { }
84 
85  gsMatrix<T> & points() { return m_points; }
86  gsMatrix<T> & pointsIfc() { return this->iface().m_points; }
87 
88  bool isMirrored() const { return nullptr!=m_mirror; }
89 
90  static uPtr make() { return uPtr(new gsExprHelper()); }
91 
92  void reset()
93  {
94  points().clear();
95  //mapVar.reset();
96  }
97 
98  void cleanUp()
99  {
100  #pragma omp single
101  {
102  m_mdata.clear();
103  m_fdata.clear();
104  m_cdata.clear();
105  //mutSrc = nullptr;
106  mutMap = nullptr;
107  mutData.mine().flags = 0;
108  if (isMirrored())
109  {
110  m_mirror->m_mdata.clear();
111  m_mirror->m_fdata.clear();
112  m_mirror->m_cdata.clear();
113  //m_mirror->mutSrc = nullptr;
114  m_mirror->mutMap = nullptr;
115  m_mirror->mutData.mine().flags = 0;
116  }
117  }//implicit barrier
118  }
119 
120  void setMultiBasis(const gsMultiBasis<T> & mesh) { mesh_ptr = &mesh; }
121 
122  bool multiBasisSet() { return NULL!=mesh_ptr;}
123 
124  const gsMultiBasis<T> & multiBasis()
125  {
126  GISMO_ASSERT(multiBasisSet(), "Integration elements not set.");
127  return *mesh_ptr;
128  }
129 
130  const gsMultiPatch<T> & multiPatch() const
131  {
132  if ( !m_mdata.empty() )
133  {
134  GISMO_ASSERT(nullptr!=dynamic_cast<const gsMultiPatch<T>*>(m_mdata.begin()->first),
135  "Multipatch geometry map not set.");
136  return *static_cast<const gsMultiPatch<T>*>(m_mdata.begin()->first);
137  }
138  if (isMirrored() && !m_mirror->m_mdata.empty() )
139  {
140  GISMO_ASSERT(nullptr!=dynamic_cast<const gsMultiPatch<T>*>(m_mirror->m_mdata.begin()->first),
141  "Multipatch geometry map not set.");
142  return *static_cast<const gsMultiPatch<T>*>(m_mirror->m_mdata.begin()->first);
143  }
144  GISMO_ERROR("Geometry map not set.");
145  }
146 
147  const gsMapData<T> & multiPatchData() const
148  {
149  GISMO_ASSERT(!m_mdata.empty(), "Geometry map not set.");
150  return m_mdata.begin()->second;
151  }
152 
153  geometryMap getMap(const gsFunctionSet<T> & mp)
154  {
155  expr::gsGeometryMap<T> gm;
156  gm.setSource(mp);
157  return gm;
158  }
159 
160  expr::gsFeVariable<T> getVar(const gsFunctionSet<T> & mp, index_t dim = 1)
161  {
162  expr::gsFeVariable<T> var;
163  var.setSource(mp);
164  var.setDim(dim);
165  return var;
166  }
167 
168  composition getVar(const gsFunctionSet<T> & mp, geometryMap & G)
169  {
170  expr::gsComposition<T> var(G);
171  var.setSource(mp);
172  return var;
173  }
174 
175  expr::gsFeSpace<T> getSpace(const gsFunctionSet<T> & mp, index_t dim = 1)
176  {
177  expr::gsFeSpace<T> var;
178  var.setSource(mp);
179  var.setDim(dim);
180  return var;
181  }
182 
183  variable getMutVar() const
184  {
185  expr::gsFeVariable<T> var;
186  return var;
187  }
188 
189  element getElement() { return m_element; }
190 
191  composition getMutVar(geometryMap & G)
192  {
193  expr::gsComposition<T> var(G);
194  //mutMap = &G.source();
195  return var;
196  }
197 
198  void setMutSource(const gsFunctionSet<T> & func)
199  {
200  mutSrc = &func;
201  }
202 
203  //void clearMutSource() ?
204 
205  void activateFlags(unsigned flg)
206  {
207  // Additional evaluation flags
208  for (MapDataIt it = m_mdata.begin(); it != m_mdata.end(); ++it)
209  it->second.mine().flags |= flg;
210  for (FuncDataIt it = m_fdata.begin(); it != m_fdata.end(); ++it)
211  it->second.mine().flags |= flg;
212  for (CFuncDataIt it = m_cdata.begin(); it != m_cdata.end(); ++it)
213  it->second.mine().flags |= flg;
214  // gsInfo<< "\n-fdata: "<< m_fdata.size()<<"\n";
215  // gsInfo<< "-mdata: "<< m_mdata.size()<<"\n";
216  // gsInfo<< "-cdata: "<< m_cdata.size()<<std::endl;
217  }
218 
219 private:
220 
221  inline gsExprHelper & iface()
222  {
223  if (nullptr==m_mirror )
224  m_mirror = memory::make_shared(new gsExprHelper(this));
225  return *m_mirror;
226  }
227 
228  template <class E1>
229  void _parse(const expr::_expr<E1> & a1)
230  {
231  a1.parse(*this);
232  //a1.print(gsInfo);
233  }
234 
235  template <class E1, class... Rest>
236  void _parse(const expr::_expr<E1> & a1, Rest &... restArgs)
237  {
238  _parse(a1);
239  _parse(restArgs...);
240  }
241 
242  template<size_t I, typename... Ts>
243  void _parse_tuple_i (const std::tuple<Ts...> &tuple)
244  {
245  std::get<I>(tuple).parse(*this);
246  if (I + 1 < sizeof... (Ts))
247  _parse_tuple_i<(I+1 < sizeof... (Ts) ? I+1 : I)> (tuple);
248  }
249 
250  template<typename... Ts>
251  void _parse_tuple (const std::tuple<Ts...> &tuple) {_parse_tuple_i<0>(tuple);}
252 
253  void setInitialFlags()
254  {
255  // Additional evaluation flags
256  for (MapDataIt it = m_mdata.begin(); it != m_mdata.end(); ++it)
257  it->second.mine().flags |= NEED_ACTIVE;
258  for (FuncDataIt it = m_fdata.begin(); it != m_fdata.end(); ++it)
259  it->second.mine().flags |= NEED_ACTIVE;
260  for (CFuncDataIt it = m_cdata.begin(); it != m_cdata.end(); ++it)
261  it->second.mine().flags |= NEED_ACTIVE;
262  //gsInfo<< "\n-fdata: "<< m_fdata.size()<<"\n";
263  //gsInfo<< "-mdata: "<< m_mdata.size()<<"\n";
264  //gsInfo<< "-cdata: "<< m_cdata.size()<<std::endl;
265 
266  if (isMirrored())
267  {
268  for (MapDataIt it = m_mirror->m_mdata.begin(); it != m_mirror->m_mdata.end(); ++it)
269  it->second.mine().flags |= NEED_ACTIVE;
270  for (FuncDataIt it = m_mirror->m_fdata.begin(); it != m_mirror->m_fdata.end(); ++it)
271  it->second.mine().flags |= NEED_ACTIVE;
272  for (CFuncDataIt it = m_mirror->m_cdata.begin(); it != m_mirror->m_cdata.end(); ++it)
273  it->second.mine().flags |= NEED_ACTIVE;
274  // gsInfo<< "+fdata: "<< m_mirror->m_fdata.size()<<"\n";
275  // gsInfo<< "+mdata: "<< m_mirror->m_mdata.size()<<"\n";
276  // gsInfo<< "+cdata: "<< m_mirror->m_cdata.size()<<std::endl;
277  }
278  }
279 
280 public:
281 
282  template<class... Ts>
283  void parse(const std::tuple<Ts...> &tuple)
284  {
285  cleanUp(); //assumes parse is called once.
286  _parse_tuple(tuple);
287  setInitialFlags();
288  }
289 
290  template<class... expr>
291  void parse(const expr &... args)
292  {
293  cleanUp(); //assumes parse is called once.
294  _parse(args...);
295  setInitialFlags();
296  }
297 
298  void add(const expr::gsGeometryMap<T> & sym)
299  {
300  GISMO_ASSERT(NULL!=sym.m_fs, "Geometry map "<<&sym<<" is invalid");
301  gsExprHelper & eh = (sym.isAcross() ? iface() : *this);
302 # pragma omp critical (m_mdata_first_touch)
303  const_cast<expr::gsGeometryMap<T>&>(sym)
304  .setData(eh.m_mdata[sym.m_fs]);
305  }
306 
307  void add(const expr::gsComposition<T> & sym)
308  {
309  //GISMO_ASSERT(NULL!=sym.m_fs, "Composition "<<&sym<<" is invalid");
310  add(sym.inner());//the map
311  sym.inner().data().flags |= NEED_VALUE;
312  if (nullptr==sym.m_fs)
313  {
314  //gsInfo<<"\nGot BC composition\n";
315  mutMap = &sym.inner().source();
316  if (nullptr!=mutSrc)
317  {
318 # pragma omp critical (m_fdata_first_touch)
319  const_cast<expr::gsComposition<T>&>(sym)
320  .setData( mutData );
321 
322  const_cast<expr::gsComposition<T>&>(sym)
323  .setSource(*mutSrc);
324  }
325  else
326  gsWarn<<"\nSomething went terribly wrong here (add gsComposition).\n";
327  return;
328  }
329 
330  //register the function //if !=nullptr?
331  auto k = std::make_pair(sym.m_fs,&m_mdata[sym.inner().m_fs]);
332  auto it = m_cdata.find(k);
333  gsExprHelper & eh = (sym.isAcross() ? iface() : *this);
334  if (m_cdata.end()==it)
335  // when the variable is added for the first time,
336  // we have to be thread-safe (atomic).
337 # pragma omp critical (m_cdata_first_touch)
338  const_cast<expr::gsComposition<T>&>(sym)
339  .setData(eh.m_cdata[ give(k) ]);
340  else
341  const_cast<expr::gsComposition<T>&>(sym)
342  .setData(eh.m_cdata[ give(k) ]);
343  }
344 
345  template <class E>
346  void add(const expr::symbol_expr<E> & sym)
347  {
348  //parallel: variables become thread-local
349  // for each variable we provide a gsFuncData pointer
350  // in the same thread this can be the same ptr (as done now)
351  gsExprHelper & eh = (sym.isAcross() ? iface() : *this);
352 
353  if (NULL!=sym.m_fs)
354  {
355  /*
356  if ( 1==sym.m_fs->size() &&
357  sym.m_fs->domainDim()<=sym.m_fs->targetDim() )// map?
358  {
359  //gsDebug<<"+ Map "<< sym.m_fs <<"\n";
360 # pragma omp critical (m_mdata_first_touch)
361  const_cast<expr::symbol_expr<E>&>(sym)
362  .setData( eh.m_mdata[sym.m_fs] );
363  }
364  else
365  */
366  {
367  //gsDebug<<"+ Func "<< sym.m_fs <<"\n";
368 # pragma omp critical (m_fdata_first_touch)
369  const_cast<expr::symbol_expr<E>&>(sym)
370  .setData( eh.m_fdata[sym.m_fs] );
371  }
372  }
373  else
374  {
375  //gsDebug<<"\nGot a mutable variable.\n";
376  if (nullptr!=mutSrc)
377  {
378 # pragma omp critical (m_fdata_first_touch)
379  const_cast<expr::symbol_expr<E>&>(sym)
380  .setData( mutData );
381 
382  const_cast<expr::symbol_expr<E>&>(sym)
383  .setSource(*mutSrc);
384  }
385  else
386  gsWarn<<"\nSomething went wrong here (add symbol_expr).\n";
387  }
388  }
389 
390  void precompute(const index_t patchIndex = 0,
391  boundary::side bs = boundary::none)
392  {
393  //First compute the maps
394  for (MapDataIt it = m_mdata.begin(); it != m_mdata.end(); ++it)
395  {
396  it->second.mine().points.swap(m_points.mine());//swap
397  it->second.mine().side = bs;
398  it->second.mine().patchId = patchIndex;
399  it->first->function(patchIndex).computeMap(it->second.mine());
400  it->second.mine().points.swap(m_points.mine());
401  }
402 
403  for (FuncDataIt it = m_fdata.begin(); it != m_fdata.end(); ++it)
404  {
405  it->second.mine().patchId = patchIndex;
406  it->first->piece(patchIndex)
407  .compute(m_points, it->second.mine());
408  }
409 
410  for (CFuncDataIt it = m_cdata.begin(); it != m_cdata.end(); ++it)
411  {
412  it->first.first->piece(patchIndex)
413  .compute(it->first.second->mine().values[0], it->second.mine());
414  it->second.mine().patchId = patchIndex;
415  }
416 
417  // Mutable variable to treat BCs
418  if (nullptr!=mutSrc && 0!=mutData.mine().flags)
419  {
420  mutSrc->piece(patchIndex)
421  .compute( mutMap ? m_mdata[mutMap].mine().values[0]
422  : m_points, mutData );
423  }
424  }
425 
426  void precompute(const boundaryInterface & iFace)
427  {
428  this->precompute( iFace.first ().patch, iFace.first().side() );
429  if ( isMirrored() )
430  m_mirror->precompute(iFace.second().patch, iFace.second().side());
431  }
432 
433 };//class gsExprHelper
434 
435 
436 } //namespace gismo
shared_ptr< T > make_shared_not_owned(const T *x)
Creates a shared pointer which does not eventually delete the underlying raw pointer. Usefull to refer to objects which should not be destroyed.
Definition: gsMemory.h:189
Definition: gsExpressions.h:96
Defines different expressions.
side
Identifiers for topological sides.
Definition: gsBoundary.h:58
MapData m_mdata
maps
Definition: gsExprHelper.h:54
S give(S &x)
Definition: gsMemory.h:266
#define index_t
Definition: gsConfig.h:32
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
FuncData m_fdata
functions
Definition: gsExprHelper.h:53
#define gsWarn
Definition: gsDebug.h:50
Holds a set of patch-wise bases and their topology information.
Definition: gsMultiBasis.h:36
Wrapper for thread-local data members.
Active function ids.
Definition: gsForwardDeclarations.h:84
Definition: gsDirichletValues.h:23
Interface for the set of functions defined on a domain (the total number of functions in the set equa...
Definition: gsFuncData.h:23
Value of the object.
Definition: gsForwardDeclarations.h:72
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
Definition: gsExpressions.h:114
CFuncData m_cdata
compositions
Definition: gsExprHelper.h:55
shared_ptr< T > make_shared(T *x)
Definition: gsMemory.h:181