G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsMappedBasis.hpp
Go to the documentation of this file.
1
15#include <gsIO/gsFileData.h>
16
17namespace gismo
18{
19
20template<short_t d,class T>
21gsMappedBasis<d,T>::gsMappedBasis( const gsMappedBasis& other )
22: gsFunctionSet<T>(other)
23{
24 m_topol = other.m_topol;
25 // clone all geometries
26 for(ConstBasisIter it = other.m_bases.begin();it!=other.m_bases.end();++it)
27 {
28 m_bases.push_back( (BasisType*)(*it)->clone().release() );
29 }
30 m_mapper=new gsWeightMapper<T>(*other.m_mapper);
31
32 //m_sb = other.m_sb; //no: other.m_sb refers to other
33}
34
35template<short_t d,class T>
36gsMappedBasis<d,T>::~gsMappedBasis()
37{
38 freeAll(m_bases);
39 delete m_mapper;
40}
41
42template<short_t d,class T>
43const std::vector<gsBasis<T>*> gsMappedBasis<d,T>::getBases() const
44{
45 std::vector<gsBasis<T>*> result;
46 for (size_t i=0; i<m_bases.size();++i)
47 result.push_back(m_bases[i]);
48 return result;
49}
50
51template<short_t d,class T>
52index_t gsMappedBasis<d,T>::size(const index_t index) const
53{
54 if(index == static_cast<int>(nPatches())-1)
55 return size()-(size()/nPatches())*(nPatches()-1);
56 else
57 return size()/nPatches();
58}
59
60template<short_t d,class T>
61short_t gsMappedBasis<d,T>::maxDegree() const
62{
63 index_t deg = degree(0,0);
64 for(size_t i=0;i<nPatches();i++)
65 for(short_t j=0;j<m_bases[i]->dim();++j)
66 if(degree(i,j)>deg)
67 deg=degree(i,j);
68 return deg;
69}
70
71template<short_t d,class T>
72void gsMappedBasis<d,T>::addLocalIndicesOfPatchSide(const patchSide& ps,index_t offset,std::vector<index_t>& locals) const
73{
74 index_t patch = ps.patch;
75 index_t side = ps.side();
76 index_t localOffset = _getFirstLocalIndex(patch);
77 gsMatrix<index_t> indizes;
78 //for(index_t i = 0;i<=offset;++i)
79 {
80 indizes=m_bases[patch]->boundaryOffset(side,offset);
81 for(index_t j=0;j<indizes.rows();++j)
82 locals.push_back(indizes.at(j)+localOffset);
83 }
84}
85
86// HV[05/10/2023]: check for correctness
87template<short_t d,class T>
88void gsMappedBasis<d,T>::boundary(std::vector<index_t> & indices,index_t offset) const
89{
90 std::vector<index_t> locals;
91 locals.reserve(this->size());
92 typedef std::vector< patchSide >::const_iterator b_const_iter;
93 for(b_const_iter iter = m_topol.bBegin();iter!=m_topol.bEnd();++iter)
94 addLocalIndicesOfPatchSide(*iter,offset,locals);
95 sort( locals.begin(), locals.end() );
96 locals.erase( unique( locals.begin(), locals.end() ), locals.end() );
97 m_mapper->sourceToTarget(locals,indices);
98}
99
100// HV[05/10/2023]: check for correctness
101template<short_t d,class T>
102void gsMappedBasis<d,T>::innerBoundaries(std::vector<index_t> & indices,index_t offset) const
103{
104 std::vector<index_t> locals;
105 locals.reserve(this->size());
106 typedef std::vector< gismo::boundaryInterface >::const_iterator i_const_iter;
107 for(i_const_iter iter = m_topol.iBegin();iter!=m_topol.iEnd();++iter)
108 {
109 patchSide firstPs = iter->first();
110 addLocalIndicesOfPatchSide(firstPs,offset,locals);
111 patchSide secondPs = iter->second();
112 addLocalIndicesOfPatchSide(secondPs,offset,locals);
113 }
114 sort( locals.begin(), locals.end() );
115 locals.erase( unique( locals.begin(), locals.end() ), locals.end() );
116 m_mapper->sourceToTarget(locals,indices);
117}
118
119template<short_t d,class T>
120gsGeometry<T>* gsMappedBasis<d,T>::exportPatch(const index_t i,gsMatrix<T> const & localCoef) const
121{
122 const short_t geoDim=localCoef.cols();
123 const index_t start = _getFirstLocalIndex(i);
124 const index_t end = _getLastLocalIndex(i);
125 gsMatrix<T> coefs = localCoef.block(start,0,end-start+1,geoDim);
126 return getBase(i).makeGeometry( give(coefs) ).release();
127}
128
129template<short_t d,class T>
130gsMultiPatch<T> gsMappedBasis<d,T>::exportToPatches(gsMatrix<T> const & localCoef) const
131{
132 std::vector<gsGeometry<T> *> patches(nPatches());
133 for(size_t i = 0; i<nPatches() ; ++i)
134 patches[i]= exportPatch(i,localCoef);
135 return gsMultiPatch<T>(patches,m_topol.boundaries(),m_topol.interfaces());
136}
137
138template<short_t d,class T>
139void gsMappedBasis<d,T>::active_into(const index_t patch, const gsMatrix<T> & u,
140 gsMatrix<index_t>& result) const //global BF active on patch at point
141{
142 const index_t start = _getFirstLocalIndex(patch);
143 gsMatrix<index_t> pActive;
144 m_bases[patch]->active_into(u, pActive);
145 // Shift actives by the offset of the current patch
146 pActive.array() += start;
147 const index_t numact = pActive.rows();
148 IndexContainer temp;
149 result.resizeLike( pActive );
150 std::vector<std::vector<index_t> > temp_output;//collects the outputs
151 temp_output.resize( pActive.cols() );
152 size_t max = 0;
153 for(index_t i = 0; i< pActive.cols();i++)
154 {
155 std::vector<index_t> act_i( pActive.col(i).data(), pActive.col(i).data() + numact); // to be removed
156 m_mapper->sourceToTarget(act_i, temp);
157 temp_output[i]=temp;
158 if(temp.size()>max)
159 max=temp.size();
160 //result.col(i) = gsAsConstMatrix<index_t>(temp, temp.size(), 1 ).cast<index_t>();
161 }
162 result.resize(max,u.cols());
163 for(index_t i = 0; i < result.cols(); i++)
164 for (index_t j = 0; j < result.rows();j++)
165 if (size_t(j) < temp_output[i].size())
166 result(j,i) = temp_output[i][j];
167 else
168 result(j,i) = 0 ;
169}
170
171template<short_t d,class T>
172void gsMappedBasis<d,T>::eval_into(const index_t patch, const gsMatrix<T> & u, gsMatrix<T>& result ) const
173{
174 gsMatrix<index_t> bact;
175 std::vector<index_t> act, act0;
176 gsMatrix<T> beval, map;//r:B,c:C
177 const index_t shift=_getFirstLocalIndex(patch);
178
179 gsVector<index_t> numAct;
180 std::vector<gsMatrix<T>> result_tmp;
181 result_tmp.resize(u.cols());
182 numAct.resize(u.cols());
183 for (index_t i = 0; i!=u.cols(); ++i)
184 {
185 m_bases[patch]->active_into(u.col(i), bact);
186 act0 = std::vector<index_t>(bact.data(), bact.data()+bact.rows());
187 m_bases[patch]->eval_into(u.col(i), beval);
188 std::transform(act0.begin(), act0.end(), act0.begin(),
189 GS_BIND2ND(std::plus<index_t>(), shift));
190
191 m_mapper->fastSourceToTarget(act0,act);
192 m_mapper->getLocalMap(act0, act, map);
193 result_tmp[i] = map.transpose() * beval; // todo: remove transpose()
194 numAct[i] = result_tmp[i].rows();
195 }
196
197 result.setZero(numAct.maxCoeff(), u.cols());
198 for (index_t i = 0; i!=u.cols(); ++i)
199 for(index_t j = 0; j != result_tmp[i].rows(); j++) // result_tmp[i] == dim(rows,1)
200 result(j,i) = result_tmp[i](j,0);
201
202}
203
204template<short_t d,class T>
205void gsMappedBasis<d,T>::deriv_into(const index_t patch, const gsMatrix<T> & u, gsMatrix<T>& result ) const
206{
207 gsMatrix<index_t> actives;
208 gsMatrix<T> curr_res;
209 active_into(patch,u,actives);
210 index_t rows = actives.rows();
211 index_t cols = actives.cols();
212 result.setZero(d*rows,cols);
213 for(index_t j = 0; j<cols; j++) // For all points u.col(j)
214 {
215 const gsMatrix<T> & curr_u = u.col(j);
216 for(index_t i = 0; i<rows; i++) // For all actives at the point
217 {
218 if(actives(i,j)==0&&i>0)
219 continue;
220 derivSingle_into(patch, actives(i,j), curr_u, curr_res); // Evaluate N_j(u_i)
221 result.block(i*d,j,d,1).noalias() = curr_res;
222 }
223 }
224}
225
226template<short_t d,class T>
227void gsMappedBasis<d,T>::deriv2_into(const index_t patch, const gsMatrix<T> & u, gsMatrix<T>& result ) const
228{
229 gsMatrix<index_t> bact;
230 m_bases[patch]->active_into(u, bact);
231 std::vector<index_t> act, act0(bact.data(), bact.data()+bact.rows());
232 const index_t shift=_getFirstLocalIndex(patch);
233 std::transform(act0.begin(), act0.end(), act0.begin(),
234 GS_BIND2ND(std::plus<index_t>(), shift));
235 m_mapper->fastSourceToTarget(act0,act);
236 gsMatrix<T> map;//r:B,c:C
237 m_mapper->getLocalMap(act0, act, map);
238
239 m_bases[patch]->deriv2_into(u, result);
240 index_t nr = bact.rows();
241 const index_t nc = bact.cols();
242
243 static const index_t sd = d*(d+1)/2;
244
245 const index_t mr = map.cols();
246 gsMatrix<T> tmp(sd*mr, nc);
247
248 for (unsigned i = 0; i!=sd; ++i)
249 {
250 gsEigen::Map<typename gsMatrix<T>::Base, 0, gsEigen::Stride<-1,sd> >
251 s(result.data()+i, nr, nc, gsEigen::Stride<-1,sd>(sd*nr,sd) );
252 gsEigen::Map<typename gsMatrix<T>::Base, 0, gsEigen::Stride<-1,sd> >
253 t(tmp.data()+i, mr, nc, gsEigen::Stride<-1,sd>(sd*mr,sd) );
254 t = map.transpose() * s; //.noalias() bug
255 }
256
257 result.swap(tmp);
258}
259
260template<short_t d,class T>
261void gsMappedBasis<d,T>::evalSingle_into(const index_t patch, const index_t global_BF, const gsMatrix<T> & u, gsMatrix<T>& result ) const
262{
263 BasisType * this_patch = m_bases[patch];
264 index_t start = _getFirstLocalIndex(patch), end = _getLastLocalIndex(patch);
265 result.setZero(1,u.cols());
266 if ( m_mapper->targetIsId(global_BF) )
267 {
268 IndexContainer indlist;
269 m_mapper->targetToSource(global_BF, indlist);
270 if(start <= indlist[0] && indlist[0] <= end)
271 this_patch->evalSingle_into(_getPatchIndex(indlist[0]), u, result);
272 else
273 result.setZero(1,u.cols());
274 }
275 else
276 {
277 gsMatrix<T> allLocals;
278 gsMatrix<index_t> pActive;
279 for (index_t k = 0; k != u.cols(); k++)
280 {
281 this_patch->eval_into(u.col(k), allLocals);
282 this_patch->active_into(u.col(k), pActive);
283 gsSparseMatrix<T> L(allLocals.cols(),localSize()), Coefs(size(),1);
284 const index_t offset = _getFirstLocalIndex(patch);
285 for(index_t p = 0;p<allLocals.cols();++p)
286 for(index_t j=0;j<pActive.rows();++j)
287 L(p,pActive(j,p)+offset)=allLocals(j,p);
288 Coefs(global_BF,0)=1;
289 gsSparseMatrix<T> temp = L*(m_mapper->asMatrix())*Coefs;
290 result.col(k) = temp.transpose().toDense();
291 }
292 }
293}
294
295template<short_t d,class T>
296void gsMappedBasis<d,T>::derivSingle_into(const index_t patch, const index_t global_BF, const gsMatrix<T> & u, gsMatrix<T>& result ) const
297{
298 BasisType * this_patch = m_bases[patch];
299 index_t start = _getFirstLocalIndex(patch), end = _getLastLocalIndex(patch);
300 if ( m_mapper->targetIsId(global_BF) )
301 {
302 IndexContainer indlist;
303 m_mapper->targetToSource(global_BF, indlist);
304 if(start <= indlist[0] && indlist[0] <= end)
305 this_patch->derivSingle_into(_getPatchIndex(indlist[0]), u, result);
306 else
307 result.setZero(d,u.cols());
308 }
309 else
310 {
311 gsMatrix<T> allLocals;
312 gsMatrix<index_t> pActive;
313 this_patch->deriv_into(u, allLocals);
314 this_patch->active_into(u, pActive);
315 gsSparseMatrix<T> L(2*allLocals.cols(),localSize()),Coefs(size(),1);
316 const index_t offset = _getFirstLocalIndex(patch);
317 for(index_t p = 0;p<allLocals.cols();++p)
318 for(index_t j=0;j<pActive.rows();++j)
319 {
320 L(2*p,pActive(j,p)+offset)=allLocals(2*j,p);
321 L(2*p+1,pActive(j,p)+offset)=allLocals(2*j+1,p);
322 }
323 Coefs(global_BF,0)=1;
324 gsSparseMatrix<T> temp = L*(m_mapper->asMatrix())*Coefs;
325 result = temp.toDense();
326 }
327}
328
329template<short_t d,class T>
330void gsMappedBasis<d,T>::deriv2Single_into(const index_t patch, const index_t global_BF, const gsMatrix<T> & u, gsMatrix<T>& result ) const
331{
332 const index_t blocksize = d*(d + 1)/2;
333 BasisType * this_patch = m_bases[patch];
334 index_t start = _getFirstLocalIndex(patch), end = _getLastLocalIndex(patch);
335 if ( m_mapper->targetIsId(global_BF) )
336 {
337 IndexContainer indlist;
338 m_mapper->targetToSource(global_BF, indlist);
339 if(start <= indlist[0] && indlist[0] <= end)
340 this_patch->deriv2Single_into(_getPatchIndex(indlist[0]), u, result);
341 else
342 result.setZero(blocksize,u.cols());
343 }
344 else
345 {
346 gsMatrix<T> allLocals;
347 gsMatrix<index_t> pActive;
348 this_patch->deriv2_into(u, allLocals);
349 this_patch->active_into(u, pActive);
350 gsSparseMatrix<T> L(3*allLocals.cols(),localSize()),Coefs(size(),1);
351 const index_t offset = _getFirstLocalIndex(patch);
352 for(index_t p = 0;p<allLocals.cols();++p)
353 for(index_t j=0;j<pActive.rows();++j)
354 {
355 L(3*p,pActive(j,p)+offset)=allLocals(3*j,p);
356 L(3*p+1,pActive(j,p)+offset)=allLocals(3*j+1,p);
357 L(3*p+2,pActive(j,p)+offset)=allLocals(3*j+2,p);
358 }
359 Coefs(global_BF,0)=1;
360 gsSparseMatrix<T> temp = L*(m_mapper->asMatrix())*Coefs;
361 result = temp.toDense();
362 }
363}
364
365template<short_t d,class T>
366void gsMappedBasis<d,T>::evalAllDers_into(const index_t patch, const gsMatrix<T> & u,
367 const index_t n, std::vector<gsMatrix<T> >& result, bool sameElement) const
368{
369 gsMatrix<index_t> bact;
370 m_bases[patch]->active_into(u, bact);
371 std::vector<index_t> act, act0(bact.data(), bact.data()+bact.rows());
372 const index_t shift=_getFirstLocalIndex(patch);
373 std::transform(act0.begin(), act0.end(), act0.begin(),
374 GS_BIND2ND(std::plus<index_t>(), shift));
375 m_mapper->fastSourceToTarget(act0,act);
376 gsMatrix<T> map;//r:B,c:C
377 m_mapper->getLocalMap(act0, act, map);
378
379 m_bases[patch]->evalAllDers_into(u, n, result, sameElement);
380 index_t nr = result.front().rows();
381 const index_t nc = result.front().cols();
382 result.front() = map.transpose() * result.front();
383
384 if ( n>0 )
385 {
386 const index_t mr = map.cols();
387 gsMatrix<T> tmp(d*mr, nc);
388
389 for (index_t i = 0; i!=d; ++i)
390 {
391 gsEigen::Map<typename gsMatrix<T>::Base, 0, gsEigen::Stride<-1,d> >
392 s(result[1].data()+i, nr, nc, gsEigen::Stride<-1,d>(d*nr,d) );
393 gsEigen::Map<typename gsMatrix<T>::Base, 0, gsEigen::Stride<-1,d> >
394 t(tmp.data()+i, mr, nc, gsEigen::Stride<-1,d>(d*mr,d) );
395 t = map.transpose() * s; //.noalias() bug
396 }
397 result[1].swap(tmp);
398
399 if ( n>1 )
400 {
401 static const index_t sd = d*(d+1)/2;
402 tmp.resize(sd*mr, nc);
403
404 for (index_t i = 0; i!=sd; ++i)
405 {
406 gsEigen::Map<typename gsMatrix<T>::Base, 0, gsEigen::Stride<-1,sd> >
407 s(result[2].data()+i, nr, nc, gsEigen::Stride<-1,sd>(sd*nr,sd) );
408 gsEigen::Map<typename gsMatrix<T>::Base, 0, gsEigen::Stride<-1,sd> >
409 t(tmp.data()+i, mr, nc, gsEigen::Stride<-1,sd>(sd*mr,sd) );
410 t = map.transpose() * s; //.noalias() bug
411 }
412 result[2].swap(tmp);
413 }
414 }
415 GISMO_ASSERT( n < 3, "gsMappedBasis::evalAllDers() not implemented for 2<n." );
416}
417
418template<short_t d,class T>
419void gsMappedBasis<d,T>::evalAllDersSingle_into(const index_t patch, const index_t global_BF, const gsMatrix<T> & u,const index_t n, std::vector<gsMatrix<T> >& result ) const
420{
421 GISMO_ASSERT( n<2, "gsTensorBasis::evalAllDers() not implemented for 1<n." );
422 result.resize(n);
423 // result.resize(( 2*n + 1 ), u.cols());
424 BasisType * this_patch = m_bases[patch];
425 // result.setZero();
426 IndexContainer allLocalIndizes,localIndizes;
427 WeightContainer allWeights,weights;
428 gsMatrix<T> res;
429 m_mapper->targetToSource(global_BF,allLocalIndizes,allWeights);
430 const index_t start = _getFirstLocalIndex(patch);
431 const index_t end = _getLastLocalIndex(patch);
432 for(size_t i = 0;i<allLocalIndizes.size();++i)
433 if(allLocalIndizes[i]>=start && allLocalIndizes[i]<=end)
434 {
435 weights.push_back(allWeights[i]);
436 localIndizes.push_back(allLocalIndizes[i]);
437 }
438 for(index_t i=0;i<=n;i++)
439 {
440 ConstWeightIter wIter = weights.begin();
441 for(ConstIndexIter it=localIndizes.begin();it!=localIndizes.end();++it)
442 {
443 if(i==0)
444 {
445 this_patch->evalSingle_into(_getPatchIndex(*it),u,res);
446 result[i].resize(1,u.cols());
447 }
448 else if(i==1)
449 {
450 this_patch->derivSingle_into(_getPatchIndex(*it),u,res);
451 result[i].resize(d,u.cols());
452 }
453 else
454 GISMO_ERROR("only for n<2");
455 for(index_t j=0;j<u.cols();j++)
456 {
457 result[i].col(j)+=res.col(j)*(*wIter);
458 }
459 ++wIter;
460 }
461 }
462}
463
464template<short_t d,class T>
465std::ostream & gsMappedBasis<d,T>::print(std::ostream &os) const
466{
467 os << "gsMappedBasis:\n";
468 os << "\t Local size: "<<this->localSize()<<"\n";
469 os << "\t Global size: "<<this->globalSize()<<"\n";
470 return os;
471}
472
473template<short_t d,class T>
474index_t gsMappedBasis<d,T>::_getPatch(const index_t localIndex) const
475{
476 size_t patch;
477 index_t patchIndex=localIndex;
478 for(patch=0;patch<m_bases.size();patch++)
479 {
480 if(patchIndex>=static_cast<index_t>(m_bases[patch]->size()))
481 patchIndex-=m_bases[patch]->size();
482 else
483 break;
484 }
485 return patch;
486}
487
488template<short_t d,class T>
489index_t gsMappedBasis<d,T>::getGlobalIndex(index_t patch, index_t localIndex)
490{
491 GISMO_ASSERT(patch>=0 && patch<(index_t)m_bases.size(),"patch index out of range");
492 return _getLocalIndex(patch, localIndex);
493}
494
495template<short_t d,class T>
496gsMatrix<index_t> gsMappedBasis<d,T>::getGlobalIndex(index_t patch, gsMatrix<index_t> localIndices)
497{
498 GISMO_ASSERT(patch>=0 && patch<(index_t)m_bases.size(),"patch index out of range");
499 gsMatrix<index_t> globalIndices(localIndices);
500 globalIndices.array() += _getFirstLocalIndex(patch);
501 return globalIndices;
502}
503
504template<short_t d,class T>
505index_t gsMappedBasis<d,T>::_getPatchIndex(const index_t localIndex) const
506{
507 index_t patchIndex=localIndex;
508 for(index_t i = 0;i<_getPatch(localIndex);i++)
509 patchIndex-=m_bases[i]->size();
510 return patchIndex;
511}
512
513template<short_t d,class T>
514index_t gsMappedBasis<d,T>::_getFirstLocalIndex(index_t const patch) const
515{
516 index_t index=0;
517 for(index_t i=0;i<patch;i++)
518 index+=m_bases[i]->size();
519 return index;
520}
521
522} // namespace gismo
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_ERROR(message)
Definition gsDebug.h:118
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Utility class which holds I/O XML data to read/write to/from files.
Provides declaration of Basis abstract interface.
The G+Smo namespace, containing all definitions for the library.
S give(S &x)
Definition gsMemory.h:266
void freeAll(It begin, It end)
Frees all pointers in the range [begin end)
Definition gsMemory.h:312