G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsTensorTools.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsCore/gsLinearAlgebra.h>
17 
20 
21 namespace gismo
22 {
23 
26 template <int d>
28 {
29  int result = 0;
30  unsigned stride = 1;
31  for (index_t i = 0; i < idx.size(); ++i)
32  {
33  result += stride * idx[i];
34  stride *= sz[i];
35  }
36  return result;
37 }
38 
49 template <short_t d, typename T>
52  gsSparseMatrix<T,RowMajor> & transfer)
53 {
54  typedef typename gsSparseMatrix<T,RowMajor>::iterator InnerIt;
55  gsSparseEntries<T> entries;
56  gsVector<unsigned, d> oldSize, newSize, v, v_old;
57 
58  for (unsigned i = 0; i < d; ++i)
59  {
60  oldSize[i] = static_cast<unsigned>(B[i].innerSize());
61  newSize[i] = static_cast<unsigned>(B[i].outerSize());
62  }
63 
64  std::vector<InnerIt> it(d);
65 
66  // iterate over all new tensor indices
67  v.setZero();
68  index_t newIdx = 0;
69  do {
70  // set up iterators over component contributions
71  for (unsigned i = 0; i < d; ++i)
72  it[i] = B[i].begin(v[i]);
73 
74  // iterate over the component contributions
75  bool more;
76  do {
77  // get the old tensor index
78  T contrib = (T)(1);
79  for (unsigned i = 0; i < d; ++i)
80  {
81  contrib *= it[i].value();
82  v_old[i] = it[i].index();
83  }
84 
85  const index_t oldIdx = fromTensorIndex<d>(v_old, oldSize);
86  entries.add( newIdx, oldIdx, contrib );
87 
88  // advance iterators
89  more = true;
90  for (unsigned i = 0; i < d; ++i)
91  {
92  ++it[i]; // increase current dimension
93  if (it[i]) // current dimension not yet exhausted?
94  break;
95  else // current dimension exhausted
96  {
97  if (i == d - 1) // was it the last one?
98  more = false; // then all elements exhausted
99  else
100  it[i] = B[i].begin(v[i]); // otherwise, reset this to start and increase the next dimension
101  }
102  }
103  } while (more);
104  } while (++newIdx, nextLexicographic(v, newSize));
105 
106  GISMO_ASSERT( newIdx == (index_t) newSize.prod(), "Iteration did not complete as expected." );
107 
108  transfer.resize( newSize.prod(), oldSize.prod() );
109  transfer.setFrom( entries );
110  transfer.makeCompressed();
111 }
112 
114 template<typename VectIn, typename VectOut> inline
115 void tensorStrides(const VectIn & sz, VectOut & strides)
116 {
117  strides.derived().resize(sz.size());
118  strides[0] = 1;
119  for ( index_t i=1; i != sz.size(); ++i )
120  strides[i] = strides[i-1] * sz[i-1];
121 }
122 
128 template <typename T, int d>
129 void swapTensorDirection( int k1, int k2,
130  gsVector<index_t,d> & sz,
131  gsMatrix<T> & coefs)
132 {
133  GISMO_ASSERT( sz.prod() == coefs.rows(),
134  "Input error, sizes do not match: "<<sz.prod()<<"!="<< coefs.rows() );
135  GISMO_ASSERT( k1<d && k2 < d && k1>=0 && k2>=0,
136  "Invalid directions: "<< k1 <<", "<< k2 );
137 
138  if ( k1 == k2 )
139  return; //Nothing to do
140 
141  /*
142  gsVector<int,d> perm = gsVector<int,d>::LinSpaced(d,0,d-1);
143  std::swap(perm[k1],perm[k2] );
144  permuteTensorVector(perm,sz,coefs);
145  return;
146  */
147 
148  gsGridIterator<index_t,CUBE,d> it(sz);
149 
150  std::swap( sz[k1], sz[k2] );
151  gsVector<index_t,d> perstr;
152  tensorStrides(sz, perstr);
153  std::swap(perstr[k1], perstr[k2] );
154 
155  gsMatrix<T> tmp(coefs.rows(), coefs.cols() );
156 
157  for(index_t r=0; it; ++it, ++r)
158  tmp.row(perstr.dot(*it)) = coefs.row(r);
159 
160  coefs.swap(tmp);
161 }
162 
168 template <typename T, int d>
170  gsVector<index_t,d> & sz,
171  gsMatrix<T> & coefs)
172 {
173  GISMO_ASSERT( sz.prod() == coefs.rows(),
174  "Input error, sizes do not match: "<<sz.prod()<<"!="<< coefs.rows() );
175  GISMO_ASSERT( perm.sum() == sz.size()*(sz.size()-1)/2,
176  "Error in the permutation: "<< perm.transpose());
177 
178  if ( perm == gsVector<index_t>::LinSpaced(sz.size(),0,sz.size()-1) )
179  return; //Nothing to do
180 
181  typename gsVector<index_t>::PermutationWrap P(perm);
182  gsGridIterator<index_t,CUBE,d> it(sz);
183 
184  sz = P * sz;
185  gsVector<index_t,d> perstr;
186  tensorStrides(sz, perstr);
187  perstr = P * perstr;
188 
189  // check: is it better to create a big permutation to apply to coefs ?
190  gsMatrix<T> tmp(coefs.rows(), coefs.cols() );
191 
192  for(index_t r=0; it; ++it, ++r)
193  tmp.row(perstr.dot(*it)) = coefs.row(r);
194 
195  coefs.swap(tmp);
196 }
197 
200 template <typename T, int d>
201 void flipTensorVector(const int dir,
202  const gsVector<index_t,d> & sz,
203  gsMatrix<T> & coefs)
204 {
205  GISMO_ASSERT( sz.prod() == coefs.rows(),
206  "Input error, sizes do not match: "<<sz.prod()<<"!="<< coefs.rows() );
207 
208  gsVector<index_t,d> perstr = sz;
209  perstr[dir] /= 2;
210  gsGridIterator<index_t,CUBE,d> it(perstr);
211  tensorStrides(sz, perstr);//reuse
212  const index_t cc = sz[dir] - 1;
213 
214  for(; it; ++it)
215  {
216  const index_t i1 = perstr.dot(*it);
217  const index_t i2 = i1 + (cc - 2 * it->at(dir)) * perstr[dir];
218  coefs.row( i1 ).swap( coefs.row( i2 ) );
219  }
220 }
221 
222 } // namespace gismo
Class that provides a container for triplets (i,j,value) to be filled in a sparse matrix...
Definition: gsSparseMatrix.h:33
void swapTensorDirection(int k1, int k2, gsVector< index_t, d > &sz, gsMatrix< T > &coefs)
Definition: gsTensorTools.h:129
void flipTensorVector(const int dir, const gsVector< index_t, d > &sz, gsMatrix< T > &coefs)
Flips tensor directions in place.
Definition: gsTensorTools.h:201
#define index_t
Definition: gsConfig.h:32
void tensorStrides(const VectIn &sz, VectOut &strides)
Helper to compute the strides of a d-tensor.
Definition: gsTensorTools.h:115
Provides combinatorial unitilies.
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition: gsVector.h:35
int fromTensorIndex(const gsVector< unsigned, d > &idx, const gsVector< unsigned, d > &sz)
Helper function to compute a lexicographically numbered index from tensor indices.
Definition: gsTensorTools.h:27
bool nextLexicographic(Vec &cur, const Vec &size)
Iterates through a tensor lattice with the given size. Updates cur and returns true if another entry ...
Definition: gsCombinatorics.h:196
void tensorCombineTransferMatrices(gsSparseMatrix< T, RowMajor > B[d], gsSparseMatrix< T, RowMajor > &transfer)
Combine component-wise transfer matrices into a transfer matrix for the tensor product basis...
Definition: gsTensorTools.h:50
void permuteTensorVector(const gsVector< index_t, d > &perm, gsVector< index_t, d > &sz, gsMatrix< T > &coefs)
Definition: gsTensorTools.h:169
This is the main header file that collects wrappers of Eigen for linear algebra.
Provides iteration over integer or numeric points in a (hyper-)cube.