G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsIetiMapper.hpp
Go to the documentation of this file.
1
14#pragma once
15
18
19/* Concerning the status flag m_status:
20 * (m_status&1)!=0 means that the object has been initialized by calling init or the value constructor
21 * (m_status&2)!=0 means that the jump matrices have been computed
22 * (m_status&4)!=0 means that corners have been set up as primal constraints
23 * (m_status&flag)!=0 for flag = 8, 16,... means that edges, faces, ... have been set up as primal constraints
24 */
25
26namespace gismo
27{
28
29template <class T>
31 const gsMultiBasis<T>& multiBasis,
32 gsDofMapper dofMapperGlobal,
33 const Matrix& fixedPart
34 )
35{
36 GISMO_ASSERT( dofMapperGlobal.componentsSize() == 1, "gsIetiMapper::init: "
37 "Got only 1 multi basis, so a gsDofMapper with only 1 component is expected." );
38 GISMO_ASSERT( dofMapperGlobal.numPatches() == multiBasis.nBases(), "gsIetiMapper::init: "
39 "Number of patches does not agree." );
40
41 const index_t nPatches = dofMapperGlobal.numPatches();
42 m_multiBasis = &multiBasis;
43 m_dofMapperGlobal = give(dofMapperGlobal);
44 m_dofMapperLocal.clear();
45 m_dofMapperLocal.resize(nPatches);
46 m_fixedPart.clear();
47 m_fixedPart.resize(nPatches);
48 m_jumpMatrices.clear();
49 m_nPrimalDofs = 0;
50 m_primalConstraints.clear();
51 m_primalConstraints.resize(nPatches);
52 m_primalDofIndices.clear();
53 m_primalDofIndices.resize(nPatches);
54 m_status = 1;
55
56 for (index_t k=0; k<nPatches; ++k)
57 {
58 const index_t nDofs = m_dofMapperGlobal.patchSize(k);
59 GISMO_ASSERT( nDofs==m_multiBasis->piece(k).size(), "gsIetiMapper::init: "
60 "The mapper for patch "<<k<<" has not as many dofs as the corresponding basis." );
61
62 m_dofMapperLocal[k].setIdentity(1,nDofs);
63
64 // Eliminate boundary dofs (we do not consider the full floating case).
65 for (index_t i=0; i<nDofs; ++i)
66 {
67 const index_t idx = m_dofMapperGlobal.index(i,k);
68 if (m_dofMapperGlobal.is_boundary_index(idx))
69 m_dofMapperLocal[k].eliminateDof(i,0);
70 }
71 m_dofMapperLocal[k].finalize();
72
73 const index_t szFixedPart = m_dofMapperLocal[k].boundarySize();
74 m_fixedPart[k].setZero(szFixedPart,1);
75 for (index_t i=0; i<nDofs; ++i)
76 {
77 const index_t idx = m_dofMapperGlobal.index(i,k);
78 if (m_dofMapperGlobal.is_boundary_index(idx))
79 {
80 const index_t globalBoundaryIdx = m_dofMapperGlobal.bindex(i,k);
81 const index_t localBoundaryIdx = m_dofMapperLocal[k].bindex(i,0);
82 m_fixedPart[k](localBoundaryIdx,0) = fixedPart(globalBoundaryIdx,0);
83 }
84 }
85 }
86}
87
88
89template <class T>
91gsIetiMapper<T>::constructGlobalSolutionFromLocalSolutions( const std::vector<Matrix>& localContribs )
92{
93 GISMO_ASSERT( m_status&1, "gsIetiMapper: The class has not been initialized." );
94
95 const index_t nPatches = m_dofMapperGlobal.numPatches();
96 GISMO_ASSERT( nPatches == static_cast<index_t>(localContribs.size()),
97 "gsIetiMapper::constructGlobalSolutionFromLocalSolutions; The number of local contributions does "
98 "not argee with the number of patches." );
99
100 Matrix result;
101 result.setZero( m_dofMapperGlobal.freeSize(), localContribs[0].cols() );
102
103 for (index_t k=0; k<nPatches; ++k)
104 {
105 const index_t sz=m_dofMapperLocal[k].size();
106 for (index_t i=0; i<sz; ++i)
107 {
108 if (m_dofMapperLocal[k].is_free(i,0) && m_dofMapperGlobal.is_free(i,k))
109 result.row(m_dofMapperGlobal.index(i,k)) = localContribs[k].row(m_dofMapperLocal[k].index(i,0));
110 }
111 }
112 return result;
113}
114
115namespace {
116struct dof_helper {
117 index_t globalIndex;
118 index_t patch;
119 index_t localIndex;
120 bool operator<(const dof_helper& other) const
121 { return globalIndex < other.globalIndex; }
122};
123}
124
125template <class T>
127{
128 GISMO_ASSERT( m_status&1, "gsIetiMapper: The class has not been initialized." );
129 GISMO_ASSERT( !(m_status&4), "gsIetiMapper::cornersAsPrimals: This function has already been called." );
130 m_status |= 4;
131
132 const index_t nPatches = m_dofMapperLocal.size();
133
134 // Construct all corners
135 std::vector<dof_helper> corners;
136 const index_t dim = m_multiBasis->dim();
137 corners.reserve((1<<dim)*nPatches);
138 // Add corners on all patches
139 for (index_t k=0; k<nPatches; ++k)
140 {
141 for (boxCorner it = boxCorner::getFirst(dim); it!=boxCorner::getEnd(dim); ++it)
142 {
143 const index_t idx = (*m_multiBasis)[k].functionAtCorner(it);
144 dof_helper dh;
145 dh.globalIndex = m_dofMapperGlobal.index( idx, k );
146 dh.patch = k;
147 dh.localIndex = m_dofMapperLocal[k].index( idx, 0 );
148 if (m_dofMapperGlobal.is_free_index(dh.globalIndex))
149 corners.push_back(dh);
150 }
151 }
152
153 // Sort corners to collapse corners with same global index
154 std::sort(corners.begin(), corners.end());
155
156 // Create data
157 index_t lastIndex = -1;
158 const index_t sz = corners.size();
159 for (index_t i=0; i<sz; ++i)
160 {
161 if (lastIndex!=corners[i].globalIndex)
162 {
163 lastIndex = corners[i].globalIndex;
164 if (i+1<sz&&corners[i+1].globalIndex==corners[i].globalIndex)
165 ++m_nPrimalDofs;
166 else
167 continue; // Ignore corners that are not shared
168 }
169 const index_t cornerIndex = m_nPrimalDofs - 1;
170 const index_t patch = corners[i].patch;
171 const index_t localIndex = corners[i].localIndex;
172
173 SparseVector constr(m_dofMapperLocal[patch].freeSize());
174 constr[localIndex] = 1;
175
176 m_primalConstraints[patch].push_back(give(constr));
177 m_primalDofIndices[patch].push_back(cornerIndex);
178 }
179
180}
181
182template <class T>
184 const gsGeometry<T>& geo,
185 const gsBasis<T>& basis,
186 const gsDofMapper& dm,
187 boxComponent bc
188)
189{
190 gsMatrix<index_t> indices;
191
193 *(geo.component(bc)),
194 *(basis.componentBasis_withIndices(bc, indices, false))
197 );
198
199 SparseVector constraint( dm.freeSize() );
200 T sum = (T)0;
201 const index_t sz = moments.size();
202 GISMO_ASSERT( sz == indices.size(), "Internal error." );
203 for (index_t i=0; i<sz; ++i)
204 {
205 const index_t idx = dm.index( indices(i,0), 0 );
206 if (dm.is_free_index(idx))
207 {
208 constraint[idx] = moments(i,0);
209 sum += moments(i,0);
210 }
211 }
212 return constraint / sum;
213
214}
215
216
217template <class T>
219{
220 GISMO_ASSERT( m_status&1, "gsIetiMapper: The class has not been initialized." );
221 GISMO_ASSERT( d>0, "gsIetiMapper::interfaceAveragesAsPrimals cannot handle corners." );
222 GISMO_ASSERT( d<=m_multiBasis->dim(), "gsIetiMapper::interfaceAveragesAsPrimals: "
223 "Interfaces cannot have larger dimension than considered object." );
224 GISMO_ASSERT( (index_t)(geo.nPatches()) == m_multiBasis->nPieces(),
225 "gsIetiMapper::interfaceAveragesAsPrimals: The given geometry does not fit.");
226 GISMO_ASSERT( geo.parDim() == m_multiBasis->dim(),
227 "gsIetiMapper::interfaceAveragesAsPrimals: The given geometry does not fit.");
228
229 const unsigned flag = 1<<(2+d);
230 GISMO_ASSERT( !(m_status&flag), "gsIetiMapper::interfaceAveragesAsPrimals: This function has "
231 " already been called for d="<<d );
232 m_status |= flag;
233
234 std::vector< std::vector<patchComponent> > components = geo.allComponents();
235 const index_t nComponents = components.size();
236 for (index_t n=0; n<nComponents; ++n)
237 {
238 const index_t sz = components[n].size();
239 if ( components[n][0].dim() == d && ( sz > 1 || m_multiBasis->dim() == d ))
240 {
241 index_t used = 0;
242 for (index_t i=0; i<sz; ++i)
243 {
244 const index_t k = components[n][i].patch();
245 gsSparseVector<T> constr = assembleAverage(
246 geo[k],
247 (*m_multiBasis)[k],
248 m_dofMapperLocal[k],
249 components[n][i]
250 );
251 if ( constr.nonZeros() > 0 )
252 {
253 m_primalConstraints[k].push_back(give(constr));
254 m_primalDofIndices[k].push_back(m_nPrimalDofs);
255 ++used;
256 }
257 }
258 GISMO_ASSERT( used==0 || used == sz, "Internal error." );
259 if (used)
260 ++m_nPrimalDofs;
261 }
262 }
263}
264
265
266template <class T>
267void gsIetiMapper<T>::customPrimalConstraints( std::vector< std::pair<index_t,SparseVector> > data )
268{
269 GISMO_ASSERT( m_status&1, "gsIetiMapper: The class has not been initialized." );
270
271 const index_t sz = data.size();
272 for (index_t i=0; i<sz; ++i)
273 {
274 const index_t patch = data[i].first;
275 m_primalConstraints[patch].push_back(give(data[i].second));
276 m_primalDofIndices[patch].push_back(m_nPrimalDofs);
277 }
278 ++m_nPrimalDofs;
279}
280
281template <class T>
282std::vector<index_t> gsIetiMapper<T>::skeletonDofs( const index_t patch ) const
283{
284 GISMO_ASSERT( m_status&1, "gsIetiMapper: The class has not been initialized." );
285
286 std::vector<index_t> result;
287 const index_t patchSize = m_dofMapperGlobal.patchSize(patch);
288 const index_t dim = m_multiBasis->dim();
289 result.reserve(2*dim*std::pow(patchSize,(1.0-dim)/dim));
290 for (index_t i=0; i<patchSize; ++i)
291 if ( m_dofMapperGlobal.is_coupled(i,patch) )
292 result.push_back(m_dofMapperLocal[patch].index(i,0));
293 return result;
294}
295
296template <class T>
297void gsIetiMapper<T>::computeJumpMatrices( bool fullyRedundant, bool excludeCorners )
298{
299 GISMO_ASSERT( m_status&1, "gsIetiMapper: The class has not been initialized." );
300
301 GISMO_ASSERT( !(m_status&2), "gsIetiMapper::computeJumpMatrices: This function has already been called." );
302 m_status |= 2;
303
304 const index_t nPatches = m_dofMapperGlobal.numPatches();
305 const index_t coupledSize = m_dofMapperGlobal.coupledSize();
306
307 // Find the groups of to be coupled indices
308 std::vector< std::vector< std::pair<index_t,index_t> > > coupling;
309 coupling.resize(coupledSize);
310
311 for (index_t k=0; k<nPatches; ++k)
312 {
313 const index_t patchSize = m_dofMapperGlobal.patchSize(k);
314 for (index_t i=0; i<patchSize; ++i)
315 {
316 const index_t globalIndex = m_dofMapperGlobal.index(i,k);
317 if ( m_dofMapperGlobal.is_coupled_index(globalIndex) )
318 {
319 const index_t coupledIndex = m_dofMapperGlobal.cindex(i,k);
320 const index_t localIndex = m_dofMapperLocal[k].index(i,0);
321 coupling[coupledIndex].push_back(
322 std::pair<index_t,index_t>(k,localIndex)
323 );
324 }
325 }
326 }
327
328 // Erease data for corners if so desired
329 if (excludeCorners)
330 {
331 const index_t dim = m_multiBasis->dim();
332 for (index_t k=0; k<nPatches; ++k)
333 {
334 for (boxCorner it = boxCorner::getFirst(dim); it!=boxCorner::getEnd(dim); ++it)
335 {
336 const index_t idx = (*m_multiBasis)[k].functionAtCorner(it);
337 const index_t globalIndex = m_dofMapperGlobal.index(idx,k);
338 if ( m_dofMapperGlobal.is_coupled_index(globalIndex) )
339 {
340 const index_t coupledIndex = m_dofMapperGlobal.cindex(idx,k);
341 coupling[coupledIndex].clear();
342 }
343 }
344 }
345 }
346
347 // Compute the number of Lagrange multipliers
348 index_t numLagrangeMult = 0;
349 for (index_t i=0; i<coupledSize; ++i)
350 {
351 const index_t n = coupling[i].size();
352 GISMO_ASSERT( n>1 || excludeCorners, "gsIetiMapper::computeJumpMatrices:"
353 "Found a coupled dof that is not coupled to any other dof." );
354 if (fullyRedundant)
355 numLagrangeMult += (n * (n-1))/2;
356 else
357 numLagrangeMult += n-1;
358 }
359
360 // Compute the jump matrices
361 std::vector< gsSparseEntries<T> > jumpMatrices_se(nPatches);
362 for (index_t i=0; i<nPatches; ++i)
363 {
364 const index_t dim = m_multiBasis->dim();
365 jumpMatrices_se[i].reserve(std::pow(m_dofMapperLocal[i].freeSize(),(1.0-dim)/dim));
366 }
367
368 index_t multiplier = 0;
369 for (index_t i=0; i<coupledSize; ++i)
370 {
371 const index_t n = coupling[i].size();
372 const index_t maxIndex = fullyRedundant ? (n-1) : 1;
373 for (index_t j1=0; j1<maxIndex; ++j1)
374 {
375 const index_t patch1 = coupling[i][j1].first;
376 const index_t localMappedIndex1 = coupling[i][j1].second;
377 for (index_t j2=j1+1; j2<n; ++j2)
378 {
379 const index_t patch2 = coupling[i][j2].first;
380 const index_t localMappedIndex2 = coupling[i][j2].second;
381 jumpMatrices_se[patch1].add(multiplier,localMappedIndex1,(T)1);
382 jumpMatrices_se[patch2].add(multiplier,localMappedIndex2,(T)-1);
383 ++multiplier;
384 }
385 }
386 }
387 GISMO_ASSERT( multiplier == numLagrangeMult, "gsIetiMapper::computeJumpMatrices: Internal error: "
388 << multiplier << "!=" << numLagrangeMult );
389
390 m_jumpMatrices.clear();
391 for (index_t i=0; i<nPatches; ++i)
392 {
393 m_jumpMatrices.push_back(JumpMatrix(numLagrangeMult, m_dofMapperLocal[i].freeSize()));
394 m_jumpMatrices[i].setFrom(jumpMatrices_se[i]);
395 }
396
397}
398
399template <class T>
401{
402 GISMO_ASSERT(localSolution.cols() == m_fixedPart[k].cols(), "gsIetiMapper::incorporateFixedPart: Dimension missmatch.");
403 const std::size_t sz = m_dofMapperLocal[k].totalSize();
404 Matrix coeffs(sz, localSolution.cols());
405 for (std::size_t i = 0; i < sz; ++i)
406 {
407 if ( m_dofMapperLocal[k].is_free(i, 0) )
408 coeffs.row(i) = localSolution.row( m_dofMapperLocal[k].index(i, 0) );
409 else
410 coeffs.row(i) = m_fixedPart[k].row( m_dofMapperLocal[k].bindex(i, 0) );
411 }
412 return coeffs;
413}
414
415
416} // namespace gismo
A basis represents a family of scalar basis functions defined over a common parameter domain.
Definition gsBasis.h:79
std::vector< std::vector< patchComponent > > allComponents(bool combineCorners=false) const
Returns all components representing the topology.
Definition gsBoxTopology.cpp:294
Class defining a globally constant function.
Definition gsConstantFunction.h:34
Maintains a mapping from patch-local dofs to global dof indices and allows the elimination of individ...
Definition gsDofMapper.h:69
size_t numPatches() const
Returns the number of patches present underneath the mapper.
Definition gsDofMapper.h:469
bool is_free_index(index_t gl) const
Returns true if global dof gl is not eliminated.
Definition gsDofMapper.h:376
index_t freeSize() const
Returns the number of free (not eliminated) dofs.
Definition gsDofMapper.h:436
index_t index(index_t i, index_t k=0, index_t c=0) const
Returns the global dof index associated to local dof i of patch k.
Definition gsDofMapper.h:325
Assembles mass and stiffness matrices and right-hand sides on a given domain.
Definition gsGenericAssembler.h:33
const gsMatrix< T > & assembleMoments(const gsFunction< T > &func, index_t patchIndex=-1, bool refresh=true)
Moments assembly routine.
Definition gsGenericAssembler.hpp:93
Abstract base class representing a geometry map.
Definition gsGeometry.h:93
short_t targetDim() const
Dimension of the ambient physical space (overriding gsFunction::targetDim())
Definition gsGeometry.h:286
gsGeometry::uPtr component(boxComponent const &bc) const
Get parametrization of box component bc as a new gsGeometry uPtr.
Definition gsGeometry.hpp:240
Matrix incorporateFixedPart(index_t k, const gsMatrix< T > &localSolution) const
Incorporates fixedPart (eg. from eliminated Dirichlet dofs) to given patch-local solution.
Definition gsIetiMapper.hpp:400
static gsSparseVector< T > assembleAverage(const gsGeometry< T > &geo, const gsBasis< T > &basis, const gsDofMapper &dm, boxComponent bc)
Assembles for interfaceAveragesAsPrimals.
Definition gsIetiMapper.hpp:183
void computeJumpMatrices(bool fullyRedundant, bool excludeCorners)
This function computes the jump matrices.
Definition gsIetiMapper.hpp:297
void interfaceAveragesAsPrimals(const gsMultiPatch< T > &geo, short_t d)
Set up interface averages as primal dofs.
Definition gsIetiMapper.hpp:218
void cornersAsPrimals()
Set up the corners as primal dofs.
Definition gsIetiMapper.hpp:126
void init(const gsMultiBasis< T > &multiBasis, gsDofMapper dofMapperGlobal, const Matrix &fixedPart)
Init the ieti mapper after default construction.
Definition gsIetiMapper.hpp:30
Matrix constructGlobalSolutionFromLocalSolutions(const std::vector< Matrix > &localContribs)
Construct the global solution from a vector of patch-local ones.
Definition gsIetiMapper.hpp:91
void customPrimalConstraints(std::vector< std::pair< index_t, SparseVector > > data)
With this function, the caller can register more primal constraints.
Definition gsIetiMapper.hpp:267
std::vector< index_t > skeletonDofs(index_t patch) const
Returns a list of dofs that are (on the coarse level) coupled.
Definition gsIetiMapper.hpp:282
Holds a set of patch-wise bases and their topology information.
Definition gsMultiBasis.h:37
size_t nBases() const
Number of patch-wise bases.
Definition gsMultiBasis.h:264
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition gsMultiPatch.h:100
short_t parDim() const
Dimension of the parameter domain (must match for all patches).
Definition gsMultiPatch.h:249
size_t nPatches() const
Number of patches.
Definition gsMultiPatch.h:274
Sparse vector class, based on gsEigen::SparseVector.
Definition gsSparseVector.h:35
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
Provides declaration of ConstantFunction class.
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Provides an assembler for common IGA matrices.
The G+Smo namespace, containing all definitions for the library.
S give(S &x)
Definition gsMemory.h:266
Struct which represents a certain component (interior, face, egde, corner).
Definition gsBoundary.h:445
Struct which represents a certain corner of a hyper-cube.
Definition gsBoundary.h:292
static boxCorner getEnd(short_t dim)
helper for iterating on corners of an n-dimensional box
Definition gsBoundary.h:372
static boxCorner getFirst(short_t)
helper for iterating on corners of an n-dimensional box
Definition gsBoundary.h:356