G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsFlowAssemblerBase.hpp
Go to the documentation of this file.
1
12#pragma once
14
15namespace gismo
16{
17
18template<class T, int MatOrder>
20{
21 m_dofs = 0;
22 m_tarDim = getPatches().dim();
23 m_isInitialized = false;
24 m_isBaseReady = false;
25 m_isSystemReady = false;
26}
27
28
29template<class T, int MatOrder>
30void gsFlowAssemblerBase<T, MatOrder>::computeDirichletDofs(const index_t unk, const index_t basisID, gsMatrix<T>& ddofVector)
31{
32 GISMO_ASSERT(ddofVector.rows() == m_dofMappers[basisID].boundarySize(), "Dirichlet DOF vector has wrong size.");
33
34 const gsDofMapper & mapper = m_dofMappers[basisID];
35 const gsMultiBasis<T> & mbasis = getBases().at(basisID);
36
37 switch (getAssemblerOptions().dirValues)
38 {
39 case dirichlet::homogeneous:
40 ddofVector.setZero();
41 break;
42 case dirichlet::interpolation:
43 computeDirichletDofsIntpl(unk, mapper, mbasis, ddofVector);
44 break;
45 case dirichlet::l2Projection:
46 computeDirichletDofsL2Proj(unk, mapper, mbasis, ddofVector);
47 break;
48 default:
49 GISMO_ERROR("Something went wrong with Dirichlet values.");
50 }
51
52 // Corner values
53 for (typename gsBoundaryConditions<T>::const_citerator
54 it = getBCs().cornerBegin();
55 it != getBCs().cornerEnd(); ++it)
56 {
57 if (it->unknown == unk)
58 {
59 const index_t i = mbasis[it->patch].functionAtCorner(it->corner);
60 const index_t ii = mapper.bindex(i, it->patch);
61 ddofVector.row(ii).setConstant(it->value);
62 }
63 else
64 continue;
65 }
66}
68
69template<class T, int MatOrder>
70void gsFlowAssemblerBase<T, MatOrder>::computeDirichletDofsIntpl(const index_t unk, const gsDofMapper & mapper, const gsMultiBasis<T> & mbasis, gsMatrix<T>& ddofVector)
71{
72 for (typename gsBoundaryConditions<T>::const_iterator
73 it = getBCs().dirichletBegin();
74 it != getBCs().dirichletEnd(); ++it)
75 {
76 if (it->unknown() != unk)
77 continue;
78
79 const index_t patchID = it->patch();
80 const gsBasis<T> & basis = mbasis.piece(patchID);
82 // Get dofs on this boundary
83 gsMatrix<index_t> boundary = basis.boundary(it->side());
84
85 // If the condition is homogeneous then fill with zeros
86 if (it->isHomogeneous())
87 {
88 for (index_t i = 0; i != boundary.size(); ++i)
89 {
90 const index_t ii = mapper.bindex((boundary)(i), it->patch());
91 ddofVector.row(ii).setZero();
92 }
93 continue;
94 }
95
96 // Get the side information
97 short_t dir = it->side().direction();
98 index_t param = (it->side().parameter() ? 1 : 0);
99
100 // Compute grid of points on the face ("face anchors")
101 std::vector< gsVector<T> > rr;
102 rr.reserve(getPatches().parDim());
103
104 for (short_t i = 0; i < getPatches().parDim(); ++i)
106 if (i == dir)
107 {
108 gsVector<T> b(1);
109 b[0] = (basis.component(i).support()) (0, param);
110 rr.push_back(b);
111 }
112 else
113 {
114 rr.push_back(basis.component(i).anchors().transpose());
115 }
116 }
117
118 GISMO_ASSERT(it->function()->targetDim() == ddofVector.cols(),
119 "Given Dirichlet boundary function does not match problem dimension."
120 << it->function()->targetDim() << " != " << ddofVector.cols() << "\n");
121
122 // Compute dirichlet values
123 gsMatrix<T> pts = getPatches().patch(it->patch()).eval(gsPointGrid<T>(rr));
124 gsMatrix<T> fpts;
125 if (!it->parametric())
126 {
127 fpts = it->function()->eval(pts);
128 }
129// else if (it->parametric() && m_params.settings().isIgaDirichletGeometry())
130// {
131// gsMatrix<T> parPts;
132// getIgaBCGeom().invertPoints(pts, parPts);
133// fpts = it->function()->eval(parPts);
134// }
135 else
136 fpts = it->function()->eval(gsPointGrid<T>(rr));
137
138 // Interpolate dirichlet boundary
139 typename gsBasis<T>::uPtr h = basis.boundaryBasis(it->side());
140 typename gsGeometry<T>::uPtr geo = h->interpolateAtAnchors(fpts);
141 const gsMatrix<T> & dVals = geo->coefs();
142
143 // Save corresponding boundary dofs
144 for (index_t i = 0; i != boundary.size(); ++i)
145 {
146 const index_t ii = mapper.bindex(boundary.at(i), it->patch());
147 ddofVector.row(ii) = dVals.row(i);
148 }
149 }
150}
151
152
153template<class T, int MatOrder>
154void gsFlowAssemblerBase<T, MatOrder>::computeDirichletDofsL2Proj(const index_t unk, const gsDofMapper & mapper, const gsMultiBasis<T> & mbasis, gsMatrix<T>& ddofVector)
155{
156 // Set up matrix, right-hand-side and solution vector/matrix for
157 // the L2-projection
158 gsSparseEntries<T> projMatEntries;
159 gsMatrix<T> globProjRhs;
160 globProjRhs.setZero(ddofVector.rows(), ddofVector.cols());
161
162 // Temporaries
163 gsVector<T> quWeights;
164 gsMatrix<T> rhsVals;
165 gsMatrix<index_t> globIdxAct;
166 gsMatrix<T> basisVals;
167 gsMapData<T> mapData(NEED_MEASURE);
168
169 // Iterate over all patch-sides with Dirichlet-boundary conditions
170 for (typename gsBoundaryConditions<T>::const_iterator
171 it = getBCs().dirichletBegin();
172 it != getBCs().dirichletEnd(); ++it)
173 {
174 if (it->unknown() != unk)
175 continue;
176
177 if (it->isHomogeneous())
178 continue;
179
180 GISMO_ASSERT(it->function()->targetDim() == ddofVector.cols(),
181 "Given Dirichlet boundary function does not match problem dimension."
182 << it->function()->targetDim() << " != " << ddofVector.cols() << "\n");
183
184 const index_t patchID = it->patch();
185 const gsBasis<T> & basis = mbasis.piece(patchID);
186 const gsGeometry<T> & patch = getPatches()[patchID];
187
188 // Set up quadrature to degree+1 Gauss points per direction,
189 // all lying on it->side() except from the direction which
190 // is NOT along the element
191
192 gsGaussRule<T> bdQuRule(basis, 1.0, 1, it->side().direction());
193
194 // Create the iterator along the given part boundary.
195 typename gsBasis<T>::domainIter bdryIter = basis.makeDomainIterator(it->side());
196
197 for (; bdryIter->good(); bdryIter->next())
198 {
199 bdQuRule.mapTo(bdryIter->lowerCorner(), bdryIter->upperCorner(),
200 mapData.points, quWeights);
201
202 patch.computeMap(mapData);
203
204 // the values of the boundary condition are stored
205 // to rhsVals. Here, "rhs" refers to the right-hand-side
206 // of the L2-projection, not of the PDE.
207 rhsVals = it->function()->eval(getPatches()[patchID].eval(mapData.points));
208
209 basis.eval_into(mapData.points, basisVals);
210
211 // active basis (first line) functions/DOFs:
212 basis.active_into(mapData.points.col(0), globIdxAct);
213 mapper.localToGlobal(globIdxAct, patchID, globIdxAct);
214
215 // eltBdryFcts stores the row in basisVals/globIdxAct, i.e.,
216 // something like a "element-wise index"
217 std::vector<index_t> eltBdryFcts;
218 eltBdryFcts.reserve(mapper.boundarySize());
219 for (index_t i = 0; i < globIdxAct.rows(); i++)
220 if (mapper.is_boundary_index(globIdxAct(i, 0)))
221 eltBdryFcts.push_back(i);
222
223 // Do the actual assembly:
224 for (index_t k = 0; k < mapData.points.cols(); k++)
225 {
226 const T weight_k = quWeights[k] * mapData.measure(k);
227
228 // Only run through the active boundary functions on the element:
229 for (size_t i0 = 0; i0 < eltBdryFcts.size(); i0++)
230 {
231 // Each active boundary function/DOF in eltBdryFcts has...
232 // ...the above-mentioned "element-wise index"
233 const index_t i = eltBdryFcts[i0];
234 // ...the boundary index.
235 const index_t ii = mapper.global_to_bindex(globIdxAct(i));
236
237 for (size_t j0 = 0; j0 < eltBdryFcts.size(); j0++)
238 {
239 const index_t j = eltBdryFcts[j0];
240 const index_t jj = mapper.global_to_bindex(globIdxAct(j));
241
242 // Use the "element-wise index" to get the needed
243 // function value.
244 // Use the boundary index to put the value in the proper
245 // place in the global projection matrix.
246 projMatEntries.add(ii, jj, weight_k * basisVals(i, k) * basisVals(j, k));
247 } // for j
248
249 globProjRhs.row(ii) += weight_k * basisVals(i, k) * rhsVals.col(k).transpose();
250
251 } // for i
252 } // for k
253 } // bdryIter
254 } // boundaryConditions-Iterator
255
256 gsSparseMatrix<T> globProjMat(mapper.boundarySize(), mapper.boundarySize());
257 globProjMat.setFrom(projMatEntries);
258 globProjMat.makeCompressed();
259
260 // Solve the linear system:
261 // The position in the solution vector already corresponds to the
262 // numbering by the boundary index. Hence, we can simply take them
263 // for the values of the eliminated Dirichlet DOFs.
264 typename gsSparseSolver<T>::CGDiagonal solver;
265 ddofVector = solver.compute(globProjMat).solve(globProjRhs);
266}
267
268
269template<class T, int MatOrder>
271{
272 for(size_t p = 0; p < getPatches().nPatches(); p++)
273 {
274 visitor.initOnPatch(p);
275
276 if (m_params.options().getString("assemb.loop") == "RbR")
277 {
278 index_t nBases = m_params.getBases()[testBasisID].piece(p).size();
279
280 for(index_t i = 0; i < nBases; i++)
281 {
282 visitor.evaluate(i);
283 visitor.assemble();
284 visitor.localToGlobal(m_ddof, block, blockRhs);
285 }
286 }
287 else
288 {
289 if (m_params.options().getString("assemb.loop") != "EbE")
290 gsWarn << "Unknown matrix formation method, using EbE (element by element)!\n";
291
292 typename gsBasis<T>::domainIter domIt = m_params.getBases().front().piece(p).makeDomainIterator(boundary::none);
293
294 while (domIt->good())
295 {
296 visitor.evaluate(domIt.get());
297 visitor.assemble();
298 visitor.localToGlobal(m_ddof, block, blockRhs);
299
300 domIt->next();
301 }
302 }
303 }
304
305 block.makeCompressed();
306}
307
308
309template<class T, int MatOrder>
311{
312 for(size_t p = 0; p < getPatches().nPatches(); p++)
313 {
314 visitor.initOnPatch(p);
315
316 if (m_params.options().getString("assemb.loop") == "RbR")
317 {
318 index_t nBases = m_params.getBases()[testBasisID].piece(p).size();
319
320 for(index_t i = 0; i < nBases; i++)
321 {
322 visitor.evaluate(i);
323 visitor.assemble();
324 visitor.localToGlobal(rhs);
325 }
326 }
327 else
328 {
329 typename gsBasis<T>::domainIter domIt = m_params.getBases().front().piece(p).makeDomainIterator(boundary::none);
330
331 while (domIt->good())
332 {
333 visitor.evaluate(domIt.get());
334 visitor.assemble();
335 visitor.localToGlobal(rhs);
336
337 domIt->next();
338 }
339 }
340 }
341}
342
343
344template<class T, int MatOrder>
346{
347 assembleNonlinearPart();
348}
349
350
351template<class T, int MatOrder>
353{
354 assembleLinearPart();
355 m_isInitialized = true;
356}
357
358
359template<class T, int MatOrder>
360void gsFlowAssemblerBase<T, MatOrder>::update(const gsMatrix<T> & solVector, bool updateSol)
361{
362 GISMO_ASSERT(m_isInitialized, "Assembler must be initialized first, call initialize()");
363
364 updateCurrentSolField(solVector, updateSol);
365 updateAssembly();
366}
367
368
369} // namespace gismo
A basis represents a family of scalar basis functions defined over a common parameter domain.
Definition gsBasis.h:79
memory::unique_ptr< gsBasis > uPtr
Unique pointer for gsBasis.
Definition gsBasis.h:89
virtual memory::unique_ptr< gsGeometry< T > > interpolateAtAnchors(gsMatrix< T > const &vals) const
Applies interpolation of values pts using the anchors as parameter points. May be reimplemented in de...
Definition gsBasis.hpp:267
Maintains a mapping from patch-local dofs to global dof indices and allows the elimination of individ...
Definition gsDofMapper.h:69
void localToGlobal(const gsMatrix< index_t > &locals, index_t patchIndex, gsMatrix< index_t > &globals, index_t comp=0) const
Computes the global indices of the input local indices.
Definition gsDofMapper.cpp:25
index_t bindex(index_t i, index_t k=0, index_t c=0) const
Returns the boundary index of local dof i of patch k.
Definition gsDofMapper.h:334
index_t boundarySize() const
Returns the number of eliminated dofs.
Definition gsDofMapper.h:457
index_t global_to_bindex(index_t gl) const
Returns the boundary index of global dof gl.
Definition gsDofMapper.h:364
bool is_boundary_index(index_t gl) const
Returns true if global dof gl is eliminated.
Definition gsDofMapper.h:386
void assembleBlock(gsFlowVisitor< T, MatOrder > &visitor, index_t testBasisID, gsSparseMatrix< T, MatOrder > &block, gsMatrix< T > &blockRhs)
Assemble a matrix block.
Definition gsFlowAssemblerBase.hpp:270
virtual void initialize()
Initialize the assembler.
Definition gsFlowAssemblerBase.hpp:352
void computeDirichletDofs(const index_t unk, const index_t basisID, gsMatrix< T > &ddofVector)
Compute the coefficients of the basis functions at the Dirichlet boundaries.
Definition gsFlowAssemblerBase.hpp:30
void computeDirichletDofsIntpl(const index_t unk, const gsDofMapper &mapper, const gsMultiBasis< T > &mbasis, gsMatrix< T > &ddofVector)
Compute the coefficients of the basis functions at the Dirichlet boundaries using interpolation.
Definition gsFlowAssemblerBase.hpp:70
void computeDirichletDofsL2Proj(const index_t unk, const gsDofMapper &mapper, const gsMultiBasis< T > &mbasis, gsMatrix< T > &ddofVector)
Compute the coefficients of the basis functions at the Dirichlet boundaries using L2-projection.
Definition gsFlowAssemblerBase.hpp:154
void assembleRhs(gsFlowVisitor< T, MatOrder > &visitor, index_t testBasisID, gsMatrix< T > &rhs)
Assemble the right-hand side.
Definition gsFlowAssemblerBase.hpp:310
void initMembers()
Initialize the class members.
Definition gsFlowAssemblerBase.hpp:19
virtual void update(const gsMatrix< T > &solVector, bool updateSol=true)
Update the assembler in new nonlinear iteration.
Definition gsFlowAssemblerBase.hpp:360
virtual void updateAssembly()
Assemble all that needs to be updated in each nonlinear iteration.
Definition gsFlowAssemblerBase.hpp:345
Base class for incompressible flow visitors.
Definition gsFlowVisitors.h:29
void evaluate(index_t testFunID)
Evaluate basis data on the support of a given test function (used for row-by-row assembly).
Definition gsFlowVisitors.hpp:230
void initOnPatch(index_t patchID)
Initialize the visitor on the given patch.
Definition gsFlowVisitors.hpp:150
virtual void localToGlobal(const std::vector< gsMatrix< T > > &eliminatedDofs, gsSparseMatrix< T, MatOrder > &globalMat, gsMatrix< T > &globalRhs)
Map local matrix to the global matrix.
Definition gsFlowVisitors.h:162
virtual void assemble()
Assemble the local matrix.
Definition gsFlowVisitors.hpp:190
Class that represents the (tensor) Gauss-Legendre quadrature rule.
Definition gsGaussRule.h:28
Abstract base class representing a geometry map.
Definition gsGeometry.h:93
gsMatrix< T > & coefs()
Definition gsGeometry.h:340
memory::unique_ptr< gsGeometry > uPtr
Unique pointer for gsGeometry.
Definition gsGeometry.h:100
the gsMapData is a cache of pre-computed function (map) values.
Definition gsFuncData.h:349
gsMatrix< T > points
input (parametric) points
Definition gsFuncData.h:372
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
Holds a set of patch-wise bases and their topology information.
Definition gsMultiBasis.h:37
const gsBasis< T > & piece(const index_t i) const
Returns the piece(s) of the function(s) at subdomain k.
Definition gsMultiBasis.h:274
const_reference at(size_t i) const
Assess i-th parametric basis.
Definition gsMultiBasis.h:163
virtual void mapTo(const gsVector< T > &lower, const gsVector< T > &upper, gsMatrix< T > &nodes, gsVector< T > &weights) const
Maps quadrature rule (i.e., points and weights) from the reference domain to an element.
Definition gsQuadRule.h:177
Class that provides a container for triplets (i,j,value) to be filled in a sparse matrix.
Definition gsSparseMatrix.h:34
Sparse matrix class, based on gsEigen::SparseMatrix.
Definition gsSparseMatrix.h:139
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_ERROR(message)
Definition gsDebug.h:118
#define gsWarn
Definition gsDebug.h:50
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
The G+Smo namespace, containing all definitions for the library.
@ NEED_MEASURE
The density of the measure pull back.
Definition gsForwardDeclarations.h:76
Struct that defines the boundary sides and corners and types of a geometric object.
Definition gsBoundary.h:56