G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsPrimalSystem.hpp
Go to the documentation of this file.
1 
14 #pragma once
15 
16 namespace gismo
17 {
18 
19 template <class T>
21  : m_localMatrix(nPrimalDofs,nPrimalDofs), m_eliminatePointwiseConstraints(false)
22 {
23  this->m_localRhs.setZero(nPrimalDofs,1);
24 }
25 
26 template <class T>
28  const std::vector<SparseVector>& primalConstraints,
29  bool eliminatePointwiseConstraints,
30  const SparseMatrix& localMatrix,
31  SparseMatrix& modifiedLocalMatrix,
32  SparseMatrix& localEmbedding,
33  SparseMatrix& embeddingForBasis,
34  Matrix& rhsForBasis
35  )
36 {
37  const index_t localDofs = localMatrix.rows();
38  const index_t nrPrimalConstraints = primalConstraints.size();
39 
40  // Which dofs should we eliminate?
41  index_t nElimDofs = 0;
42  std::vector<bool> eliminatedDof(localDofs, false);
43  std::vector<bool> eliminatedConstaint(nrPrimalConstraints, false);
44 
45  {
46  gsSparseEntries<T> seModifiedLocalMatrix;
47  seModifiedLocalMatrix.reserve( localMatrix.nonZeros() + nrPrimalConstraints * localDofs );
48 
49  if (eliminatePointwiseConstraints)
50  {
51  for (index_t i=0; i!=nrPrimalConstraints; ++i)
52  {
53  if (primalConstraints[i].nonZeros() == 1)
54  {
55  typename SparseVector::InnerIterator it(primalConstraints[i]);
56  // mark dof and constraint as to be eliminated
57  eliminatedDof[it.row()] = true;
58  eliminatedConstaint[i] = true;
59  // set diagonal matrix of new matrix
60  seModifiedLocalMatrix.add(it.row(),it.row(),(T)1);
61  ++nElimDofs;
62  }
63  }
64  }
65 
66  // Copy entries of local matrix if not eliminated
67  for (index_t i=0; i!=localDofs; ++i)
68  for (typename SparseMatrix::InnerIterator it(localMatrix,i); it; ++it)
69  if ( !eliminatedDof[it.row()] && !eliminatedDof[it.col()] )
70  seModifiedLocalMatrix.add(it.row(), it.col(), it.value());
71 
72  // Make saddle point for non-eliminated primal constraints
73  for (index_t i=0, j=0; i!=nrPrimalConstraints; ++i)
74  {
75  if ( !eliminatedConstaint[i] )
76  {
77  for (typename SparseVector::InnerIterator it(primalConstraints[i]); it; ++it)
78  {
79  if ( !eliminatedDof[it.row()] )
80  {
81  seModifiedLocalMatrix.add(it.row(), localDofs+j, it.value());
82  seModifiedLocalMatrix.add(localDofs+j, it.row(), it.value());
83  }
84  }
85  ++j;
86  }
87  }
88 
89  modifiedLocalMatrix.clear();
90  modifiedLocalMatrix.resize(localDofs+nrPrimalConstraints-nElimDofs, localDofs+nrPrimalConstraints-nElimDofs);
91  modifiedLocalMatrix.setFrom(seModifiedLocalMatrix);
92  modifiedLocalMatrix.makeCompressed();
93  }
94 
95  // Compute the embedding matrices
96  {
97  localEmbedding.clear();
98  localEmbedding.resize(localDofs+nrPrimalConstraints-nElimDofs,localDofs);
99  embeddingForBasis.clear();
100  embeddingForBasis.resize(localDofs+nrPrimalConstraints-nElimDofs,localDofs);
101  gsSparseEntries<T> seLocalEmbedding, seEmbeddingForBasis;
102  seLocalEmbedding.reserve(localDofs-nElimDofs);
103  seEmbeddingForBasis.reserve(localDofs);
104  for (index_t i=0; i!=localDofs; ++i)
105  {
106  if ( !eliminatedDof[i] )
107  seLocalEmbedding.add(i,i,(T)1);
108  seEmbeddingForBasis.add(i,i,(T)1);
109  }
110  localEmbedding.setFrom(seLocalEmbedding);
111  localEmbedding.makeCompressed();
112  embeddingForBasis.setFrom(seEmbeddingForBasis);
113  embeddingForBasis.makeCompressed();
114  }
115 
116  // Compute rhs for basis
117  rhsForBasis.setZero(localDofs+nrPrimalConstraints-nElimDofs,nrPrimalConstraints);
118  for (index_t i=0, j=0; i!=nrPrimalConstraints; ++i)
119  {
120  if ( eliminatedConstaint[i] )
121  {
122  typename SparseVector::InnerIterator it(primalConstraints[i]);
123  const index_t idx = it.row();
124  for (typename SparseMatrix::InnerIterator it2(localMatrix, idx); it2; ++it2)
125  {
126  if ( !eliminatedDof[it2.row()] )
127  rhsForBasis(it2.row(),i) = - it2.value();
128  }
129  rhsForBasis(idx,i) = (T)1;
130  }
131  else
132  {
133  rhsForBasis(localDofs+j,i) = (T)1;
134  ++j;
135  }
136  }
137 }
138 
139 template <class T>
142  OpPtr localSaddlePointSolver,
143  const SparseMatrix& embeddingForBasis,
144  const Matrix& rhsForBasis,
145  const std::vector<index_t>& primalDofIndices,
146  index_t nPrimalDofs
147  )
148 {
149  const index_t nrPrimalConstraints = primalDofIndices.size();
150  const index_t localDofs = embeddingForBasis.cols();
151 
152  GISMO_ASSERT( nrPrimalConstraints<=nPrimalDofs, "gsPrimalSystem::primalBasis: "
153  "There are more local constraints that there are constraints in total. "
154  "Forgot to call gsPrimalSystem::init()?" );
155 
156  SparseMatrix result( localDofs, nPrimalDofs );
157 
158  if (nPrimalDofs==0||rhsForBasis.cols()==0) return result;
159 
160  Matrix tmp;
161  localSaddlePointSolver->apply(rhsForBasis, tmp);
162  Matrix basis = embeddingForBasis.transpose() * tmp;
163 
164  gsSparseEntries<T> se_result;
165  se_result.reserve(localDofs*nrPrimalConstraints);
166  for (index_t i=0; i<localDofs; ++i)
167  for (index_t j=0; j<nrPrimalConstraints; ++j)
168  {
169  GISMO_ASSERT( primalDofIndices[j]>=0 && primalDofIndices[j]<nPrimalDofs,
170  "gsPrimalSystem::primalBasis: Invalid index.");
171  se_result.add(i,primalDofIndices[j],basis(i,j));
172  }
173 
174  result.setFrom(se_result);
175  return result;
176 }
177 
178 template <class T>
180  const JumpMatrix& jumpMatrix,
181  const SparseMatrix& localMatrix,
182  const Matrix& localRhs,
183  SparseMatrix primalBasis,
184  OpPtr embedding
185  )
186 {
187  if (m_jumpMatrix.rows()==0&&m_jumpMatrix.cols()==0)
188  m_jumpMatrix.resize(jumpMatrix.rows(),nPrimalDofs());
189 
190  GISMO_ASSERT( primalBasis.cols() == m_jumpMatrix.cols(),
191  "gsPrimalSystem::incorporate: The given problem size does not match the stored primal problem size. "
192  "Forgot to call gsPrimalSystem::init()?" );
193 
194  m_localMatrix += primalBasis.transpose() * localMatrix * primalBasis;
195  m_localRhs += primalBasis.transpose() * localRhs;
196  m_jumpMatrix += JumpMatrix(jumpMatrix * primalBasis);
197  m_primalBases.push_back(give(primalBasis));
198  m_embeddings.push_back(give(embedding));
199 }
200 
201 template <class T>
203  const std::vector<SparseVector>& primalConstraints,
204  const std::vector<index_t>& primalDofIndices,
205  JumpMatrix& jumpMatrix,
206  SparseMatrix& localMatrix,
207  Matrix& localRhs
208  )
209 {
210  SparseMatrix modifiedLocalMatrix, localEmbedding, embeddingForBasis;
211  Matrix rhsForBasis;
212 
213  incorporateConstraints(primalConstraints,eliminatePointwiseConstraints(),
214  localMatrix,
215  modifiedLocalMatrix,localEmbedding,embeddingForBasis,rhsForBasis);
216 
217  addContribution(
218  jumpMatrix, localMatrix, localRhs,
219  primalBasis(
220  makeSparseLUSolver(modifiedLocalMatrix),
221  embeddingForBasis, rhsForBasis, primalDofIndices, nPrimalDofs()
222  )
223  );
224 
225  localMatrix = give(modifiedLocalMatrix);
226  localRhs = localEmbedding * localRhs;
227  jumpMatrix = jumpMatrix * localEmbedding.transpose();
228 }
229 
230 template <class T>
231 std::vector<typename gsPrimalSystem<T>::Matrix>
233 {
234  const index_t sz = this->m_primalBases.size();
235 
236  // If the primal problem is empty, there might just not be any primal subdomain
237  if (static_cast<index_t>(sol.size())==sz && this->m_jumpMatrix.cols()==0)
238  return sol;
239 
240  GISMO_ASSERT(static_cast<index_t>(sol.size())==sz+1, "gsPrimalSystem::distributePrimalSolution "
241  "expects that there is one more subdomain that patches.");
242 
243  for (index_t i=0; i<sz; ++i)
244  {
245  GISMO_ASSERT( sol[i].rows() >= this->m_primalBases[i].rows()
246  && this->m_primalBases[i].cols() == sol.back().rows()
247  && sol.back().cols() == sol[i].cols(),
248  "gsPrimalSystem::distributePrimalSolution: Dimensions do not agree: "
249  << sol[i].rows() << ">=" << this->m_primalBases[i].rows() << "&&"
250  << this->m_primalBases[i].cols() << "==" << sol.back().rows() << "&&"
251  << sol.back().cols() << "==" << sol[i].cols() << " ( i=" << i << "). "
252  << "This method assumes the primal subspace to be the last one." );
253 
254  if (m_embeddings[i])
255  {
256  Matrix tmp;
257  m_embeddings[i]->apply(sol[i],tmp);
258  sol[i].swap(tmp);
259  }
260  else
261  sol[i].conservativeResize( this->m_primalBases[i].rows(), gsEigen::NoChange );
262  sol[i] += this->m_primalBases[i] * sol.back();
263  }
264 
265  sol.pop_back();
266 
267  return sol;
268 }
269 
270 
271 } // namespace gismo
Class that provides a container for triplets (i,j,value) to be filled in a sparse matrix...
Definition: gsSparseMatrix.h:33
memory::shared_ptr< Op > OpPtr
Shared pointer to linear operator.
Definition: gsPrimalSystem.h:90
void addContribution(const JumpMatrix &jumpMatrix, const SparseMatrix &localMatrix, const Matrix &localRhs, SparseMatrix primalBasis, OpPtr embedding=OpPtr())
Adds contributions for a patch to the data hold in the class.
Definition: gsPrimalSystem.hpp:179
S give(S &x)
Definition: gsMemory.h:266
#define index_t
Definition: gsConfig.h:32
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
void handleConstraints(const std::vector< SparseVector > &primalConstraints, const std::vector< index_t > &primalDofIndices, JumpMatrix &jumpMatrix, SparseMatrix &localMatrix, Matrix &localRhs)
Convenience function for handling the primal constraints.
Definition: gsPrimalSystem.hpp:202
static gsSparseMatrix< T > primalBasis(OpPtr localSaddlePointSolver, const SparseMatrix &embeddingForBasis, const Matrix &rhsForBasis, const std::vector< index_t > &primalDofIndices, index_t nPrimalDofs)
Returns the matrix representation of the energy minimizing primal basis.
Definition: gsPrimalSystem.hpp:141
static void incorporateConstraints(const std::vector< SparseVector > &primalConstraints, bool eliminatePointwiseConstraints, const SparseMatrix &localMatrix, SparseMatrix &modifiedLocalMatrix, SparseMatrix &localEmbedding, SparseMatrix &embeddingForBasis, Matrix &rhsForBasis)
Incorporates the given constraints in the local system.
Definition: gsPrimalSystem.hpp:27
gsPrimalSystem(index_t nPrimalDofs)
Constructor.
Definition: gsPrimalSystem.hpp:20
Matrix m_localRhs
The right-hand side for the primal problem.
Definition: gsPrimalSystem.h:292
std::vector< Matrix > distributePrimalSolution(std::vector< Matrix > sol)
Distributes the given solution for K+1 subdomains to the K patches.
Definition: gsPrimalSystem.hpp:232