OOFEM 3.0
Loading...
Searching...
No Matches
freewarping.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 "freewarping.h"
36#include "crosssection.h"
37#include "sm/Elements/trwarp.h"
38#include "nummet.h"
39#include "timestep.h"
40#include "element.h"
41#include "dof.h"
42#include "sparsemtrx.h"
43#include "verbose.h"
47#include "datastream.h"
48#include "contextioerr.h"
49#include "classfactory.h"
50#include "outputmanager.h"
51#include "mathfem.h"
52
53//#define THROW_CIOERR(e) throw ContextIOERR(e, __FILE__, __LINE__); // km???
54
55#ifdef __MPI_PARALLEL_MODE
56 #include "problemcomm.h"
57 #include "communicator.h"
58#endif
59
60#include <typeinfo>
61
62namespace oofem {
64
65FreeWarping :: FreeWarping(int i, EngngModel *_master) : StructuralEngngModel(i, _master), loadVector(), displacementVector()
66{
67 ndomains = 1;
68 initFlag = 1;
70}
71
72
73FreeWarping :: ~FreeWarping()
74{
75}
76
77
78NumericalMethod *FreeWarping :: giveNumericalMethod(MetaStep *mStep)
79{
80 if ( isParallel() ) {
81 if ( ( solverType == ST_Petsc ) || ( solverType == ST_Feti ) ) {
82 nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this);
83 }
84 } else {
85 nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this);
86 }
87
88 if ( !nMethod ) {
89 OOFEM_ERROR("linear solver creation failed for lstype %d", solverType);
90 }
91
92 return nMethod.get();
93}
94
95void
96FreeWarping :: initializeFrom(InputRecord &ir)
97{
98 StructuralEngngModel :: initializeFrom(ir);
99
100 int val = 0;
103
104 val = 0;
107
108#ifdef __MPI_PARALLEL_MODE
109 if ( isParallel() ) {
111 communicator = new NodeCommunicator(this, commBuff, this->giveRank(),
112 this->giveNumberOfProcesses());
113 }
114
115#endif
116}
117
118
119void
120FreeWarping :: computeCenterOfGravity()
121{
122 int noCS = this->giveDomain(1)->giveNumberOfCrossSectionModels(); //number of warping Crosssections
123 CG.resize(noCS, 2);
124 // cg.resize(2);
125 FloatArray Sx, Sy, moments, domainArea;
126 Sx.resize(noCS);
127 Sy.resize(noCS);
128 domainArea.resize(noCS);
129 moments.resize(2);
130
131 for ( int i = 1; i <= this->giveDomain(1)->giveNumberOfElements(); ++i ) {
132 int j = this->giveDomain(1)->giveElement(i)->giveCrossSection()->giveNumber();
133 Tr_Warp *trwarp = dynamic_cast< Tr_Warp * >( this->giveDomain(1)->giveElement(i) );
134 if ( trwarp ) {
135 trwarp->computeFirstMomentOfArea(moments);
136 Sx.at(j) += moments.at(1);
137 Sy.at(j) += moments.at(2);
138
139 domainArea.at(j) += fabs( this->giveDomain(1)->giveElement(i)->computeArea() );
140 } else {
141 OOFEM_ERROR("Error during dynamic_cast");
142 }
143 }
144 for ( int j = 1; j <= noCS; ++j ) {
145 double A = domainArea.at(j);
146 if ( A != 0 ) {
147 CG.at(j, 1) = Sx.at(j) / A;
148 CG.at(j, 2) = Sy.at(j) / A;
149 } else {
150 OOFEM_ERROR("Zero crosssection area");
151 }
152 }
153}
154
155void
156FreeWarping :: computeResultAtCenterOfGravity(TimeStep *tStep)
157{
158 int noCS = this->giveDomain(1)->giveNumberOfCrossSectionModels(); //number of warping Crosssections
159 SolutionAtCG.resize(noCS);
160 Element *closestElement;
161 FloatArray lcoords, closest, lcg;
162 SpatialLocalizer *sp = this->giveDomain(1)->giveSpatialLocalizer();
163 sp->init();
164 lcoords.resize(2);
165 closest.resize(2);
166 lcg.resize(2);
167
168 for ( int j = 1; j <= noCS; ++j ) {
169 lcg.at(1) = CG.at(j, 1);
170 lcg.at(2) = CG.at(j, 2);
171 closestElement = sp->giveElementClosestToPoint(lcoords, closest, lcg, 0);
172
173 StructuralElement *sE = dynamic_cast< StructuralElement * >(closestElement);
174 FloatArray u, r, b;
176 sE->computeNmatrixAt(lcoords, N);
177 sE->computeVectorOf(VM_Total, tStep, u);
178 u.resizeWithValues(3);
179 r.beProductOf(N, u);
180
181 SolutionAtCG.at(j) = r.at(1);
182 }
183}
184
185
186double FreeWarping :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof)
187// returns unknown quantity like displacement, velocity of equation eq
188// This function translates this request to numerical method language
189{
190 int eq = dof->__giveEquationNumber();
191#ifdef DEBUG
192 if ( eq == 0 ) {
193 OOFEM_ERROR("invalid equation number");
194 }
195#endif
196
197 if ( tStep != this->giveCurrentStep() ) {
198 OOFEM_ERROR("unknown time step encountered");
199 }
200
201 switch ( mode ) {
202 case VM_Total:
203 case VM_Incremental:
204 if ( displacementVector.isNotEmpty() ) {
205 return displacementVector.at(eq);
206 } else {
207 return 0.;
208 }
209
210 default:
211 OOFEM_ERROR("Unknown is of undefined type for this problem");
212 }
213
214 // return 0.;
215}
216
217
218TimeStep *FreeWarping :: giveNextStep()
219{
220 int istep = this->giveNumberOfFirstStep();
221 StateCounterType counter = 1;
222
223 if ( currentStep ) {
224 istep = currentStep->giveNumber() + 1;
225 counter = currentStep->giveSolutionStateCounter() + 1;
226 }
227
228 previousStep = std :: move(currentStep);
229 currentStep = std::make_unique<TimeStep>(istep, this, 1, ( double ) istep, 0., counter);
230 return currentStep.get();
231}
232
233
234void FreeWarping :: solveYourself()
235{
237
238 if ( this->isParallel() ) {
239 #ifdef __VERBOSE_PARALLEL
240 // force equation numbering before setting up comm maps
242 OOFEM_LOG_INFO("[process rank %d] neq is %d\n", this->giveRank(), neq);
243 #endif
244 this->initializeCommMaps();
245 }
246
247 StructuralEngngModel :: solveYourself();
248}
249
250
251
252void FreeWarping :: solveYourselfAt(TimeStep *tStep)
253{
254 //
255 // creates system of governing eq's and solves them at given time step
256 //
257 // first assemble problem at current time step
258
259 if ( initFlag ) {
260#ifdef VERBOSE
261 OOFEM_LOG_DEBUG("Assembling stiffness matrix\n");
262#endif
263
264 //
265 // first step assemble stiffness Matrix
266 //
267 stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType);
268 if ( !stiffnessMatrix ) {
269 OOFEM_ERROR("sparse matrix creation failed");
270 }
271
272 stiffnessMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() );
273
274 this->assemble( *stiffnessMatrix, tStep, TangentAssembler(TangentStiffness),
276 //
277 // original stiffnes Matrix is singular (no Dirichlet b.c's exist for free warping problem)
278 // thus one diagonal element is made stiffer (for each warping crosssection)
280
281 initFlag = 0;
282 }
283
284#ifdef VERBOSE
285 OOFEM_LOG_DEBUG("Assembling load\n");
286#endif
287
288 //
289 // allocate space for displacementVector
290 //
292 displacementVector.zero();
293
294 //
295 // assembling the load vector
296 //
298 loadVector.zero();
299 this->assembleVector( loadVector, tStep, ExternalForceAssembler(), VM_Total,
301
302 //
303 // internal forces (from Dirichlet b.c's, or thermal expansion, etc.)
304 //
305 // no such forces exist for the free warping problem
306 /*
307 * FloatArray internalForces( this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ) );
308 * internalForces.zero();
309 * this->assembleVector( internalForces, tStep, InternalForceAssembler(), VM_Total,
310 * EModelDefaultEquationNumbering(), this->giveDomain(1) );
311 *
312 * loadVector.subtract(internalForces);
313 */
314
316
317 //
318 // set-up numerical model
319 //
320 this->giveNumericalMethod( this->giveMetaStep( tStep->giveMetaStepNumber() ) );
321
322 //
323 // call numerical model to solve arose problem
324 //
325#ifdef VERBOSE
326 OOFEM_LOG_INFO("\n\nSolving ...\n\n");
327#endif
329 if (s != CR_CONVERGED) {
330 OOFEM_ERROR("No success in solving system.");
331 }
332 tStep->convergedReason = s;
333 //
334 // update computed "displacementVector" with the respect to the center of gravity
335 //
337 //
338 // results are shifted to be zero at the center of gravity (for each warping crosssection)
339 //
341
342
343 // update solution state counter
344 tStep->incrementStateCounter();
345}
346
347
348void
349FreeWarping :: updateDomainLinks()
350{
351 EngngModel :: updateDomainLinks();
352 this->giveNumericalMethod( this->giveCurrentMetaStep() )->setDomain( this->giveDomain(1) );
353}
354
355
356void
357FreeWarping :: printOutputAt(FILE *file, TimeStep *tStep)
358{
359 if ( this->giveDomain(1)->giveOutputManager()->testTimeStepOutput(tStep) ) {
360 return;
361 }
362
363 EngngModel :: printOutputAt(file, tStep);
364
365 fprintf(file, "\n Center of gravity:");
366 for ( int j = 1; j <= this->giveDomain(1)->giveNumberOfCrossSectionModels(); ++j ) {
367 fprintf(file, "\n CrossSection %d x = %f y = %f", j, CG.at(j, 1), CG.at(j, 2) );
368 }
369}
370
371
372int
373FreeWarping :: estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType)
374{
375 int count = 0, pcount = 0;
376 Domain *domain = this->giveDomain(1);
377
378 if ( packUnpackType == 0 ) {
379 for ( int map: commMap ) {
380 for ( Dof *jdof: *domain->giveDofManager( map ) ) {
381 if ( jdof->isPrimaryDof() && ( jdof->__giveEquationNumber() ) ) {
382 count++;
383 } else {
384 pcount++;
385 }
386 }
387 }
388
389 // --------------------------------------------------------------------------------
390 // only pcount is relevant here, since only prescribed components are exchanged !!!!
391 // --------------------------------------------------------------------------------
392
393 return ( buff.givePackSizeOfDouble(1) * pcount );
394 } else if ( packUnpackType == 1 ) {
395 for ( int map: commMap ) {
396 count += domain->giveElement( map )->estimatePackSize(buff);
397 }
398
399 return count;
400 }
401
402 return 0;
403}
404
405
406void
407FreeWarping :: updateStiffnessMatrix(SparseMtrx *answer)
408{
409 // increase diagonal stiffness (coresponding to the 1st node of 1st element ) for each crosssection
410 for ( int j = 1; j <= this->giveDomain(1)->giveNumberOfCrossSectionModels(); j++ ) {
411 for ( auto &elem : this->giveDomain(1)->giveElements() ) {
412 int CSnumber = elem->giveCrossSection()->giveNumber();
413 if ( CSnumber == j ) {
414 IntArray locationArray;
416 elem->giveLocationArray(locationArray, s);
417 if ( locationArray.at(1) != 0 ) {
418 int cn = locationArray.at(1);
419 if ( answer->at(cn, cn) != 0 ) {
420 answer->at(cn, cn) *= 2;
421 } else {
422 answer->at(cn, cn) = 1000;
423 }
424 }
425 break;
426 }
427 }
428 }
429}
430
431
432void
433FreeWarping :: updateComputedResults(FloatArray &answer, TimeStep *tStep)
434{
435 // value of result in the center of gravity is interpolated
436 // and substracted from the original solution vector
437 // (individualy for each crosssection)
438
439
440 // set up vector of crosssections numbers
441 // through all nodes
442 int length = answer.giveSize();
443 IntArray CSindicator(length);
445 for ( int i = 1; i <= this->giveDomain(1)->giveNumberOfElements(); i++ ) {
446 int CSnumber = this->giveDomain(1)->giveElement(i)->giveCrossSection()->giveNumber();
447 IntArray locationArray;
448 this->giveDomain(1)->giveElement(i)->giveLocationArray(locationArray, s);
449 for ( int j = 1; j <= 3; j++ ) {
450 int locationNumber = locationArray.at(j);
451 if ( locationNumber != 0 ) {
452 CSindicator.at(locationNumber) = CSnumber;
453 }
454 }
455 }
456
457 // substracr answer for corresponding warping crosssection
458 for ( int i = 1; i <= length; i++ ) {
459 answer.at(i) -= SolutionAtCG.at( CSindicator.at(i) );
460 }
461}
462} // end namespace oofem
double length(const Vector &a)
Definition CSG.h:88
#define N(a, b)
#define REGISTER_EngngModel(class)
virtual int givePackSizeOfDouble(std::size_t count)=0
virtual int __giveEquationNumber() const =0
DofManager * giveDofManager(int n)
Definition domain.C:317
Element * giveElement(int n)
Definition domain.C:165
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
int estimatePackSize(DataStream &buff)
Definition element.C:1748
void initializeCommMaps(bool forceInit=false)
Definition engngm.C:2147
virtual TimeStep * giveCurrentStep(bool force=false)
Definition engngm.h:717
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Definition engngm.C:452
int giveNumberOfProcesses() const
Returns the number of collaborating processes.
Definition engngm.h:1156
int giveRank() const
Returns domain rank in a group of collaborating processes (0..groupSize-1).
Definition engngm.h:1154
ProblemCommunicator * communicator
Communicator.
Definition engngm.h:315
std ::unique_ptr< TimeStep > previousStep
Previous time step.
Definition engngm.h:243
MetaStep * giveCurrentMetaStep()
Returns current meta step.
Definition engngm.C:1900
int ndomains
Number of receiver domains.
Definition engngm.h:215
Domain * giveDomain(int n)
Definition engngm.C:1936
std ::unique_ptr< TimeStep > currentStep
Current time step.
Definition engngm.h:241
MetaStep * giveMetaStep(int i)
Returns the i-th meta step.
Definition engngm.h:773
CommunicatorBuff * commBuff
Common Communicator buffer.
Definition engngm.h:313
virtual int giveNumberOfFirstStep(bool force=false)
Definition engngm.h:763
bool isParallel() const
Returns true if receiver in parallel mode.
Definition engngm.h:1152
int updateSharedDofManagers(FloatArray &answer, const UnknownNumberingScheme &s, int ExchangeTag)
Definition engngm.C:2162
void assembleVector(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1106
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 resizeWithValues(Index s, std::size_t allocChunk=0)
Definition floatarray.C:103
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void updateStiffnessMatrix(SparseMtrx *answer)
FloatArray loadVector
Definition freewarping.h:68
FloatArray SolutionAtCG
Definition freewarping.h:79
std ::unique_ptr< SparseLinearSystemNM > nMethod
Numerical method used to solve the problem.
Definition freewarping.h:74
std ::unique_ptr< SparseMtrx > stiffnessMatrix
Definition freewarping.h:67
NumericalMethod * giveNumericalMethod(MetaStep *mStep) override
Returns reference to receiver's numerical method.
Definition freewarping.C:78
FloatArray displacementVector
Definition freewarping.h:69
void computeResultAtCenterOfGravity(TimeStep *tStep)
void computeCenterOfGravity()
LinSystSolverType solverType
Definition freewarping.h:71
SparseMtrxType sparseMtrxType
Definition freewarping.h:72
void updateComputedResults(FloatArray &answer, TimeStep *tStep)
int & at(std::size_t i)
Definition intarray.h:104
virtual double & at(int i, int j)=0
Returns coefficient at position (i,j).
virtual int init(bool force=false)
virtual Element * giveElementClosestToPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &coords, int region=0)=0
virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer)
StructuralEngngModel(int i, EngngModel *master=nullptr)
Creates new StructuralEngngModel with number i, associated to domain d.
int giveMetaStepNumber()
Returns receiver's meta step number.
Definition timestep.h:150
void incrementStateCounter()
Updates solution state counter.
Definition timestep.h:213
ConvergedReason convergedReason
Status of solution step (Converged,.
Definition timestep.h:120
void computeFirstMomentOfArea(FloatArray &answer)
Definition trwarp.C:179
#define _IFT_EngngModel_lstype
Definition engngm.h:91
#define _IFT_EngngModel_smtype
Definition engngm.h:92
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
FloatArrayF< N > assemble(const FloatArrayF< M > &x, int const (&c)[M])
Assemble components into zero matrix.
long StateCounterType
StateCounterType type used to indicate solution state.
ClassFactory & classFactory

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