OOFEM 3.0
Loading...
Searching...
No Matches
nldeidynamic.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 "timestep.h"
37#include "dofmanager.h"
38#include "element.h"
39#include "dof.h"
40#include "verbose.h"
41#include "outputmanager.h"
42#include "mathfem.h"
43#include "datastream.h"
44#include "contextioerr.h"
45#include "sparsemtrx.h"
46#include "classfactory.h"
48
49#ifdef __MPI_PARALLEL_MODE
50 #include "problemcomm.h"
51 #include "processcomm.h"
52#endif
53
54namespace oofem {
55#define ZERO_REL_MASS 1.E-6
56
58
59NlDEIDynamic :: NlDEIDynamic(int i, EngngModel *_master) : StructuralEngngModel(i, _master), massMatrix(), loadVector(),
62 initFlag(1)
63{
64 ndomains = 1;
65}
66
67
68NlDEIDynamic :: ~NlDEIDynamic()
69{ }
70
71
72NumericalMethod *NlDEIDynamic :: giveNumericalMethod(MetaStep *mStep)
73{
74 if ( !nMethod ) {
75 nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this);
76 }
77 return nMethod.get();
78}
79
80
81void
82NlDEIDynamic :: initializeFrom(InputRecord &ir)
83{
84 StructuralEngngModel :: initializeFrom(ir);
85
86 IR_GIVE_FIELD(ir, dumpingCoef, _IFT_NlDEIDynamic_dumpcoef); // C = dumpingCoef * M
88
89 reductionFactor = 1.;
91
92 drFlag = 0;
94 if ( drFlag ) {
97 }
98
99#ifdef __MPI_PARALLEL_MODE
101 communicator = new NodeCommunicator(this, commBuff, this->giveRank(),
102 this->giveNumberOfProcesses());
103
105 nonlocalExt = 1;
107 this->giveNumberOfProcesses());
108 }
109
110#endif
111}
112
113
114double NlDEIDynamic :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof)
115// Returns unknown quantity like displacement, velocity of equation eq.
116// This function translates this request to numerical method language.
117{
118 int eq = dof->__giveEquationNumber();
119#ifdef DEBUG
120 if ( eq == 0 ) {
121 OOFEM_ERROR("invalid equation number");
122 }
123#endif
124
125 if ( tStep != this->giveCurrentStep() ) {
126 OOFEM_ERROR("unknown time step encountered");
127 }
128
129 switch ( mode ) {
130 case VM_Total:
131 return displacementVector.at(eq);
132
133 case VM_Incremental:
135
136 case VM_Velocity:
137 return velocityVector.at(eq);
138
139 case VM_Acceleration:
140 return accelerationVector.at(eq);
141
142 default:
143 OOFEM_ERROR("Unknown is of undefined type for this problem");
144 }
145
146 // return 0.;
147}
148
149
150TimeStep *NlDEIDynamic :: giveNextStep()
151{
152 int istep = 0;
153 double totalTime = 0;
154 StateCounterType counter = 1;
155
156 if ( currentStep ) {
157 totalTime = currentStep->giveTargetTime() + deltaT;
158 istep = currentStep->giveNumber() + 1;
159 counter = currentStep->giveSolutionStateCounter() + 1;
160 }
161
162 previousStep = std :: move(currentStep);
163 currentStep = std::make_unique<TimeStep>(istep, this, 1, totalTime, deltaT, counter);
164
165 return currentStep.get();
166}
167
168
169void NlDEIDynamic :: solveYourself()
170{
171 if ( this->isParallel() ) {
172 #ifdef __VERBOSE_PARALLEL
173 // Force equation numbering before setting up comm maps.
175 OOFEM_LOG_INFO("[process rank %d] neq is %d\n", this->giveRank(), neq);
176 #endif
177
178 this->initializeCommMaps();
179 }
180
181 StructuralEngngModel :: solveYourself();
182}
183
184void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep)
185{
186 //
187 // Creates system of governing eq's and solves them at given time step.
188 //
189
190 Domain *domain = this->giveDomain(1);
192 double maxOm = 0.;
193
194 if ( initFlag ) {
195#ifdef VERBOSE
196 OOFEM_LOG_DEBUG("Assembling mass matrix\n");
197#endif
198
199 //
200 // Assemble mass matrix.
201 //
202 this->computeMassMtrx(massMatrix, maxOm, tStep);
203
204 if ( drFlag ) {
205 // If dynamic relaxation: Assemble amplitude load vector.
206 loadRefVector.resize(neq);
207 loadRefVector.zero();
208
209 this->computeLoadVector(loadRefVector, VM_Total, tStep);
210
211#ifdef __MPI_PARALLEL_MODE
212 // Compute the processor part of load vector norm pMp
213 this->pMp = 0.0;
214 double my_pMp = 0.0;
215 for ( auto &dman : domain->giveDofManagers() ) {
216 dofManagerParallelMode dofmanmode = dman->giveParallelMode();
217
218 // Skip all remote and null dofmanagers
219 double coeff = 1.0;
220 if ( ( dofmanmode == DofManager_remote ) || ( ( dofmanmode == DofManager_null ) ) ) {
221 continue;
222 } else if ( dofmanmode == DofManager_shared ) {
223 coeff = 1. / dman->givePartitionsConnectivitySize();
224 }
225
226 // For shared nodes we add locally an average = 1/givePartitionsConnectivitySize()*contribution,
227 for ( auto &dof: *dman ) {
228 int eqNum;
229 if ( dof->isPrimaryDof() && ( eqNum = dof->__giveEquationNumber() ) ) {
230 my_pMp += coeff * loadRefVector.at(eqNum) * loadRefVector.at(eqNum) / massMatrix.at(eqNum);
231 }
232 }
233 }
234
235 // Sum up the contributions from processors.
236 MPI_Allreduce(& my_pMp, & pMp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
237#else
238 this->pMp = 0.0;
239 for ( int i = 1; i <= neq; i++ ) {
240 pMp += loadRefVector.at(i) * loadRefVector.at(i) / massMatrix.at(i);
241 }
242#endif
243 // Solve for rate of loading process (parameter "c") (undamped system assumed),
244 if ( dumpingCoef < 1.e-3 ) {
245 c = 3.0 * this->pyEstimate / pMp / Tau / Tau;
246 } else {
248 ( -3.0 / 2.0 + dumpingCoef * Tau + 2.0 * exp(-dumpingCoef * Tau) - 0.5 * exp(-2.0 * dumpingCoef * Tau) );
249 }
250 }
251
252 initFlag = 0;
253 }
254
255
256 if ( tStep->isTheFirstStep() ) {
257 //
258 // Special init step - Compute displacements at tstep 0.
259 //
260 displacementVector.resize(neq);
261 displacementVector.zero();
264 velocityVector.resize(neq);
265 velocityVector.zero();
266 accelerationVector.resize(neq);
267 accelerationVector.zero();
268
269 for ( auto &node : domain->giveDofManagers()) {
270 for ( Dof *dof: *node ) {
271 // Ask for initial values obtained from
272 // bc (boundary conditions) and ic (initial conditions)
273 // all dofs are expected to be DisplacementVector type.
274 if ( !dof->isPrimaryDof() ) {
275 continue;
276 }
277
278 int jj = dof->__giveEquationNumber();
279 if ( jj ) {
280 displacementVector.at(jj) = dof->giveUnknown(VM_Total, tStep);
281 velocityVector.at(jj) = dof->giveUnknown(VM_Velocity, tStep);
282 accelerationVector.at(jj) = dof->giveUnknown(VM_Acceleration, tStep);
283 }
284 }
285 }
286
287 //
288 // Set-up numerical model.
289 //
290
291 // Try to determine the best deltaT,
292 double maxDt = reductionFactor * 2.0 / sqrt(maxOm);
293 int newNumberOfSteps = this->numberOfSteps;
294 double newDeltaT = 0;
295
296 if ( deltaT > maxDt ) {
297 //Scale number of steps based on reduced time step
298 newDeltaT = maxDt;
299 newNumberOfSteps = (int) floor(numberOfSteps*deltaT/newDeltaT);
300 this->giveMetaStep(1)->setNumberOfSteps(newNumberOfSteps);
301 this->deltaT = newDeltaT;
302 tStep->setTimeIncrement(deltaT);
303
304 // Print reduced time step increment and minimum period Tmin
305 OOFEM_LOG_RELEVANT("deltaT reduced to %e, Tmin is %e, nsteps is %d\n", this->deltaT, maxDt * M_PI, newNumberOfSteps);
306 }
307
308 for ( int j = 1; j <= neq; j++ ) {
311 }
312#ifdef VERBOSE
313 OOFEM_LOG_RELEVANT( "\n\nSolving [Step number %8d, Time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() );
314#endif
315 return;
316 } // end of init step
317
318#ifdef VERBOSE
319 OOFEM_LOG_DEBUG("Assembling right hand side\n");
320#endif
321
323
324 // Update solution state counter
325 tStep->incrementStateCounter();
326
327 // Compute internal forces.
328 this->updateInternalRHS(internalForces, tStep, this->giveDomain(1), nullptr);
329
330 if ( !drFlag ) {
331 //
332 // Assembling the element part of load vector.
333 //
334 this->computeLoadVector(loadVector, VM_Total, tStep);
335 //
336 // Assembling additional parts of right hand side.
337 //
338 loadVector.subtract(internalForces);
339 } else {
340 // Dynamic relaxation
341 // compute load factor
342 pt = 0.0;
343
344#ifdef __MPI_PARALLEL_MODE
345 double my_pt = 0.0;
346 for ( auto &dman : domain->giveDofManagers() ) {
347 dofManagerParallelMode dofmanmode = dman->giveParallelMode();
348 // skip all remote and null dofmanagers
349 double coeff = 1.0;
350 if ( ( dofmanmode == DofManager_remote ) || ( dofmanmode == DofManager_null ) ) {
351 continue;
352 } else if ( dofmanmode == DofManager_shared ) {
353 coeff = 1. / dman->givePartitionsConnectivitySize();
354 }
355
356 // For shared nodes we add locally an average= 1/givePartitionsConnectivitySize()*contribution.
357 for ( auto &dof: *dman ) {
358 int eqNum;
359 if ( dof->isPrimaryDof() && ( eqNum = dof->__giveEquationNumber() ) ) {
360 my_pt += coeff * internalForces.at(eqNum) * loadRefVector.at(eqNum) / massMatrix.at(eqNum);
361 }
362 }
363 }
364
365 // Sum up the contributions from processors.
366 MPI_Allreduce(& my_pt, & pt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
367#else
368 for ( int k = 1; k <= neq; k++ ) {
369 pt += internalForces.at(k) * loadRefVector.at(k) / massMatrix.at(k);
370 }
371
372#endif
373 pt = pt / pMp;
374 if ( dumpingCoef < 1.e-3 ) {
375 pt += c * ( Tau - tStep->giveTargetTime() ) / Tau;
376 } else {
377 pt += c * ( 1.0 - exp( dumpingCoef * ( tStep->giveTargetTime() - Tau ) ) ) / dumpingCoef / Tau;
378 }
379
381 for ( int k = 1; k <= neq; k++ ) {
382 loadVector.at(k) = pt * loadRefVector.at(k) - internalForces.at(k);
383 }
384
385
386 // Compute relative error.
387 double err = 0.0;
388#ifdef __MPI_PARALLEL_MODE
389 double my_err = 0.0;
390
391 for ( auto &dman : domain->giveDofManagers() ) {
392 auto dofmanmode = dman->giveParallelMode();
393 // Skip all remote and null dofmanagers.
394 double coeff = 1.0;
395 if ( ( dofmanmode == DofManager_remote ) || ( dofmanmode == DofManager_null ) ) {
396 continue;
397 } else if ( dofmanmode == DofManager_shared ) {
398 coeff = 1. / dman->givePartitionsConnectivitySize();
399 }
400
401 // For shared nodes we add locally an average= 1/givePartitionsConnectivitySize()*contribution.
402 for ( auto &dof: *dman ) {
403 int eqNum;
404 if ( dof->isPrimaryDof() && ( eqNum = dof->__giveEquationNumber() ) ) {
405 my_err += coeff * loadVector.at(eqNum) * loadVector.at(eqNum) / massMatrix.at(eqNum);
406 }
407 }
408 }
409
410 // Sum up the contributions from processors.
411 MPI_Allreduce(& my_err, & err, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
412
413#else
414 for ( int k = 1; k <= neq; k++ ) {
415 err = loadVector.at(k) * loadVector.at(k) / massMatrix.at(k);
416 }
417
418#endif
419 err = err / ( pMp * pt * pt );
420 OOFEM_LOG_RELEVANT("Relative error is %e, loadlevel is %e\n", err, pt);
421 }
422
423 for ( int j = 1; j <= neq; j++ ) {
424 loadVector.at(j) +=
425 massMatrix.at(j) * ( ( 1. / ( deltaT * deltaT ) ) - dumpingCoef * 1. / ( 2. * deltaT ) ) *
427 }
428
429 //
430 // Set-up numerical model
431 //
432 /* it is not necesary to call numerical method
433 * approach used here is not good, but effective enough
434 * inverse of diagonal mass matrix is done here
435 */
436 //
437 // call numerical model to solve arised problem - done localy here
438 //
439#ifdef VERBOSE
440 OOFEM_LOG_RELEVANT( "\n\nSolving [Step number %8d, Time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() );
441#endif
442
443 // NM_Status s = nMethod->solve(*massMatrix, loadVector, displacementVector);
444 // if ( !(s & NM_Success) ) {
445 // OOFEM_ERROR("No success in solving system. Ma=f");
446 // }
447
448
449 for ( int i = 1; i <= neq; i++ ) {
450 double prevIncrOfDisplacement = previousIncrementOfDisplacementVector.at(i);
451 double incrOfDisplacement = loadVector.at(i) /
452 ( massMatrix.at(i) * ( 1. / ( deltaT * deltaT ) + dumpingCoef / ( 2. * deltaT ) ) );
453
454 accelerationVector.at(i) = ( incrOfDisplacement - prevIncrOfDisplacement ) / ( deltaT * deltaT );
455 velocityVector.at(i) = ( incrOfDisplacement + prevIncrOfDisplacement ) / ( 2. * deltaT );
456 previousIncrementOfDisplacementVector.at(i) = incrOfDisplacement;
457 }
458}
459
460
461void NlDEIDynamic :: updateYourself(TimeStep *tStep)
462{
463 // Updates internal state to reached one
464 // all internal variables are directly updated by
465 // numerical method - void function here
466
467 // this->updateInternalState(tStep);
468 StructuralEngngModel :: updateYourself(tStep);
469}
470
471
472void
473NlDEIDynamic :: computeLoadVector(FloatArray &answer, ValueModeType mode, TimeStep *tStep)
474{
476 answer.zero();
477
478 //
479 // Assemble the nodal part of load vector.
480 //
481 this->assembleVector( answer, tStep, ExternalForceAssembler(), mode,
483
484 //
485 // Exchange contributions.
486 //
488}
489
490
491void
492NlDEIDynamic :: computeMassMtrx(FloatArray &massMatrix, double &maxOm, TimeStep *tStep)
493{
494 Domain *domain = this->giveDomain(1);
495 int nelem = domain->giveNumberOfElements();
497 FloatMatrix charMtrx, charMtrx2, R;
498 IntArray loc;
500
501#ifndef LOCAL_ZERO_MASS_REPLACEMENT
502 FloatArray diagonalStiffMtrx;
503#endif
504
505 maxOm = 0.;
506 massMatrix.resize(neq);
507 massMatrix.zero();
508 for ( int i = 1; i <= nelem; i++ ) {
509 Element *element = domain->giveElement(i);
510
511 // skip remote elements (these are used as mirrors of remote elements on other domains
512 // when nonlocal constitutive models are used. They introduction is necessary to
513 // allow local averaging on domains without fine grain communication between domains).
514 if ( element->giveParallelMode() == Element_remote ) {
515 continue;
516 }
517
518 element->giveLocationArray(loc, en);
519 element->giveCharacteristicMatrix(charMtrx, LumpedMassMatrix, tStep);
520 if ( charMtrx.isNotEmpty() ) {
522 if ( element->giveRotationMatrix(R) ) {
523 charMtrx.rotatedWith(R);
524 }
525 }
526
527#ifdef LOCAL_ZERO_MASS_REPLACEMENT
528 element->giveCharacteristicMatrix(charMtrx2, TangentStiffnessMatrix, tStep);
529 if ( charMtrx2.isNotEmpty() ) {
531 if ( R.isNotEmpty() ) {
532 charMtrx2.rotatedWith(R);
533 }
534 }
535#endif
536
537#ifdef DEBUG
538 if ( loc.giveSize() != charMtrx.giveNumberOfRows() ) {
539 OOFEM_ERROR("dimension mismatch");
540 }
541#endif
542
543 int n = loc.giveSize();
544
545#ifdef LOCAL_ZERO_MASS_REPLACEMENT
546
547 double maxElmass = -1.0;
548 for ( int j = 1; j <= n; j++ ) {
549 maxElmass = max( maxElmass, charMtrx.at(j, j) );
550 }
551
552 if ( maxElmass <= 0.0 ) {
553 OOFEM_WARNING("Element (%d) with zero (or negative) lumped mass encountered\n", i);
554 } else {
555
556 if (charMtrx2.isNotEmpty() ) {
557 // in case stifness matrix defined, we can generate artificial mass
558 // in those DOFs without mass
559 double maxOmEl = 0.;
560 for ( int j = 1; j <= n; j++ ) {
561 if ( charMtrx.at(j, j) > maxElmass * ZERO_REL_MASS ) {
562 double maxOmi = charMtrx2.at(j, j) / charMtrx.at(j, j);
563 maxOmEl = ( maxOmEl > maxOmi ) ? ( maxOmEl ) : ( maxOmi );
564 }
565 }
566
567 maxOm = ( maxOm > maxOmEl ) ? ( maxOm ) : ( maxOmEl );
568
569 for ( int j = 1; j <= n; j++ ) {
570 int jj = loc.at(j);
571 if ( ( jj ) && ( charMtrx.at(j, j) <= maxElmass * ZERO_REL_MASS ) ) {
572 charMtrx.at(j, j) = charMtrx2.at(j, j) / maxOmEl;
573 }
574 }
575 }
576 }
577#endif
578
579 for ( int j = 1; j <= n; j++ ) {
580 int jj = loc.at(j);
581 if ( jj ) {
582 massMatrix.at(jj) += charMtrx.at(j, j);
583 }
584 }
585 }
586
587#ifndef LOCAL_ZERO_MASS_REPLACEMENT
588 // If init step - find minimun period of vibration in order to
589 // determine maximal admisible time step
590 // global variant
591 for ( auto &element : domain->giveElements() ) {
592 element->giveLocationArray(loc, en);
593 element->giveCharacteristicMatrix(charMtrx, TangentStiffnessMatrix, tStep);
594 if ( charMtrx.isNotEmpty() ) {
596 if ( element->giveRotationMatrix(R) ) {
597 charMtrx.rotatedWith(R);
598 }
599 }
600
601 int n = loc.giveSize();
602 for ( int j = 1; j <= n; j++ ) {
603 int jj = loc.at(j);
604 if ( jj ) {
605 diagonalStiffMtrx.at(jj) += charMtrx.at(j, j);
606 }
607 }
608 }
609
610 // Find find global minimun period of vibration
611 double maxElmass = -1.0;
612 for ( int j = 1; j <= n; j++ ) {
613 maxElmass = max( maxElmass, charMtrx.at(j, j) );
614 }
615
616 if ( maxElmass <= 0.0 ) {
617 OOFEM_ERROR("Element with zero (or negative) lumped mass encountered");
618 }
619
620 for ( int j = 1; j <= neq; j++ ) {
621 if ( massMatrix.at(j) > maxElmass * ZERO_REL_MASS ) {
622 double maxOmi = diagonalStiffMtrx.at(j) / massMatrix.at(j);
623 maxOm = ( maxOm > maxOmi ) ? ( maxOm ) : ( maxOmi );
624 }
625 }
626
627 // Set ZERO MASS members in massMatrix to value which corresponds to global maxOm.
628 for ( int i = 1; i <= neq; i++ ) {
629 if ( massMatrix.at(i) <= maxElmass * ZERO_REL_MASS ) {
630 massMatrix.at(i) = diagonalStiffMtrx.at(i) / maxOm;
631 }
632 }
633#endif
634
636
637#ifdef __MPI_PARALLEL_MODE
638 // Determine maxOm over all processes.
639 #ifdef __USE_MPI
640 double globalMaxOm;
641
642 #ifdef __VERBOSE_PARALLEL
643 VERBOSEPARALLEL_PRINT( "NlDEIDynamic :: computeMassMtrx", "Reduce of maxOm started", this->giveRank() );
644 #endif
645
646 int result = MPI_Allreduce(& maxOm, & globalMaxOm, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
647
648 #ifdef __VERBOSE_PARALLEL
649 VERBOSEPARALLEL_PRINT( "NlDEIDynamic :: computeMassMtrx", "Reduce of maxOm finished", this->giveRank() );
650 #endif
651
652 if ( result != MPI_SUCCESS ) {
653 OOFEM_ERROR("MPI_Allreduce failed");
654 }
655
656 maxOm = globalMaxOm;
657 #else
658WARNING: NOT SUPPORTED MESSAGE PARSING LIBRARY
659 #endif
660
661#endif
662}
663
664int
665NlDEIDynamic :: estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType)
666{
667 int count = 0, pcount = 0;
668 Domain *domain = this->giveDomain(1);
669
670 if ( packUnpackType == 0 ) {
671 for ( int inod: commMap ) {
672 DofManager *dman = domain->giveDofManager( inod );
673 for ( Dof *dof: *dman ) {
674 if ( dof->isPrimaryDof() && ( dof->__giveEquationNumber() ) ) {
675 count++;
676 } else {
677 pcount++;
678 }
679 }
680 }
681
682 return ( buff.givePackSizeOfDouble(1) * max(count, pcount) );
683 } else if ( packUnpackType == 1 ) {
684 for ( int inod: commMap ) {
685 count += domain->giveElement( inod )->estimatePackSize(buff);
686 }
687
688 return count;
689 }
690
691 return 0;
692}
693
694void NlDEIDynamic :: saveContext(DataStream &stream, ContextMode mode)
695{
697
698 StructuralEngngModel :: saveContext(stream, mode);
699
700 if ( ( iores = previousIncrementOfDisplacementVector.storeYourself(stream) ) != CIO_OK ) {
701 THROW_CIOERR(iores);
702 }
703
704 if ( ( iores = displacementVector.storeYourself(stream) ) != CIO_OK ) {
705 THROW_CIOERR(iores);
706 }
707
708 if ( ( iores = velocityVector.storeYourself(stream) ) != CIO_OK ) {
709 THROW_CIOERR(iores);
710 }
711
712 if ( ( iores = accelerationVector.storeYourself(stream) ) != CIO_OK ) {
713 THROW_CIOERR(iores);
714 }
715
716 if ( !stream.write(deltaT) ) {
718 }
719}
720
721
722void NlDEIDynamic :: restoreContext(DataStream &stream, ContextMode mode)
723{
725
726 StructuralEngngModel :: restoreContext(stream, mode);
727
728 if ( ( iores = previousIncrementOfDisplacementVector.restoreYourself(stream) ) != CIO_OK ) {
729 THROW_CIOERR(iores);
730 }
731
732 if ( ( iores = displacementVector.restoreYourself(stream) ) != CIO_OK ) {
733 THROW_CIOERR(iores);
734 }
735
736 if ( ( iores = velocityVector.restoreYourself(stream) ) != CIO_OK ) {
737 THROW_CIOERR(iores);
738 }
739
740 if ( ( iores = accelerationVector.restoreYourself(stream) ) != CIO_OK ) {
741 THROW_CIOERR(iores);
742 }
743
744 if ( !stream.read(deltaT) ) {
746 }
747}
748
749
750void
751NlDEIDynamic :: printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep)
752{
753 static char dofchar[] = "dva";
754 static ValueModeType dofmodes[] = {
755 VM_Total, VM_Velocity, VM_Acceleration
756 };
757
758 iDof->printMultipleOutputAt(stream, tStep, dofchar, dofmodes, 3);
759}
760
761
762void
763NlDEIDynamic :: printOutputAt(FILE *file, TimeStep *tStep)
764{
765 if ( !this->giveDomain(1)->giveOutputManager()->testTimeStepOutput(tStep) ) {
766 return; // do not print even Solution step header
767 }
768
769 fprintf(file, "\n\nOutput for time %.3e, solution step number %d\n", tStep->giveTargetTime(), tStep->giveNumber() );
770 if ( drFlag ) {
771 fprintf(file, "Reached load level : %e\n\n", this->pt);
772 }
773
774 this->giveDomain(1)->giveOutputManager()->doDofManOutput(file, tStep);
775 this->giveDomain(1)->giveOutputManager()->doElementOutput(file, tStep);
776 this->printReactionForces(tStep, 1, file);
777}
778} // end namespace oofem
#define REGISTER_EngngModel(class)
virtual int read(int *data, std::size_t count)=0
Reads count integer values into array pointed by data.
virtual int givePackSizeOfDouble(std::size_t count)=0
virtual int write(const int *data, std::size_t count)=0
Writes count integer values from array pointed by data.
virtual void printMultipleOutputAt(FILE *File, TimeStep *tStep, char *ch, ValueModeType *mode, int nite)
Definition dof.C:92
virtual int __giveEquationNumber() const =0
int giveNumberOfElements() const
Returns number of elements in domain.
Definition domain.h:463
std ::vector< std ::unique_ptr< DofManager > > & giveDofManagers()
Definition domain.h:427
DofManager * giveDofManager(int n)
Definition domain.C:317
Element * giveElement(int n)
Definition domain.C:165
std ::vector< std ::unique_ptr< Element > > & giveElements()
Definition domain.h:294
virtual bool giveRotationMatrix(FloatMatrix &answer)
Definition element.C:298
virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep)
Definition element.C:620
void giveLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s, IntArray *dofIds=NULL) const
Definition element.C:429
int estimatePackSize(DataStream &buff)
Definition element.C:1748
elementParallelMode giveParallelMode() const
Definition element.h:1139
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
int ndomains
Number of receiver domains.
Definition engngm.h:215
ProblemCommunicator * nonlocCommunicator
NonLocal Communicator. Necessary when nonlocal constitutive models are used.
Definition engngm.h:318
int numberOfSteps
Total number of time steps.
Definition engngm.h:219
Domain * giveDomain(int n)
Definition engngm.C:1936
std ::unique_ptr< TimeStep > currentStep
Current time step.
Definition engngm.h:241
int nonlocalExt
Flag indicating if nonlocal extension active, which will cause data to be sent between shared element...
Definition engngm.h:293
MetaStep * giveMetaStep(int i)
Returns the i-th meta step.
Definition engngm.h:773
CommunicatorBuff * commBuff
Common Communicator buffer.
Definition engngm.h:313
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
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void rotatedWith(const FloatMatrix &r, char mode='n')
bool isNotEmpty() const
Tests for empty matrix.
int giveNumberOfRows() const
Returns number of rows of receiver.
double at(std::size_t i, std::size_t j) const
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
FloatArray internalForces
Vector of real nodal forces.
FloatArray massMatrix
Mass matrix.
double pMp
Product of p^tM^(-1)p; where p is reference load vector.
FloatArray accelerationVector
double dumpingCoef
Dumping coefficient (C = dumpingCoef * MassMtrx).
double reductionFactor
Optional reduction factor for time step deltaT.
FloatArray loadRefVector
Reference load vector.
double deltaT
Time step.
FloatArray velocityVector
void computeMassMtrx(FloatArray &mass, double &maxOm, TimeStep *tStep)
double Tau
End of time interval.
double pt
Load level.
FloatArray loadVector
Load vector.
double pyEstimate
Estimate of loadRefVector^T*displacementVector(Tau).
LinSystSolverType solverType
FloatArray previousIncrementOfDisplacementVector
Vector storing displacement increments.
FloatArray displacementVector
Displacement, velocity and acceleration vectors.
std::unique_ptr< SparseLinearSystemNM > nMethod
int initFlag
Flag indicating the need for initialization.
double c
Parameter determining rate of the loading process.
void computeLoadVector(FloatArray &answer, ValueModeType mode, TimeStep *tStep)
int drFlag
Flag indicating whether dynamic relaxation takes place.
void printReactionForces(TimeStep *tStep, int id, FILE *out)
StructuralEngngModel(int i, EngngModel *master=nullptr)
Creates new StructuralEngngModel with number i, associated to domain d.
void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override
void incrementStateCounter()
Updates solution state counter.
Definition timestep.h:213
double giveTargetTime()
Returns target time.
Definition timestep.h:164
void setTimeIncrement(double newDt)
Sets solution step time increment.
Definition timestep.h:170
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
bool isTheFirstStep()
Definition timestep.C:148
#define THROW_CIOERR(e)
#define OOFEM_WARNING(...)
Definition error.h:80
#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
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define OOFEM_LOG_RELEVANT(...)
Definition logger.h:142
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
#define M_PI
Definition mathfem.h:52
long ContextMode
Definition contextmode.h:43
@ Element_remote
Element in active domain is only mirror of some remote element.
Definition element.h:89
long StateCounterType
StateCounterType type used to indicate solution state.
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
dofManagerParallelMode
In parallel mode, this type indicates the mode of DofManager.
Definition dofmanager.h:66
@ DofManager_shared
Definition dofmanager.h:68
@ DofManager_null
Definition dofmanager.h:74
@ DofManager_remote
Definition dofmanager.h:71
ClassFactory & classFactory
@ CIO_IOERR
General IO error.
#define ZERO_REL_MASS
#define _IFT_NlDEIDynamic_reduct
#define _IFT_NlDEIDynamic_dumpcoef
#define _IFT_NlDEIDynamic_deltat
#define _IFT_NlDEIDynamic_nonlocalext
#define _IFT_NlDEIDynamic_tau
#define _IFT_NlDEIDynamic_py
#define _IFT_NlDEIDynamic_drflag
#define VERBOSEPARALLEL_PRINT(service, str, rank)
Definition parallel.h:50

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