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