G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsMappedBasis.hpp
Go to the documentation of this file.
1 
15 #include <gsIO/gsFileData.h>
16 
17 namespace gismo
18 {
19 
20 template<short_t d,class T>
21 gsMappedBasis<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 
35 template<short_t d,class T>
36 gsMappedBasis<d,T>::~gsMappedBasis()
37 {
38  freeAll(m_bases);
39  delete m_mapper;
40 }
41 
42 template<short_t d,class T>
43 const 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 
51 template<short_t d,class T>
52 index_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 
60 template<short_t d,class T>
61 short_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 
71 template<short_t d,class T>
72 void 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
87 template<short_t d,class T>
88 void 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
101 template<short_t d,class T>
102 void 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 
119 template<short_t d,class T>
120 gsGeometry<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 
129 template<short_t d,class T>
130 gsMultiPatch<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 
138 template<short_t d,class T>
139 void 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 
171 template<short_t d,class T>
172 void 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 
204 template<short_t d,class T>
205 void 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 
226 template<short_t d,class T>
227 void 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 
260 template<short_t d,class T>
261 void 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 
295 template<short_t d,class T>
296 void 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 
329 template<short_t d,class T>
330 void 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 
365 template<short_t d,class T>
366 void 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 
418 template<short_t d,class T>
419 void gsMappedBasis<d,T>::evalAllDersSingle_into(const index_t patch, const index_t global_BF, const gsMatrix<T> & u,const index_t n,gsMatrix<T> & result ) const
420 {
421  GISMO_ASSERT( n<2, "gsTensorBasis::evalAllDers() not implemented for 1<n." );
422  result.resize(( 2*n + 1 ), u.cols());
423  BasisType * this_patch = m_bases[patch];
424  result.setZero();
425  IndexContainer allLocalIndizes,localIndizes;
426  WeightContainer allWeights,weights;
427  gsMatrix<T> res;
428  m_mapper->targetToSource(global_BF,allLocalIndizes,allWeights);
429  const index_t start = _getFirstLocalIndex(patch);
430  const index_t end = _getLastLocalIndex(patch);
431  for(size_t i = 0;i<allLocalIndizes.size();++i)
432  if(allLocalIndizes[i]>=start && allLocalIndizes[i]<=end)
433  {
434  weights.push_back(allWeights[i]);
435  localIndizes.push_back(allLocalIndizes[i]);
436  }
437  for(index_t i=0;i<=n;i++)
438  {
439  ConstWeightIter wIter = weights.begin();
440  for(ConstIndexIter it=localIndizes.begin();it!=localIndizes.end();++it)
441  {
442  if(i==0)
443  this_patch->evalSingle_into(_getPatchIndex(*it),u,res);
444  else if(i==1)
445  this_patch->derivSingle_into(_getPatchIndex(*it),u,res);
446  else
447  GISMO_ERROR("only for n<2");
448  for(index_t j=0;j<u.cols();j++)
449  {
450  result(i,j)+=res(0,j)*(*wIter);
451  if(i==1)
452  result(i+1,j)+=res(1,j)*(*wIter);
453  }
454  ++wIter;
455  }
456  }
457 }
458 
459 template<short_t d,class T>
460 std::ostream & gsMappedBasis<d,T>::print(std::ostream &os) const
461 {
462  os << "gsMappedBasis:\n";
463  os << "\t Local size: "<<this->localSize()<<"\n";
464  os << "\t Global size: "<<this->globalSize()<<"\n";
465  return os;
466 }
467 
468 template<short_t d,class T>
469 index_t gsMappedBasis<d,T>::_getPatch(const index_t localIndex) const
470 {
471  size_t patch;
472  index_t patchIndex=localIndex;
473  for(patch=0;patch<m_bases.size();patch++)
474  {
475  if(patchIndex>=static_cast<index_t>(m_bases[patch]->size()))
476  patchIndex-=m_bases[patch]->size();
477  else
478  break;
479  }
480  return patch;
481 }
482 
483 template<short_t d,class T>
484 index_t gsMappedBasis<d,T>::_getPatchIndex(const index_t localIndex) const
485 {
486  index_t patchIndex=localIndex;
487  for(index_t i = 0;i<_getPatch(localIndex);i++)
488  patchIndex-=m_bases[i]->size();
489  return patchIndex;
490 }
491 
492 template<short_t d,class T>
493 index_t gsMappedBasis<d,T>::_getFirstLocalIndex(index_t const patch) const
494 {
495  index_t index=0;
496  for(index_t i=0;i<patch;i++)
497  index+=m_bases[i]->size();
498  return index;
499 }
500 
501 } // namespace gismo
#define short_t
Definition: gsConfig.h:35
S give(S &x)
Definition: gsMemory.h:266
#define index_t
Definition: gsConfig.h:32
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Provides declaration of Basis abstract interface.
Utility class which holds I/O XML data to read/write to/from files.
void freeAll(It begin, It end)
Frees all pointers in the range [begin end)
Definition: gsMemory.h:312
#define GISMO_ERROR(message)
Definition: gsDebug.h:118