G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsPrimalSystem.hpp
Go to the documentation of this file.
1
14#pragma once
15
16namespace gismo
17{
18
19template <class T>
21 : m_localMatrix(nPrimalDofs,nPrimalDofs), m_eliminatePointwiseConstraints(false)
22{
23 this->m_localRhs.setZero(nPrimalDofs,1);
24}
25
26template <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
139template <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
178template <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
201template <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
230template <class T>
231std::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
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
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
memory::shared_ptr< Op > OpPtr
Shared pointer to linear operator.
Definition gsPrimalSystem.h:90
gsPrimalSystem(index_t nPrimalDofs)
Constructor.
Definition gsPrimalSystem.hpp:20
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
std::vector< Matrix > distributePrimalSolution(std::vector< Matrix > sol)
Distributes the given solution for K+1 subdomains to the K patches.
Definition gsPrimalSystem.hpp:232
Matrix m_localRhs
The right-hand side for the primal problem.
Definition gsPrimalSystem.h:292
Class that provides a container for triplets (i,j,value) to be filled in a sparse matrix.
Definition gsSparseMatrix.h:34
#define index_t
Definition gsConfig.h:32
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
The G+Smo namespace, containing all definitions for the library.
S give(S &x)
Definition gsMemory.h:266