OOFEM 3.0
Loading...
Searching...
No Matches
tet21stokes.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
35#include "tet21stokes.h"
36#include "node.h"
37#include "dof.h"
38#include "domain.h"
40#include "gausspoint.h"
41#include "bcgeomtype.h"
43#include "load.h"
44#include "bodyload.h"
45#include "boundaryload.h"
46#include "mathfem.h"
48#include "fei3dtetlin.h"
49#include "fei3dtetquad.h"
50#include "fluidcrosssection.h"
51#include "assemblercallback.h"
52#include "classfactory.h"
53
54namespace oofem {
56
57// Set up interpolation coordinates
58FEI3dTetLin Tet21Stokes :: interpolation_lin;
59FEI3dTetQuad Tet21Stokes :: interpolation_quad;
60// Set up ordering vectors (for assembling)
61IntArray Tet21Stokes :: momentum_ordering = {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18, 19,
62 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34};
63IntArray Tet21Stokes :: conservation_ordering = {4, 8, 12, 16};
64IntArray Tet21Stokes :: surf_ordering [ 4 ] = {
65 { 1, 2, 3, 9, 10, 11, 5, 6, 7, 23, 24, 25, 20, 21, 22, 17, 18, 19},
66 { 1, 2, 3, 5, 6, 7, 13, 14, 15, 17, 18, 19, 29, 30, 31, 26, 27, 28},
67 { 5, 6, 7, 9, 10, 11, 13, 14, 15, 20, 21, 22, 32, 33, 34, 29, 30, 31},
68 { 1, 2, 3, 13, 14, 15, 9, 10, 11, 26, 27, 28, 32, 33, 34, 23, 24, 25}
69};
70
71Tet21Stokes :: Tet21Stokes(int n, Domain *aDomain) : FMElement(n, aDomain), SpatialLocalizerInterface(this)
72{
73 this->numberOfDofMans = 10;
74 this->numberOfGaussPoints = 5;
75}
76
77void Tet21Stokes :: computeGaussPoints()
78{
79 if ( integrationRulesArray.size() == 0 ) {
80 integrationRulesArray.resize(1);
81 integrationRulesArray [ 0 ] = std::make_unique<GaussIntegrationRule>(1, this, 1, 3);
82 this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], this->numberOfGaussPoints, this);
83 }
84}
85
86int Tet21Stokes :: computeNumberOfDofs()
87{
88 return 34;
89}
90
91void Tet21Stokes :: giveDofManDofIDMask(int inode, IntArray &answer) const
92{
93 if ( inode <= 4 ) {
94 answer = {V_u, V_v, V_w, P_f};
95 } else {
96 answer = {V_u, V_v, V_w};
97 }
98}
99
100void Tet21Stokes :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode,
101 TimeStep *tStep)
102{
103 // Compute characteristic vector for this element. I.e the load vector(s)
104 if ( mtrx == ExternalForcesVector ) {
105 this->computeExternalForcesVector(answer, tStep);
106 } else if ( mtrx == InternalForcesVector ) {
107 this->computeInternalForcesVector(answer, tStep);
108 } else {
109 OOFEM_ERROR("Unknown Type of characteristic mtrx.");
110 }
111}
112
113void Tet21Stokes :: giveCharacteristicMatrix(FloatMatrix &answer,
114 CharType mtrx, TimeStep *tStep)
115{
116 // Compute characteristic matrix for this element. The only option is the stiffness matrix...
117 if ( mtrx == TangentStiffnessMatrix ) {
118 this->computeStiffnessMatrix(answer, TangentStiffness, tStep);
119 } else {
120 OOFEM_ERROR("Unknown Type of characteristic mtrx.");
121 }
122}
123
124void Tet21Stokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *tStep)
125{
126 FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
127 FloatArray a_pressure, a_velocity, devStress, epsp, Nh, dN_V(30);
128 FloatMatrix dN, B(6, 30);
129 double r_vol, pressure;
130 this->computeVectorOfVelocities(VM_Total, tStep, a_velocity);
131 this->computeVectorOfPressures(VM_Total, tStep, a_pressure);
132 FloatArray momentum, conservation;
133
134 B.zero();
135 for ( auto &gp: *integrationRulesArray [ 0 ] ) {
136 const FloatArray &lcoords = gp->giveNaturalCoordinates();
137
138 double detJ = fabs( this->interpolation_quad.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) );
139 this->interpolation_lin.evalN( Nh, lcoords, FEIElementGeometryWrapper(this) );
140 double dV = detJ * gp->giveWeight();
141
142 for ( int j = 0, k = 0; j < dN.giveNumberOfRows(); j++, k += 3 ) {
143 dN_V(k + 0) = B(0, k + 0) = B(3, k + 1) = B(4, k + 2) = dN(j, 0);
144 dN_V(k + 1) = B(1, k + 1) = B(3, k + 0) = B(5, k + 2) = dN(j, 1);
145 dN_V(k + 2) = B(2, k + 2) = B(4, k + 0) = B(5, k + 1) = dN(j, 2);
146 }
147
148 epsp.beProductOf(B, a_velocity);
149 pressure = Nh.dotProduct(a_pressure);
150 auto val = mat->computeDeviatoricStress3D(epsp, pressure, gp, tStep);
151 devStress = val.first;
152 r_vol = val.second;
153
154 momentum.plusProduct(B, devStress, dV);
155 momentum.add(-pressure * dV, dN_V);
156 conservation.add(r_vol * dV, Nh);
157 }
158
159 answer.resize(34);
160 answer.zero();
161 answer.assemble(momentum, this->momentum_ordering);
162 answer.assemble(conservation, this->conservation_ordering);
163}
164
165void Tet21Stokes :: computeExternalForcesVector(FloatArray &answer, TimeStep *tStep)
166{
167 int load_number, load_id;
168 Load *load;
169 BodyLoad *bLoad;
170 bcGeomType ltype;
171 FloatArray vec;
172
173 int nLoads = this->boundaryLoadArray.giveSize() / 2;
174 answer.clear();
175
176 for ( int i = 1; i <= nLoads; i++ ) { // For each Neumann boundary condition
177 load_number = this->boundaryLoadArray.at(2 * i - 1);
178 load_id = this->boundaryLoadArray.at(2 * i);
179 load = this->domain->giveLoad(load_number);
180 ltype = load->giveBCGeoType();
181
182 if ( ltype == SurfaceLoadBGT ) {
183 this->computeBoundarySurfaceLoadVector(vec, static_cast< BoundaryLoad * >(load), load_id, ExternalForcesVector, VM_Total, tStep);
184 answer.add(vec);
185 }
186 }
187
188 nLoads = this->giveBodyLoadArray()->giveSize();
189 for ( int i = 1; i <= nLoads; i++ ) {
190 load = domain->giveLoad( bodyLoadArray.at(i) );
191 if ((bLoad=dynamic_cast<BodyLoad*>(load))) {
192 ltype = load->giveBCGeoType();
193 if ( ltype == BodyLoadBGT && load->giveBCValType() == ForceLoadBVT ) {
194 this->computeLoadVector(vec, bLoad, ExternalForcesVector, VM_Total, tStep);
195 answer.add(vec);
196 }
197 }
198 }
199}
200
201void Tet21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep)
202{
203 if ( type != ExternalForcesVector ) {
204 answer.clear();
205 return;
206 }
207
208 FloatArray N, gVector, temparray(30);
209
210 load->computeComponentArrayAt(gVector, tStep, VM_Total);
211 temparray.zero();
212 if ( gVector.giveSize() ) {
213 for ( auto &gp: *integrationRulesArray [ 0 ] ) {
214 const FloatArray &lcoords = gp->giveNaturalCoordinates();
215
216 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp);
217 double detJ = fabs( this->interpolation_quad.giveTransformationJacobian( lcoords, FEIElementGeometryWrapper(this) ) );
218 double dA = detJ * gp->giveWeight();
219
220 this->interpolation_quad.evalN( N, lcoords, FEIElementGeometryWrapper(this) );
221 for ( int j = 0; j < N.giveSize(); j++ ) {
222 temparray(3 * j + 0) += N(j) * rho * gVector(0) * dA;
223 temparray(3 * j + 1) += N(j) * rho * gVector(1) * dA;
224 temparray(3 * j + 2) += N(j) * rho * gVector(2) * dA;
225 }
226 }
227 }
228
229 answer.resize(34);
230 answer.zero();
231 answer.assemble(temparray, this->momentum_ordering);
232}
233
234 void Tet21Stokes :: computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int iSurf, CharType type, ValueModeType mode, TimeStep *tStep, bool global)
235{
236 if ( type != ExternalForcesVector ) {
237 answer.clear();
238 return;
239 }
240
241 answer.resize(34);
242 answer.zero();
243
244 if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction)
245
246 int numberOfSurfaceIPs = ( int ) ceil( ( load->giveApproxOrder() + 1. ) / 2. ) * 2;
247
248 GaussIntegrationRule iRule(1, this, 1, 1);
249 FloatArray N, t, f(18);
250
251 f.zero();
252 iRule.SetUpPointsOnTriangle(numberOfSurfaceIPs, _Unknown);
253
254 for ( auto &gp: iRule ) {
255 const FloatArray &lcoords = gp->giveNaturalCoordinates();
256
257 this->interpolation_quad.surfaceEvalN( N, iSurf, lcoords, FEIElementGeometryWrapper(this) );
258 double dA = gp->giveWeight() * this->interpolation_quad.surfaceGiveTransformationJacobian( iSurf, lcoords, FEIElementGeometryWrapper(this) );
259
260 if ( load->giveFormulationType() == Load :: FT_Entity ) { // load in xi-eta system
261 load->computeValueAt(t, tStep, lcoords, VM_Total);
262 } else { // Edge load in x-y system
263 FloatArray gcoords;
264 this->interpolation_quad.surfaceLocal2global( gcoords, iSurf, lcoords, FEIElementGeometryWrapper(this) );
265 load->computeValueAt(t, tStep, gcoords, VM_Total);
266 }
267
268 // Reshape the vector
269 for ( int j = 0; j < N.giveSize(); j++ ) {
270 f(3 * j + 0) += N(j) * t(0) * dA;
271 f(3 * j + 1) += N(j) * t(1) * dA;
272 f(3 * j + 2) += N(j) * t(2) * dA;
273 }
274 }
275
276 answer.assemble(f, this->surf_ordering [ iSurf - 1 ]);
277 } else {
278 OOFEM_ERROR("Strange boundary condition type");
279 }
280}
281
282void Tet21Stokes :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep)
283{
284 FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
286 FloatMatrixF<30,4> G, Dp;
289
290 for ( auto &gp: *this->integrationRulesArray [ 0 ] ) {
291 const auto &lcoords = gp->giveNaturalCoordinates();
292
293 auto Nlin = this->interpolation_lin.evalN( lcoords );
294 auto detj_dn = this->interpolation_quad.evaldNdx( lcoords, FEIElementGeometryWrapper(this) );
295 auto dN = detj_dn.second;
296 auto detJ = detj_dn.first;
297 auto dA = std::abs(detJ) * gp->giveWeight();
298
299 auto dN_V = flatten(dN);
300 auto B = Bmatrix_3d(dN);
301
302 // Computing the internal forces should have been done first.
303 // dsigma_dev/deps_dev dsigma_dev/dp deps_vol/deps_dev deps_vol/dp
304 //auto [Ed, Ep, Cd, Cp] = mat->computeTangents2D(mode, gp, tStep);
305 auto tangents = mat->computeTangents3D(mode, gp, tStep);
306
307 K.plusProductSymmUpper(B, dot(tangents.dsdd, B), dA);
308 G.plusDyadUnsym(dN_V, Nlin, -dA);
309 Dp.plusDyadUnsym(Tdot(B, tangents.dsdp), Nlin, dA);
310 DvT.plusDyadUnsym(Nlin, Tdot(B, tangents.dedd), dA);
311 C.plusDyadSymmUpper(Nlin, tangents.dedp * dA);
312 }
313
314 K.symmetrized();
315 C.symmetrized();
316 auto GTDvT = transpose(G) + DvT;
317 auto GDp = G + Dp;
318
319 answer.resize(34, 34);
320 answer.zero();
321 answer.assemble(K, this->momentum_ordering);
322 answer.assemble(GDp, this->momentum_ordering, this->conservation_ordering);
323 answer.assemble(GTDvT, this->conservation_ordering, this->momentum_ordering);
324 answer.assemble(C, this->conservation_ordering);
325}
326
327FEInterpolation *Tet21Stokes :: giveInterpolation() const
328{
329 return & interpolation_quad;
330}
331
332FEInterpolation *Tet21Stokes :: giveInterpolation(DofIDItem id) const
333{
334 if ( id == P_f ) {
335 return & interpolation_lin;
336 } else {
337 return & interpolation_quad;
338 }
339}
340
341void Tet21Stokes :: updateYourself(TimeStep *tStep)
342{
343 Element :: updateYourself(tStep);
344}
345
346// Some extension Interfaces to follow:
347
348Interface *Tet21Stokes :: giveInterface(InterfaceType it)
349{
350 switch ( it ) {
352 return static_cast< NodalAveragingRecoveryModelInterface * >(this);
353
355 return static_cast< SpatialLocalizerInterface * >(this);
356
358 return static_cast< EIPrimaryUnknownMapperInterface * >(this);
359
360 default:
361 return FMElement :: giveInterface(it);
362 }
363}
364
365void Tet21Stokes :: EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(ValueModeType mode,
366 TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer)
367{
368 FloatArray n, n_lin;
369 this->interpolation_quad.evalN( n, lcoords, FEIElementGeometryWrapper(this) );
370 this->interpolation_lin.evalN( n_lin, lcoords, FEIElementGeometryWrapper(this) );
371 answer.resize(4);
372 answer.zero();
373 for ( int i = 1; i <= n.giveSize(); i++ ) {
374 answer(0) += n.at(i) * this->giveNode(i)->giveDofWithID(V_u)->giveUnknown(mode, tStep);
375 answer(1) += n.at(i) * this->giveNode(i)->giveDofWithID(V_v)->giveUnknown(mode, tStep);
376 answer(2) += n.at(i) * this->giveNode(i)->giveDofWithID(V_w)->giveUnknown(mode, tStep);
377 }
378
379 for ( int i = 1; i <= n_lin.giveSize(); i++ ) {
380 answer(3) += n_lin.at(i) * this->giveNode(i)->giveDofWithID(P_f)->giveUnknown(mode, tStep);
381 }
382}
383
384void Tet21Stokes :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep)
385{
386 if ( type == IST_Pressure ) {
387 answer.resize(1);
388 if ( node <= 4 ) {
389 answer.at(1) = this->giveNode(node)->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep);
390 } else {
391 const auto &eNodes = this->interpolation_quad.computeLocalEdgeMapping(node - 4);
392 answer.at(1) = 0.5 * (
393 this->giveNode( eNodes.at(1) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) +
394 this->giveNode( eNodes.at(2) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) );
395 }
396 } else {
397 answer.clear();
398 }
399}
400
401} // end namespace oofem
#define N(a, b)
#define REGISTER_Element(class)
bcType giveType() const override
void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override
int giveApproxOrder() override=0
Node * giveNode(int i) const
Definition element.h:629
IntArray boundaryLoadArray
Definition element.h:147
IntArray * giveBodyLoadArray()
Returns array containing load numbers of loads acting on element.
Definition element.C:411
int numberOfDofMans
Number of dofmanagers.
Definition element.h:136
std::vector< std ::unique_ptr< IntegrationRule > > integrationRulesArray
Definition element.h:157
int numberOfGaussPoints
Definition element.h:175
CrossSection * giveCrossSection()
Definition element.C:534
IntArray bodyLoadArray
Definition element.h:147
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
void computeVectorOfPressures(ValueModeType mode, TimeStep *tStep, FloatArray &pressures)
Definition fmelement.C:51
void computeVectorOfVelocities(ValueModeType mode, TimeStep *tStep, FloatArray &velocities)
Definition fmelement.C:44
FMElement(int n, Domain *aDomain)
Definition fmelement.C:38
void assemble(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:616
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void plusProduct(const FloatMatrix &b, const FloatArray &s, double dV)
Definition floatarray.C:288
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void add(const FloatArray &src)
Definition floatarray.C:218
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void zero()
Zeroes all coefficient of receiver.
int giveNumberOfRows() const
Returns number of rows of receiver.
void assemble(const FloatMatrix &src, const IntArray &loc)
virtual Tangents< 6 > computeTangents3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
virtual std::pair< FloatArrayF< 6 >, double > computeDeviatoricStress3D(const FloatArrayF< 6 > &eps, double pressure, GaussPoint *gp, TimeStep *tStep) const
int SetUpPointsOnTriangle(int nPoints, MaterialMode mode) override
virtual bcGeomType giveBCGeoType() const
virtual void computeComponentArrayAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode)
Definition load.C:84
virtual FormulationType giveFormulationType()
Definition load.h:170
SpatialLocalizerInterface(Element *element)
void computeExternalForcesVector(FloatArray &answer, TimeStep *tStep)
void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override
static IntArray conservation_ordering
Ordering of conservation dofs in element. Used to assemble the element stiffness.
Definition tet21stokes.h:68
void computeInternalForcesVector(FloatArray &answer, TimeStep *tStep)
static IntArray momentum_ordering
Ordering of momentum balance dofs in element. Used to assemble the element stiffness.
Definition tet21stokes.h:66
static FEI3dTetQuad interpolation_quad
Interpolation for geometry and velocity.
Definition tet21stokes.h:64
static IntArray surf_ordering[4]
Ordering of dofs on surfaces. Used to assemble edge loads (only momentum balance).
Definition tet21stokes.h:70
static FEI3dTetLin interpolation_lin
Interpolation for pressure.
Definition tet21stokes.h:62
void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep)
void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override
#define OOFEM_ERROR(...)
Definition error.h:79
FloatMatrixF< M, N > transpose(const FloatMatrixF< N, M > &mat)
Constructs transposed matrix.
FloatMatrixF< N, P > Tdot(const FloatMatrixF< M, N > &a, const FloatMatrixF< M, P > &b)
Computes .
bcGeomType
Type representing the geometric character of loading.
Definition bcgeomtype.h:40
@ SurfaceLoadBGT
Distributed surface load.
Definition bcgeomtype.h:45
@ BodyLoadBGT
Distributed body load.
Definition bcgeomtype.h:43
FloatMatrixF< 6, N *3 > Bmatrix_3d(const FloatMatrixF< 3, N > &dN)
Constructs the B matrix for 3D momentum balance problems.
double dot(const FloatArray &x, const FloatArray &y)
@ ForceLoadBVT
Definition bcvaltype.h:43
@ SpatialLocalizerInterfaceType
@ NodalAveragingRecoveryModelInterfaceType
@ EIPrimaryUnknownMapperInterfaceType
@ TransmissionBC
Neumann type (prescribed flux).
Definition bctype.h:43
FloatArrayF< N *M > flatten(const FloatMatrixF< N, M > &m)

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011