OOFEM 3.0
Loading...
Searching...
No Matches
pfemelement2d.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 "pfemelement2d.h"
36#include "node.h"
37#include "material.h"
38#include "crosssection.h"
39#include "gausspoint.h"
41#include "floatmatrix.h"
42#include "floatarray.h"
43#include "intarray.h"
44#include "domain.h"
45#include "mathfem.h"
46#include "engngm.h"
48#include "fluidcrosssection.h"
49#include "load.h"
50#include "timestep.h"
51#include "boundaryload.h"
52#include "mathfem.h"
53#include "contextioerr.h"
54
55#ifdef __OOFEG
56 #include "oofeggraphiccontext.h"
57 #include "connectivitytable.h"
58#endif
59
60namespace oofem {
61PFEMElement2d :: PFEMElement2d(int n, Domain *aDomain) :
62 PFEMElement(n, aDomain)
63{
64}
65
66PFEMElement2d :: ~PFEMElement2d()
67{ }
68
69
70void
71PFEMElement2d :: initializeFrom(InputRecord &ir, int priority)
72{
73 PFEMElement :: initializeFrom(ir, priority);
74}
75
76int
77PFEMElement2d :: checkConsistency()
78{
79 return PFEMElement :: checkConsistency();
80}
81
82
83void
84PFEMElement2d :: computeBMatrix(FloatMatrix &answer, GaussPoint *gp)
85//
86// Returns the [3x6] strain-displacement matrix {B} of the receiver,
87// evaluated at gp.
88// (epsilon_x,epsilon_y,gamma_xy) = B . r
89// r = ( u1,v1,u2,v2,u3,v3)
90{
91 FloatMatrix dnx;
92
94
95 answer.resize( 3, 2 * dnx.giveNumberOfRows() );
96 answer.zero();
97
98 for ( int i = 1; i <= dnx.giveNumberOfRows(); i++ ) {
99 answer.at(1, 2 * i - 1) = dnx.at(i, 1);
100 answer.at(2, 2 * i - 0) = dnx.at(i, 2);
101 answer.at(3, 2 * i - 1) = dnx.at(i, 2);
102 answer.at(3, 2 * i - 0) = dnx.at(i, 1);
103 }
104}
105
106void
107PFEMElement2d :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *atTime)
108{
109 FloatMatrix B, D, DB;
110 FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
111
112 answer.clear();
114 for ( auto &gp : *iRule ) {
115 D=mat->computeTangent2D(mode, gp, atTime);
116 this->computeBMatrix(B, gp);
117 DB.beProductOf(D, B);
118 double dV = this->computeVolumeAround(gp);
119 answer.plusProductUnsym(B, DB, dV);
120 }
121}
122
123
124void
125PFEMElement2d :: computePressureLaplacianMatrix(FloatMatrix &answer, TimeStep *atTime)
126{
127 answer.zero();
128
129 FloatMatrix dnx;
130 FloatMatrix temp;
131
133
134 for ( auto &gp : *iRule ) {
135 this->givePressureInterpolation()->evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
136
137 temp.resize( dnx.giveNumberOfRows(), dnx.giveNumberOfRows() );
138 temp.zero();
139 for ( int i = 1; i <= dnx.giveNumberOfRows(); i++ ) {
140 for ( int j = 1; j <= dnx.giveNumberOfRows(); j++ ) {
141 temp.at(i, j) = dnx.at(i, 1) * dnx.at(j, 1) + dnx.at(i, 2) * dnx.at(j, 2);
142 }
143 }
144
145 double dV = this->computeVolumeAround(gp);
146 answer.add(dV, temp);
147 }
148
149 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) );
150
151 answer.times(1.0 / rho);
152}
153
154
155void
156PFEMElement2d :: computeGradientMatrix(FloatMatrix &answer, TimeStep *atTime) //G
157{
158 answer.clear();
159
160 FloatArray N; //(3)
161 FloatMatrix dnx; //(3,2)
162 FloatMatrix temp;
163
165
166 for ( auto &gp : *iRule ) {
167
168 this->givePressureInterpolation()->evalN( N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
169 this->givePressureInterpolation()->evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
170
171 temp.resize( 2 * dnx.giveNumberOfRows(), N.giveSize() );
172 temp.zero();
173 for ( int i = 1; i <= dnx.giveNumberOfRows(); i++ ) {
174 for ( int j = 1; j <= N.giveSize(); j++ ) {
175 temp.at(2 * i - 1, j) = N.at(i) * dnx.at(j, 1);
176 temp.at(2 * i, j) = N.at(i) * dnx.at(j, 2);
177 }
178 }
179
180 double dV = this->computeVolumeAround(gp);
181 answer.add(dV, temp);
182 }
183}
184
185
186void
187PFEMElement2d :: computeDivergenceMatrix(FloatMatrix &answer, TimeStep *atTime) //D = G^T
188{
189 FloatArray N; //(3)
190 FloatMatrix dnx; //(3,2)
191 FloatMatrix temp;
192
193 answer.clear();
194
196 for ( auto &gp : *iRule ) {
197
198 this->giveVelocityInterpolation()->evalN( N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
199 this->giveVelocityInterpolation()->evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
200
201 temp.resize( N.giveSize(), 2 * dnx.giveNumberOfRows() );
202 temp.zero();
203 for ( int i = 1; i <= N.giveSize(); i++ ) {
204 for ( int j = 1; j <= dnx.giveNumberOfRows(); j++ ) {
205 temp.at(i, 2 * j - 1) = dnx.at(i, 1) * N.at(j);
206 temp.at(i, 2 * j) = dnx.at(i, 2) * N.at(j);
207 }
208 }
209
210 double dV = this->computeVolumeAround(gp);
211 answer.add(dV, temp);
212 }
213}
214
215
216void
217PFEMElement2d :: computePrescribedRhsVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode)
218{
219 // SHOULD BE MOVED INTO TR1_2D_PFEM
220
221 answer.resize(3);
222 answer.zero();
223 // computes numericaly the edge load vector of the receiver for given load
224 // Each element edge must have unique number assigned to identify it.
225 // Integration is done in local edge space (i.e. one dimensional integration is
226 // performed on line). This general implementation requires that element must
227 // provide following functions:
228 // - ComputeEgdeNMatrixAt - returns interpolation matrix of the edge in the
229 // local edge space.
230 // - computeEdgeVolumeAround - returns volumeAround in local edge space
231 // - GiveEdgeDofMapping - returns integer array specifying local edge dof mapping to
232 // element dofs.
233 //
235 FloatMatrix T;
236 FloatArray globalIPcoords;
237
239 GaussIntegrationRule iRule(1, this, 1, 1);
241 FloatArray reducedAnswer, force, ntf, N;
242 IntArray mask;
243 FloatMatrix Nmtrx;
244
245 FloatArray u_presq, u;
246 this->computeVectorOfPrescribed({V_u, V_v}, mode, tStep, u_presq);
247
248 for ( int iEdge = 1; iEdge <= 3; iEdge++ ) {
249 reducedAnswer.zero();
250 for ( auto &gp : iRule ) {
251 this->computeEgdeNVectorAt(N, iEdge, gp);
252 this->computeEdgeNMatrixAt(Nmtrx, iEdge, gp);
253 double dV = this->computeEdgeVolumeAround(gp, iEdge);
254 FloatArray normal;
255 this->giveVelocityInterpolation()->boundaryEvalNormal( normal, iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
256
257 FloatArray u_presq_edge(4);
258 if ( iEdge == 1 ) {
259 u_presq_edge.at(1) = u_presq.at(1);
260 u_presq_edge.at(2) = u_presq.at(2);
261 u_presq_edge.at(3) = u_presq.at(3);
262 u_presq_edge.at(4) = u_presq.at(4);
263 } else if ( iEdge == 2 ) {
264 u_presq_edge.at(1) = u_presq.at(3);
265 u_presq_edge.at(2) = u_presq.at(4);
266 u_presq_edge.at(3) = u_presq.at(5);
267 u_presq_edge.at(4) = u_presq.at(6);
268 } else {
269 u_presq_edge.at(1) = u_presq.at(5);
270 u_presq_edge.at(2) = u_presq.at(6);
271 u_presq_edge.at(3) = u_presq.at(1);
272 u_presq_edge.at(4) = u_presq.at(2);
273 }
274
275 u.beProductOf(Nmtrx, u_presq_edge);
276 double un = normal.dotProduct(u);
277 reducedAnswer.add(dV * un, N);
278 }
279
280 this->giveEdgeDofMapping(mask, iEdge);
281 answer.assemble(reducedAnswer, mask);
282 }
283}
284
285void
286PFEMElement2d :: giveEdgeDofMapping(IntArray &answer, int iEdge) const
287{
288 // SHOULD BE MOVED INTO TR1_2D_PFEM
289 /*
290 * provides dof mapping of local edge dofs (only nonzero are taken into account)
291 * to global element dofs
292 */
293
294 answer.resize(2);
295 if ( iEdge == 1 ) { // edge between nodes 1,2
296 answer.at(1) = 1;
297 answer.at(2) = 2;
298 } else if ( iEdge == 2 ) { // edge between nodes 2 3
299 answer.at(1) = 2;
300 answer.at(2) = 3;
301 } else if ( iEdge == 3 ) { // edge between nodes 3 1
302 answer.at(1) = 3;
303 answer.at(2) = 1;
304 } else {
305 OOFEM_ERROR("giveEdgeDofMapping: wrong edge number");
306 }
307}
308
309
310void
311PFEMElement2d :: computeEdgeNMatrixAt(FloatMatrix &answer, int iedge, GaussPoint *gp)
312{
313 FloatArray n;
314 this->giveVelocityInterpolation()->boundaryEvalN( n, iedge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
315 answer.beNMatrixOf(n, 2);
316}
317
318void
319PFEMElement2d :: computeEgdeNVectorAt(FloatArray &answer, int iedge, GaussPoint *gp)
320{
321 this->giveVelocityInterpolation()->boundaryEvalN(answer, iedge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
322}
323
324double
325PFEMElement2d :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge)
326{
327 double detJ = this->giveVelocityInterpolation()->boundaryGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
328 return detJ *gp->giveWeight();
329}
330
331} // end namespace oofem
#define N(a, b)
void computeVectorOfPrescribed(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:212
std::vector< std ::unique_ptr< IntegrationRule > > integrationRulesArray
Definition element.h:157
int numberOfGaussPoints
Definition element.h:175
CrossSection * giveCrossSection()
Definition element.C:534
virtual double computeVolumeAround(GaussPoint *gp)
Definition element.h:530
virtual int giveDefaultIntegrationRule() const
Definition element.h:880
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
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
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 times(double f)
void add(const FloatMatrix &a)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
void plusProductUnsym(const FloatMatrix &a, const FloatMatrix &b, double dV)
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void beNMatrixOf(const FloatArray &n, int nsd)
void zero()
Zeroes all coefficient of receiver.
int giveNumberOfRows() const
Returns number of rows of receiver.
double at(std::size_t i, std::size_t j) const
virtual FloatMatrixF< 3, 3 > computeTangent2D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
double giveWeight()
Returns integration weight of receiver.
Definition gausspoint.h:180
void resize(int n)
Definition intarray.C:73
int & at(std::size_t i)
Definition intarray.h:104
int setUpIntegrationPoints(integrationDomain intdomain, int nPoints, MaterialMode matMode)
void giveEdgeDofMapping(IntArray &answer, int iEdge) const
Gives the mapping for degrees of freedom on an edge.
void computeEgdeNVectorAt(FloatArray &answer, int iedge, GaussPoint *gp)
Calculates the shape function vector on an edge.
FEInterpolation * giveVelocityInterpolation() override=0
Returns the interpolation for velocity.
double computeEdgeVolumeAround(GaussPoint *gp, int iEdge)
Calculates the volume around an edge.
FEInterpolation * givePressureInterpolation() override=0
Returns the interpolation for the pressure.
void computeEdgeNMatrixAt(FloatMatrix &answer, int iedge, GaussPoint *gp)
Calculates the shape function matrix on an edge.
void computeBMatrix(FloatMatrix &answer, GaussPoint *gp) override
Calculates the element shape function derivative matrix.
PFEMElement(int, Domain *)
Constructor.
Definition pfemelement.C:58
#define OOFEM_ERROR(...)
Definition error.h:79

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