OOFEM 3.0
Loading...
Searching...
No Matches
prescribeddispslipbcdirichletrc.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 "dofiditem.h"
37#include "dofmanager.h"
38#include "dof.h"
39#include "valuemodetype.h"
40#include "floatarray.h"
41#include "floatmatrix.h"
42#include "function.h"
43#include "engngm.h"
44#include "set.h"
45#include "node.h"
46#include "element.h"
47#include "classfactory.h"
48#include "dynamicinputrecord.h"
49#include "feinterpol.h"
51#include "sparsemtrx.h"
52#include "sparselinsystemnm.h"
53#include "assemblercallback.h"
54#include "mathfem.h"
55#include "floatarrayf.h"
56#include "crosssection.h"
57
58namespace oofem {
60
61double PrescribedDispSlipBCDirichletRC :: give(Dof *dof, ValueModeType mode, double time)
62{
63 DofIDItem id = dof->giveDofID();
64 const auto &coords = dof->giveDofManager()->giveCoordinates();
65
66 double factor = 0;
67 if ( mode == VM_Total ) {
68 factor = this->giveTimeFunction()->evaluateAtTime(time);
69 } else if ( mode == VM_Velocity ) {
70 factor = this->giveTimeFunction()->evaluateVelocityAtTime(time);
71 } else if ( mode == VM_Acceleration ) {
72 factor = this->giveTimeFunction()->evaluateAccelerationAtTime(time);
73 } else {
74 OOFEM_ERROR("Should not be called for value mode type then total, velocity, or acceleration.");
75 }
76
77 FloatArray dx;
78 dx.beDifferenceOf(coords, this->mCenterCoord);
79
80 dispGradient.resizeWithData(coords.giveSize(), coords.giveSize());
81 dispField.resizeWithValues(coords.giveSize());
82 slipField.resizeWithValues(coords.giveSize());
83 slipGradient.resizeWithData(coords.giveSize(), coords.giveSize());
84
85 FloatArray u;
87 u.at(1) += dispField.at(1);
88 u.at(2) += dispField.at(2);
89 u.times( factor );
90
91
92 FloatArray us;
94 us.at(1) += slipField.at(1);
95 us.at(2) += slipField.at(2);
96 us.times( factor );
97
98 int pos = this->dofs.findFirstIndexOf(id);
99
100 bool onConcrete = true;
101 bool onSteel = false;
102
103 if ( reinfXBound && reinfYBound ) {
104 Set* setx = domain->giveSet(reinfXBound);
105 Set* sety = domain->giveSet(reinfYBound);
106
107 if ( setx->giveNodeList().contains( dof->giveDofManGlobalNumber() ) || sety->giveNodeList().contains( dof->giveDofManGlobalNumber() ) ) {
108 onConcrete = false;
109 onSteel = true;
110 }
111 }
112
113 if ( onConcrete ) { //node on concrete
114 return this->giveOnConcrete(dof, pos, u);
115 } else if ( onSteel ) { //node on steel
116 return this->giveOnSteel(dof, pos, u, us);
117 } else {
118 return 0.0;
119 }
120
121}
122
123
125{
126 if ( pos > 0 && pos <= u.giveSize() ) {
127 return u.at(pos);
128 } else {
129 return 0.0;
130 }
131
132}
133
134
136{
137 bool isXReinf = false;
138 bool isYReinf = false;
139
140 domain->giveSet(reinfXBound)->giveNodeList().contains( dof->giveDofManager()->giveGlobalNumber() ) ? isXReinf = true : isXReinf = false;
141 domain->giveSet(reinfYBound)->giveNodeList().contains( dof->giveDofManager()->giveGlobalNumber() ) ? isYReinf = true : isYReinf = false;
142
143 if ( isXReinf ) {
144 if ( pos == 1 ) {
145 return u.at(pos) + us.at(pos);
146 } else if ( pos == 2 ) {
147 return u.at(pos);
148 } else if ( pos == 3 ) {
149 return -dispGradient.at(2,1);
150 } else {
151 return 0.0;
152 }
153 } else if ( isYReinf ) {
154 if ( pos == 1 ) {
155 return u.at(pos);
156 } else if ( pos == 2 ) {
157 return u.at(pos) + us.at(pos);
158 } else if ( pos == 3 ) {
159 return dispGradient.at(2,1);
160 } else {
161 return 0.0;
162 }
163 } else {
164 return 0.0;
165 }
166}
167
168
170{
171// This is written in a very general way, supporting both fm and sm problems.
172// v_prescribed = C.d = (x-xbar).d;
173// Modified by ES.
174// C = [x 0 0 y]
175// [0 y x 0]
176// [ ... ] in 2D, voigt form [d_11, d_22, d_12 d_21]
177//Modified by AS:
178//Include end moments from the reinforcement.
179//\sum (R_L e_l + R_perp e_{\perp} ) \outerp (x-\bar{x}) already included in C^T.R_c (in computeField)
180//Added term \sum R_M e_{\perp} \outerp e_l
181// C = [x 0 0 y ]
182// [0 y y 0 ]
183// [ePerp1*eL1 ePerp2*eL2 ePerp1*eL2 ePerp2*eL1]
184// for DofManagers with rotational degrees of freedom.
185 Domain *domain = this->giveDomain();
186
187 int nsd = domain->giveNumberOfSpatialDimensions();
188 int npeq = domain->giveEngngModel()->giveNumberOfDomainEquations( domain->giveNumber(), EModelDefaultPrescribedEquationNumbering() );
189 C.resize(npeq, nsd * nsd);
190 C.zero();
191
192 FloatArray &cCoords = this->giveCenterCoordinate();
193 double xbar = cCoords.at(1), ybar = cCoords.at(2);
194
195 for ( auto &n : domain->giveDofManagers() ) {
196 const auto &coords = n->giveCoordinates();
197 Dof *d1 = n->giveDofWithID( this->dofs[0] );
198 Dof *d2 = n->giveDofWithID( this->dofs[1] );
199 int k1 = d1->__givePrescribedEquationNumber();
200 int k2 = d2->__givePrescribedEquationNumber();
201 int k3 = 0;
202 FloatArrayF<2> eL = { 0., 0. };
203 FloatArrayF<2> ePerp = { 0., 0. };
204 if ( (reinfXBound && reinfYBound) && n->giveNumberOfDofs() == 3 ) {
205 Dof *d3 = n->giveDofWithID( this->dofs[2] );
207 Set* setX = domain->giveSet(reinfXBound);
208 Set* setY = domain->giveSet(reinfYBound);
209 if ( setX->giveNodeList().contains( n->giveGlobalNumber() ) ) {
210 eL = { 1., 0.};
211 ePerp = { 0., 1.};
212 } else if ( setY->giveNodeList().contains( n->giveGlobalNumber() ) ) {
213 eL = { 0., 1.};
214 ePerp = { -1., 0.};
215 }
216 }
217 if ( nsd == 2 ) {
218 if ( k1 ) {
219 C.at(k1, 1) = coords.at(1) - xbar;
220 C.at(k1, 4) = coords.at(2) - ybar;
221 }
222
223 if ( k2 ) {
224 C.at(k2, 2) = coords.at(2) - ybar;
225 C.at(k2, 3) = coords.at(1) - xbar;
226 }
227
228 if ( k3 ) {
229 C.at(k3, 1) = ePerp.at(1) * eL.at(1);
230 C.at(k3, 2) = ePerp.at(2) * eL.at(2);
231 C.at(k3, 3) = ePerp.at(1) * eL.at(2);
232 C.at(k3, 4) = ePerp.at(2) * eL.at(1);
233 }
234 } else {
235 OOFEM_ERROR("Only 2D mode supported.\n");
236 }
237 }
238
239}
240
241
242
243void PrescribedDispSlipBCDirichletRC :: computeStress(FloatArray &sigma, TimeStep *tStep)
244{
245 if ( dispGradON ) {
246 EngngModel *emodel = this->domain->giveEngngModel();
248 FloatArray R_c( npeq ), R_ext( npeq );
249
250 R_c.zero();
251 R_ext.zero();
252 emodel->assembleVector( R_c, tStep, InternalForceAssembler(), VM_Total,
254 emodel->assembleVector( R_ext, tStep, ExternalForceAssembler(), VM_Total,
256 R_c.subtract( R_ext );
257
258 // Condense it;
259 FloatMatrix C;
260 this->updateCoefficientMatrix( C );
261 sigma.beTProductOf( C, R_c );
262 double volRVE = this->domainSize( this->giveDomain(), this->giveSetNumber() );
263 sigma.times( 1. / volRVE );
264 }
265}
266
268{
269 //According to 1/(\Omega_\Box) * \sum R_L \be{l}
270 // [ tau_bxx, tau_byy ]
271 // only compute when applied to reinforcement
272
273 if ( slipON ) {
274 EngngModel *emodel = this->domain->giveEngngModel();
275 Domain *domain = this->giveDomain();
276
277 int nsd = domain->giveNumberOfSpatialDimensions();
278 int npeq = domain->giveEngngModel()->giveNumberOfDomainEquations( domain->giveNumber(), EModelDefaultPrescribedEquationNumbering() );
279
280 FloatArray R_c(npeq), R_ext(npeq);
281
282 R_c.zero();
283 R_ext.zero();
284 emodel->assembleVector( R_c, tStep, InternalForceAssembler(), VM_Total,
286 //R_c contains reactions at the boundary - coming from concrete tractions, beam end forces (normal and shear) and end moments
287
288 emodel->assembleVector( R_ext, tStep, ExternalForceAssembler(), VM_Total,
290
291 R_c.subtract(R_ext);
292
293 //taking contribution only from end nodes of the reinforcement
294 IntArray nodesX = domain->giveSet(reinfXBound)->giveNodeList();
295 IntArray nodesY = domain->giveSet(reinfYBound)->giveNodeList();
296 FloatArray eL;
297 double R_L;
298 eL.resize(nsd); eL.zero();
299 bStress.resize(nsd); bStress.zero();
300
301 for (int i=1; i<=nodesX.giveSize(); i++) {
302 DofManager *d1 = domain->giveDofManager( nodesX.at(i) );
303 eL.at(1) = 1;
304 eL.at(2) = 0;
305 R_L = R_c.at( d1->giveDofWithID(1)->__givePrescribedEquationNumber() );
306 bStress.at(1) += R_L*eL.at(1);
307 bStress.at(2) += R_L*eL.at(2);
308 }
309
310 for (int i=1; i<=nodesY.giveSize(); i++) {
311 DofManager *d2 = domain->giveDofManager( nodesY.at(i) );
312 eL.at(1) = 0;
313 eL.at(2) = 1;
314 R_L = R_c.at( d2->giveDofWithID(2)->__givePrescribedEquationNumber() );
315 bStress.at(1) += R_L*eL.at(1);
316 bStress.at(2) += R_L*eL.at(2);
317 }
318
319 double volRVE = this->domainSize( this->giveDomain(), this->giveSetNumber() );
320 bStress.times( 1. / volRVE );
321 }
322}
323
324
326{
327 //According to 1/(\Omega_\Box) * \sum R_L \be{l} \outerp [x - \bar{x} ]
328 //order: sxx, syy, sxy, syx
329 // only compute when applied to reinforcement
330
331 if ( slipGradON ) {
332 EngngModel *emodel = this->domain->giveEngngModel();
333 Domain *domain = this->giveDomain();
334
335 int nsd = domain->giveNumberOfSpatialDimensions();
336 int npeq = domain->giveEngngModel()->giveNumberOfDomainEquations( domain->giveNumber(), EModelDefaultPrescribedEquationNumbering() );
337
338 FloatArray R_c(npeq), R_ext(npeq);
339
340 R_c.zero();
341 R_ext.zero();
342 emodel->assembleVector( R_c, tStep, InternalForceAssembler(), VM_Total,
344 //R_c contains reactions at the boundary - coming from concrete tractions, beam end forces (normal and shear) and end moments
345
346 emodel->assembleVector( R_ext, tStep, ExternalForceAssembler(), VM_Total,
348
349 R_c.subtract(R_ext);
350
351 //taking contribution only from end nodes of the reinforcement
352 IntArray nodesX = domain->giveSet(reinfXBound)->giveNodeList();
353 IntArray nodesY = domain->giveSet(reinfYBound)->giveNodeList();
354 FloatArray eL, cCoords = this->giveCenterCoordinate();
355 double xbar=cCoords.at(1), ybar=cCoords.at(2), R_L;
356 eL.resize(nsd); eL.zero();
357 rStress.resize(nsd*2); rStress.zero();
358
359 for (int i=1; i<=nodesX.giveSize(); i++) {
360 DofManager *d1 = domain->giveDofManager( nodesX.at(i) );
361 const auto &coords = d1->giveCoordinates();
362 eL.at(1) = 1;
363 eL.at(2) = 0;
364 R_L = R_c.at( d1->giveDofWithID(1)->__givePrescribedEquationNumber() );
365 rStress.at(1) += R_L*eL.at(1) * (coords.at(1) - xbar);
366 rStress.at(2) += R_L*eL.at(2) * (coords.at(2) - ybar);
367 rStress.at(3) += R_L*eL.at(1) * (coords.at(2) - ybar);
368 rStress.at(4) += R_L*eL.at(2) * (coords.at(1) - xbar);
369 }
370
371 for (int i=1; i<=nodesY.giveSize(); i++) {
372 DofManager *d2 = domain->giveDofManager( nodesY.at(i) );
373 const auto &coords = d2->giveCoordinates();
374 eL.at(1) = 0;
375 eL.at(2) = 1;
376 R_L = R_c.at( d2->giveDofWithID(2)->__givePrescribedEquationNumber() );
377 rStress.at(1) += R_L*eL.at(1) * (coords.at(1) - xbar);
378 rStress.at(2) += R_L*eL.at(2) * (coords.at(2) - ybar);
379 rStress.at(3) += R_L*eL.at(1) * (coords.at(2) - ybar);
380 rStress.at(4) += R_L*eL.at(2) * (coords.at(1) - xbar);
381 }
382
383 double volRVE = this->domainSize( this->giveDomain(), this->giveSetNumber() );
384 rStress.times( 1. / volRVE );
385 }
386}
387
388
389void PrescribedDispSlipBCDirichletRC :: computeTangent(FloatMatrix &tangent, TimeStep *tStep)
390// a = [a_c; a_f];
391// K.a = [R_c,0];
392// [K_cc, K_cf; K_fc, K_ff].[a_c;a_f] = [R_c; 0];
393// a_c = d.[x-x_b] = [x-x_b].d = C.d
394// E = C'.(K_cc - K_cf.K_ff^(-1).K_fc).C
395// = C'.(K_cc.C - K_cf.(K_ff^(-1).(K_fc.C)))
396// = C'.(K_cc.C - K_cf.a)
397// = C'.X
398{
399 if ( dispGradON && !slipON && !slipGradON ) {
400 // Fetch some information from the engineering model
401 EngngModel *rve = this->giveDomain()->giveEngngModel();
402 std ::unique_ptr<SparseLinearSystemNM> solver( classFactory.createSparseLinSolver( ST_Petsc, this->domain, this->domain->giveEngngModel() ) ); // = rve->giveLinearSolver();
403 SparseMtrxType stype = solver->giveRecommendedMatrix( true );
406
407 // Set up and assemble tangent FE-matrix which will make up the sensitivity analysis for the macroscopic material tangent.
408 std ::unique_ptr<SparseMtrx> Kff( classFactory.createSparseMtrx( stype ) );
409 std ::unique_ptr<SparseMtrx> Kfp( classFactory.createSparseMtrx( stype ) );
410 std ::unique_ptr<SparseMtrx> Kpf( classFactory.createSparseMtrx( stype ) );
411 std ::unique_ptr<SparseMtrx> Kpp( classFactory.createSparseMtrx( stype ) );
412 if ( !Kff ) {
413 OOFEM_ERROR( "Couldn't create sparse matrix of type %d\n", stype );
414 }
415 Kff->buildInternalStructure( rve, 1, fnum );
416 Kfp->buildInternalStructure( rve, 1, fnum, pnum );
417 Kpf->buildInternalStructure( rve, 1, pnum, fnum );
418 Kpp->buildInternalStructure( rve, 1, pnum );
419 rve->assemble( *Kff, tStep, TangentAssembler( TangentStiffness ), fnum, this->domain );
420 rve->assemble( *Kfp, tStep, TangentAssembler( TangentStiffness ), fnum, pnum, this->domain );
421 rve->assemble( *Kpf, tStep, TangentAssembler( TangentStiffness ), pnum, fnum, this->domain );
422 rve->assemble( *Kpp, tStep, TangentAssembler( TangentStiffness ), pnum, this->domain );
423
424 FloatMatrix C, X, Kpfa, KfpC, a;
425
426 this->updateCoefficientMatrix( C );
427 Kpf->timesT( C, KfpC );
428 solver->solve( *Kff, KfpC, a );
429 Kpp->times( C, X );
430 Kpf->times( a, Kpfa );
431 X.subtract( Kpfa );
432 tangent.beTProductOf( C, X );
433 tangent.times( 1. / this->domainSize( this->giveDomain(), this->giveSetNumber() ) );
434 }
435}
436
437void PrescribedDispSlipBCDirichletRC :: initializeFrom(InputRecord &ir)
438{
439 GeneralBoundaryCondition :: initializeFrom(ir);
442
443 if ( this->dispGradient.isNotEmpty() ) {
444 this->dispGradON = true;
445 }
446
447 if ( this->slipField.isNotEmpty() ) {
448 this->slipON = true;
449 }
450
451 if ( this->slipGradient.isNotEmpty() ) {
452 this->slipGradON = true;
453 }
454
455 if ( slipON || slipGradON) {
458 }
459}
460
461
462void PrescribedDispSlipBCDirichletRC :: giveInputRecord(DynamicInputRecord &input)
463{
464 GeneralBoundaryCondition :: giveInputRecord(input);
465 PrescribedDispSlipHomogenization :: giveInputRecord(input);
466}
467
468
470{
471 dispField.times(s);
472 slipField.times(s);
473 dispGradient.times(s);
474 slipGradient.times(s);
475}
476
478{
480
481 if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 2 ) {
482 //assuming that the RVE thickness is constant in 2D
483 Element *e = this->giveDomain()->giveElement( this->giveDomain()->giveSet(conBoundSet)->giveBoundaryList().at(1) );
484 std::unique_ptr<IntegrationRule> ir = e->giveInterpolation()->giveIntegrationRule( e->giveInterpolation()->giveInterpolationOrder(), e->giveGeometryType() );
486 GaussPoint *gp = ir->getIntegrationPoint(0);
487 double thickness = cs->give(CS_Thickness, gp);
488 return omegaBox * thickness;
489 } else {
490 return omegaBox;
491 }
492
493}
494
495
496} // end namespace oofem
#define REGISTER_BoundaryCondition(class)
virtual double give(CrossSectionProperty a, GaussPoint *gp) const
int giveGlobalNumber() const
Definition dofmanager.h:515
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
Dof * giveDofWithID(int dofID) const
Definition dofmanager.C:127
int giveDofManGlobalNumber() const
Definition dof.C:74
DofIDItem giveDofID() const
Definition dof.h:276
DofManager * giveDofManager() const
Definition dof.h:123
virtual int __givePrescribedEquationNumber()=0
Element * giveElement(int n)
Definition domain.C:165
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
CrossSection * giveCrossSection()
Definition element.C:534
virtual Element_Geometry_Type giveGeometryType() const =0
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Definition engngm.C:452
virtual void assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma, const UnknownNumberingScheme &s, Domain *domain)
Definition engngm.C:889
void assembleVector(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1106
virtual std::unique_ptr< IntegrationRule > giveIntegrationRule(int order, const Element_Geometry_Type) const
Definition feinterpol.C:90
int giveInterpolationOrder() const
Definition feinterpol.h:199
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int giveNumber() const
Definition femcmpnn.h:104
double & at(std::size_t i)
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Definition floatarray.C:403
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
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 times(double s)
Definition floatarray.C:834
void times(double f)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void zero()
Zeroes all coefficient of receiver.
double at(std::size_t i, std::size_t j) const
void subtract(const FloatMatrix &a)
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
int set
Set number for boundary condition to be applied to.
IntArray dofs
Dofs that b.c. is applied to (relevant for Dirichlet type b.c.s).
bool contains(int value) const
Definition intarray.h:292
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
void computeReinfStress(FloatArray &rStress, TimeStep *tStep) override
bool slipGradON
on/off flag specifying whether the slip field should be applied via Neumann BCs
bool slipON
on/off flag specifying whether the displacement gradient should be applied via Neumann BCs
double giveOnSteel(Dof *dof, int pos, const FloatArray u, const FloatArray us)
void computeTransferStress(FloatArray &bStress, TimeStep *tStep) override
int conBoundSet
on/off flag specifying whether the slip gradient should be applied via Neumann BCs
double giveOnConcrete(Dof *dof, int pos, const FloatArray u)
const IntArray & giveNodeList()
Definition set.C:168
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
@ CS_Thickness
Thickness.
ClassFactory & classFactory
#define _IFT_PrescribedDispSlipBCDirichletRC_ReinfYBound
#define _IFT_PrescribedDispSlipBCDirichletRC_ConcreteBoundary
#define _IFT_PrescribedDispSlipBCDirichletRC_ReinfXBound

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