OOFEM 3.0
Loading...
Searching...
No Matches
transversereinfconstraint.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
36#include "classfactory.h"
37#include "node.h"
38#include "masterdof.h"
39#include "element.h"
40#include "feinterpol.h"
41#include "gausspoint.h"
42#include "sparsemtrx.h"
45#include "timestep.h"
46#include "function.h"
47#include "sparselinsystemnm.h"
49#include "engngm.h"
50#include "mathfem.h"
51
52namespace oofem {
54
55TransverseReinfConstraint :: TransverseReinfConstraint(int n, Domain *d) :
57 lmLambda( new Node(0, d) )
58{
59 int dofId = d->giveNextFreeDofID();
60 lmLambdaIds.followedBy(dofId);
61 lmLambda->appendDof( new MasterDof( lmLambda.get(), ( DofIDItem ) ( dofId ) ) );
62}
63
64TransverseReinfConstraint :: ~TransverseReinfConstraint()
65{
66}
67
68
69void TransverseReinfConstraint :: initializeFrom(InputRecord &ir)
70{
73
74 return ActiveBoundaryCondition :: initializeFrom(ir);
75}
76
77
78void TransverseReinfConstraint :: giveInputRecord(DynamicInputRecord &input)
79{
80 ActiveBoundaryCondition :: giveInputRecord(input);
81}
82
83
84DofManager *TransverseReinfConstraint :: giveInternalDofManager(int i)
85{
86 return lmLambda.get();
87}
88
89
90void TransverseReinfConstraint :: assembleVector(FloatArray &answer, TimeStep *tStep,
91 CharType type, ValueModeType mode,
93 FloatArray *eNorm,
94 void* lock)
95{
96 IntArray lambda_loc;
97 lmLambda->giveLocationArray(lmLambdaIds, lambda_loc, s);
98
99 if ( type == ExternalForcesVector ) {
100 // The external forces have two contributions. On the additional equations for lambda, the load is simply zero.
101 FloatArray stressLoad = Vec1(0);
102 answer.assemble(stressLoad, lambda_loc);
103 } else if ( type == InternalForcesVector ) {
104 FloatMatrix Klam;
105 FloatArray fe_lam, fe_u;
106 FloatArray lambda, u_s, u_c, u;
107 IntArray loc, loc_s, loc_c, masterDofIDs;
108
109 // Fetch the current values of the Lagrange multiplier;
110 lmLambda->giveUnknownVector(lambda, lmLambdaIds, mode, tStep);
111
112 // Assemble
113 Set *steelSet = this->giveDomain()->giveSet(steelElSet);
114 const IntArray &elements = steelSet->giveElementList();
115
116 Set *concreteSet = this->giveDomain()->giveSet(conElBoundSet);
117 const IntArray &boundaries = concreteSet->giveBoundaryList();
118
119 if ( boundaries.giveSize() == elements.giveSize()*2 ) {
120 for ( int pos = 1; pos <= elements.giveSize(); ++pos) {
121 Element *es = this->giveDomain()->giveElement( elements.at(pos) );
122 Element *ec = this->giveDomain()->giveElement( boundaries.at(2*pos - 1) );
123 int boundary = boundaries.at(2*pos);
124
125 // Fetch the element information;
126 es->giveLocationArray(loc_s, s);
127
128 // Fetch the nodal displacements
129 // since computeVectorOf gives the unknown vector in local coordinate system, it needs to be rotated to global coordinates
130 FloatMatrix G2L;
132 es->computeVectorOf(mode, tStep, u_s);
133 u_s.rotatedWith(G2L, 't');
134
135 //Fetch boundary information
136 IntArray bndNodes;
137 bndNodes = ec->giveBoundaryEdgeNodes(boundary);
138 ec->giveBoundaryLocationArray(loc_c, bndNodes, s, &masterDofIDs);
139 masterDofIDs.resizeWithValues(2); //hack to get corresponding masterDofIDs in computeBoundaryVectorOf
140 ec->computeBoundaryVectorOf(bndNodes, masterDofIDs, mode, tStep, u_c);
141
142 //Assemble the location and u arrays
143 loc=loc_s;
144 loc.followedBy(loc_c);
145
146 u=FloatArray::fromConcatenated({u_s,u_c});
147
148 //Compute the stiffness matrix expansion
149 this->integrateTangent(Klam, es, ec, boundary);
150
151 //Compute the contribution to internal force vector
152 fe_lam.beProductOf(Klam, u);
153 fe_u.beTProductOf(Klam, lambda);
154
155 //Negate the terms for symmetry
156 fe_lam.negated();
157 fe_u.negated();
158
159 //Assemble
160 answer.assemble(fe_u, loc);
161 answer.assemble(fe_lam, lambda_loc);
162 }
163 } else {
164 OOFEM_ERROR("Steel/concrete element mismatch")
165 }
166 }
167}
168
169void TransverseReinfConstraint :: assemble(SparseMtrx &answer, TimeStep *tStep,
170 CharType type,
171 const UnknownNumberingScheme &r_s,
172 const UnknownNumberingScheme &c_s,
173 double scale,
174 void* lock)
175{
176 if ( type == TangentStiffnessMatrix || type == SecantStiffnessMatrix || type == ElasticStiffnessMatrix ) {
177 FloatMatrix Klam, KlamT;
178 IntArray loc_r, loc_c, lambda_loc_r, lambda_loc_c;
179 IntArray loc_us_r, loc_us_c, loc_uc_r, loc_uc_c;
180 IntArray masterDofIDs;
181
182 //Fetch the rows/columns for the Lagrange multiplier contributions
183 lmLambda->giveLocationArray(lmLambdaIds, lambda_loc_r, r_s);
184 lmLambda->giveLocationArray(lmLambdaIds, lambda_loc_c, c_s);
185
186 //Contributions from steel
187 Set *steelSet = this->giveDomain()->giveSet(steelElSet);
188 const IntArray &elements = steelSet->giveElementList();
189
190 //Contributions from concrete
191 Set *concreteSet = this->giveDomain()->giveSet(conElBoundSet);
192 const IntArray &boundaries = concreteSet->giveBoundaryList();
193
194 if ( boundaries.giveSize() == elements.giveSize()*2 ) {
195 for ( int pos = 1; pos <= elements.giveSize(); ++pos) {
196 Element *es = this->giveDomain()->giveElement( elements.at(pos) );
197 Element *ec = this->giveDomain()->giveElement( boundaries.at(2*pos - 1) );
198 int boundary = boundaries.at(2*pos);
199
200 // Fetch the element information;
201 es->giveLocationArray(loc_us_r, r_s);
202 es->giveLocationArray(loc_us_c, c_s);
203
204 //Fetch boundary information
205 IntArray bndNodes;
206 bndNodes = ec->giveBoundaryEdgeNodes(boundary);
207 ec->giveBoundaryLocationArray(loc_uc_r, bndNodes, r_s, &masterDofIDs);
208 ec->giveBoundaryLocationArray(loc_uc_c, bndNodes, c_s, &masterDofIDs);
209
210 //Assemble the location arrays
211 loc_c=loc_us_c;
212 loc_c.followedBy(loc_uc_c);
213 loc_r=loc_us_r;
214 loc_r.followedBy(loc_uc_r);
215
216 //Compute the stiffness matrix expansion
217 this->integrateTangent(Klam, es, ec, boundary);
218
219 Klam.negated();
220 KlamT.beTranspositionOf(Klam);
221
222 answer.assemble(lambda_loc_r, loc_c, Klam);
223 answer.assemble(loc_r, lambda_loc_c, KlamT);
224 }
225 } else {
226 OOFEM_ERROR("Steel/concrete element mismatch")
227 }
228 } else {
229 OOFEM_LOG_DEBUG("Skipping assembly in TransverseReinfConstraint::assemble().\n");
230 }
231}
232
233void TransverseReinfConstraint :: giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type,
234 const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s)
235{
236 IntArray loc_us_r, loc_us_c, loc_uc_r, loc_uc_c;
237 IntArray loc_r, loc_c, lambda_loc_r, lambda_loc_c;
238 IntArray masterDofIDs;
239
240 // Fetch the columns/rows for the stress contributions;
241 lmLambda->giveLocationArray(lmLambdaIds, lambda_loc_r, r_s);
242 lmLambda->giveLocationArray(lmLambdaIds, lambda_loc_c, c_s);
243
244 //Contributions from steel
245 Set *steelSet = this->giveDomain()->giveSet(steelElSet);
246 const IntArray &selements = steelSet->giveElementList();
247
248 //Contributions from concrete
249 Set *concreteSet = this->giveDomain()->giveSet(conElBoundSet);
250 const IntArray &boundaries = concreteSet->giveBoundaryList();
251
252 if ( boundaries.giveSize() == selements.giveSize()*2 ) {
253 rows.resize( boundaries.giveSize() + 2*selements.giveSize() );
254 cols.resize( boundaries.giveSize() + 2*selements.giveSize() );
255
256 int i=0;
257 for ( int pos = 1; pos <= selements.giveSize(); ++pos) {
258 Element *es = this->giveDomain()->giveElement( selements.at(pos) );
259 Element *ec = this->giveDomain()->giveElement( boundaries.at(2*pos - 1) );
260 int boundary = boundaries.at(2*pos);
261
262 // Fetch the element information;
263 es->giveLocationArray(loc_us_r, r_s);
264 es->giveLocationArray(loc_us_c, c_s);
265
266 //Fetch boundary information
267 IntArray bndNodes;
268 bndNodes = ec->giveBoundaryEdgeNodes(boundary);
269 ec->giveBoundaryLocationArray(loc_uc_r, bndNodes, r_s, &masterDofIDs);
270 ec->giveBoundaryLocationArray(loc_uc_c, bndNodes, c_s, &masterDofIDs);
271
272 loc_c=loc_us_c;
273 loc_c.followedBy(loc_uc_c);
274 loc_r=loc_us_r;
275 loc_r.followedBy(loc_uc_r);
276
277 // For most uses, loc_us_r == loc_us_c, and lambda_loc_r == lambda_loc_c.
278 rows [ i ] = loc_r;
279 cols [ i ] = lambda_loc_c;
280 i++;
281 // and the symmetric part (usually the transpose of above)
282 rows [ i ] = lambda_loc_r;
283 cols [ i ] = loc_c;
284 i++;
285 }
286 } else {
287 OOFEM_ERROR("Steel/concrete element mismatch")
288 }
289}
290
291void TransverseReinfConstraint :: computeField(FloatArray &lambda, TimeStep *tStep)
292{
293 lmLambda->giveUnknownVector(lambda, lmLambdaIds, VM_Total, tStep);
294}
295
296
297
298void TransverseReinfConstraint :: integrateTangent(FloatMatrix& oTangent, Element* es, Element* ec, int iBndIndex)
299{
300 FloatMatrix Kslam, Kclam;
301 int nslam, nclam, nsd=1;
302
303 //Compute contributions from steel and concrete
304 this->integrateTangentOnSteel(Kslam, es);
305 this->integrateTangentOnConcrete(Kclam, ec, iBndIndex);
306 nslam = Kslam.giveNumberOfColumns();
307 nclam = Kclam.giveNumberOfColumns();
308
309 //Assemble the tangent contribution
310 oTangent.resize(nsd,nslam + nclam);
311 for (int i=1; i <= nsd; ++i) {
312 for (int j=1; j <= nslam; ++j) {
313 oTangent.at(i,j) = Kslam.at(i,j);
314 }
315 for (int j=nslam+1; j <= nslam+nclam; ++j) {
316 oTangent.at(i,j) = Kclam.at(i,j-nslam);
317 }
318 }
319}
320
321void TransverseReinfConstraint :: integrateTangentOnSteel(FloatMatrix& oTangent, Element* e)
322{
323 //reminder: Kslam must be 1x6
324 FloatArray normal;
325 FloatMatrix Ns, contrib;
326 IntArray DofMask;
327
328 e->giveDofManDofIDMask(1, DofMask);
329 int ndof = DofMask.giveSize();
330
331 FEInterpolation *interp = e->giveInterpolation();
332 int order = interp->giveInterpolationOrder();
333 std :: unique_ptr< IntegrationRule > ir;
334 ir = interp->giveIntegrationRule(order, e->giveGeometryType());
335
336 oTangent.clear();
337
338 for (auto &gp : *ir ) {
339 const FloatArray &lcoords = gp->giveNaturalCoordinates();
340 FEIElementGeometryWrapper cellgeo(e);
341
342 FloatArray nu;
343 interp->evalN(nu, lcoords, cellgeo);
344 double detJ = interp->boundaryEvalNormal(normal, 1, lcoords, cellgeo);
345
346 //Constant traction interpolation
347 FloatMatrix Nlam(ndof,1);
348 // Note: this works only if the reinforcement is horizontal/vertical!
349 // Regardless of interpolation and direction of normal vector taking an absolute value gives
350 // consistent direction of Lagrange multiplier in this case.
351 // Otherwise the order of nodes for the line elements would make a difference (inward/outward pointing normal).
352 // Ideally, it shouldn't matter in which direction (bottom->up, top->down) the reinforcement elements are defined.
353 Nlam(0,0) = fabs(normal.at(1)); //x component of LM
354 Nlam(1,0) = fabs(normal.at(2)); //y component of LM
355 Nlam(2,0) = 0.; //rotation component of LM
356
357 Ns.beNMatrixOf(nu, ndof);
358
359 contrib.beTProductOf(Nlam,Ns);
360 oTangent.add(detJ * gp->giveWeight(), contrib);
361 }
362}
363
364void TransverseReinfConstraint :: integrateTangentOnConcrete(FloatMatrix &oTangent, Element *e, int iBndIndex)
365{
366 //reminder: Kclam must be 1x4
367 FloatArray normal;
368 FloatMatrix Nc, contrib;
369 IntArray DofMask;
370
371 e->giveDofManDofIDMask(1, DofMask);
372 int ndof = DofMask.giveSize();
373
374 FEInterpolation *interp = e->giveInterpolation();
375 int order = interp->giveInterpolationOrder();
376 std :: unique_ptr< IntegrationRule > ir;
377 ir = interp->giveBoundaryIntegrationRule(order, iBndIndex, e->giveGeometryType());
378
379 oTangent.clear();
380
381 for (auto &gp : *ir ) {
382 const FloatArray &lcoords = gp->giveNaturalCoordinates();
383 FEIElementGeometryWrapper cellgeo(e);
384
385 FloatArray nu;
386 interp->boundaryEvalN(nu, iBndIndex, lcoords, cellgeo);
387 double detJ = interp->boundaryEvalNormal(normal, iBndIndex, lcoords, cellgeo);
388
389 //Constant traction interpolation
390 FloatMatrix Nlam(ndof,1);
391 // Note: this works only if the reinforcement is horizontal/vertical!
392 // Regardless of interpolation and direction of normal vector taking an absolute value gives
393 // consistent direction of Lagrange multiplier in this case.
394 // Otherwise it would make a difference on which side of the reinforcement bar the solid elements are located,
395 // but it shouldn't matter.
396 Nlam(0,0) = fabs(normal.at(1)); //x component of LM
397 Nlam(1,0) = fabs(normal.at(2)); //y component of LM
398
399 Nc.beNMatrixOf(nu, ndof);
400
401 contrib.beTProductOf(Nlam,Nc);
402 oTangent.add(detJ * gp->giveWeight(), contrib);
403 oTangent.negated(); //this term is negative in the formulation
404 }
405}
406} /* namespace oofem */
#define REGISTER_BoundaryCondition(class)
ActiveBoundaryCondition(int n, Domain *d)
Definition activebc.h:71
int giveNextFreeDofID(int increment=1)
Definition domain.C:1519
virtual bool computeGtoLRotationMatrix(FloatMatrix &answer)
Definition element.C:1710
virtual void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIds=NULL)
Definition element.C:485
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
virtual IntArray giveBoundaryEdgeNodes(int boundary, bool includeHierarchical=false) const
Definition element.C:892
virtual void giveDofManDofIDMask(int inode, IntArray &answer) const
Definition element.h:488
void giveLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s, IntArray *dofIds=NULL) const
Definition element.C:429
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
void computeBoundaryVectorOf(const IntArray &bNodes, const IntArray &dofIDMask, ValueModeType u, TimeStep *tStep, FloatArray &answer, bool padding=false)
Definition element.C:163
virtual Element_Geometry_Type giveGeometryType() const =0
virtual std::unique_ptr< IntegrationRule > giveBoundaryIntegrationRule(int order, int boundary, const Element_Geometry_Type) const
Definition feinterpol.C:101
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual std::unique_ptr< IntegrationRule > giveIntegrationRule(int order, const Element_Geometry_Type) const
Definition feinterpol.C:90
int giveInterpolationOrder() const
Definition feinterpol.h:199
virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
Domain * giveDomain() const
Definition femcmpnn.h:97
void assemble(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:616
double & at(Index i)
Definition floatarray.h:202
static FloatArray fromConcatenated(std::initializer_list< FloatArray > ini)
Definition floatarray.C:146
void rotatedWith(FloatMatrix &r, char mode)
Definition floatarray.C:814
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void beTProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:721
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()
int giveNumberOfColumns() const
Returns number of columns of receiver.
void beNMatrixOf(const FloatArray &n, int nsd)
void beTranspositionOf(const FloatMatrix &src)
double at(std::size_t i, std::size_t j) const
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
void resizeWithValues(int n, int allocChunk=0)
Definition intarray.C:64
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
const IntArray & giveBoundaryList()
Definition set.C:160
const IntArray & giveElementList()
Definition set.C:158
virtual int assemble(const IntArray &loc, const FloatMatrix &mat)=0
void integrateTangent(FloatMatrix &oTangent, Element *es, Element *ec, int iBndIndex)
Help functions that integrate the tangent contribution from steel and concrete elements.
void integrateTangentOnConcrete(FloatMatrix &oTangent, Element *e, int iBndIndex)
int conElBoundSet
Set of element boundaries along the reinforcement.
void integrateTangentOnSteel(FloatMatrix &oTangent, Element *e)
int steelElSet
Reinforcement bar element set.
std ::unique_ptr< Node > lmLambda
DOF-manager containing the unknown Lagrange multiplier.
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
static FloatArray Vec1(const double &a)
Definition floatarray.h:605
#define _IFT_TransverseReinfConstraint_SteelElSet
#define _IFT_TransverseReinfConstraint_ConElBoundSet

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