OOFEM 3.0
Loading...
Searching...
No Matches
nlinearstatic.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
37#include "nummet.h"
38#include "timestep.h"
39#include "metastep.h"
40#include "error.h"
41#include "verbose.h"
43#include "nrsolver.h"
44#include "calmls.h"
45#include "outputmanager.h"
46#include "datastream.h"
47#include "classfactory.h"
48#include "timer.h"
49#include "contextioerr.h"
50#include "sparsemtrx.h"
51#include "errorestimator.h"
52#include "mathfem.h"
53#include "dofmanager.h"
54#include "dof.h"
56#include "function.h"
57
58#ifdef __MPI_PARALLEL_MODE
59 #include "problemcomm.h"
60 #include "communicator.h"
61 #include "loadbalancer.h"
62#endif
63
64namespace oofem {
66
67NonLinearStatic :: NonLinearStatic(int i, EngngModel *_master) : LinearStatic(i, _master),
70{
71 //
72 // constructor
73 //
74 prevStepLength = 0.;
83 refLoadInputMode = SparseNonLinearSystemNM :: rlm_total;
84 nMethod = NULL;
86 deltaT = 1.0;
87 dtFunction = 0;
89}
90
91
92NonLinearStatic :: ~NonLinearStatic()
93{
94 delete nMethod;
95}
96
97
98NumericalMethod *NonLinearStatic :: giveNumericalMethod(MetaStep *mStep)
99{
100 if ( mStep == NULL ) {
101 OOFEM_ERROR("undefined meta step");
102 }
103
104 int _val = 0;
106 IR_GIVE_OPTIONAL_FIELD( ( mStep->giveAttributesRecord() ), _val, "controllmode" );
108
109 if ( mode == nls_indirectControl ) {
110 if ( nMethod ) {
111 if ( dynamic_cast< CylindricalALM * >(nMethod) ) {
112 return nMethod;
113 } else {
114 delete nMethod;
115 }
116 }
117
118 this->nMethod = new CylindricalALM(this->giveDomain(1), this);
119 } else if ( mode == nls_directControl ) {
120 if ( nMethod ) {
121 if ( dynamic_cast< NRSolver * >(nMethod) ) {
122 return nMethod;
123 } else {
124 delete nMethod;
125 }
126 }
127
128 this->nMethod = new NRSolver(this->giveDomain(1), this);
129 } else {
130 OOFEM_ERROR("unsupported controlMode");
131 }
132
133 return this->nMethod;
134}
135
136
137void
138NonLinearStatic :: updateAttributes(MetaStep *mStep)
139{
140 MetaStep *mStep1 = this->giveMetaStep( mStep->giveNumber() ); //this line ensures correct input file in staggered problem
141 auto &ir = mStep1->giveAttributesRecord();
142
143 LinearStatic :: updateAttributes(mStep1);
144
145 /*
146 * if ((mstep->giveFirstStepNumber() == tStep->giveNumber()) && hasString(initString, "fixload")) {
147 * double factor;
148 *
149 * printf ("NonLinearStatic: fixed load level");
150 * if (initialLoadVector.isEmpty()) initialLoadVector.resize(loadVector.giveSize());
151 * if ((controlMode == nls_directControl) || (controlMode == nls_directControl2)) factor = 1.0;
152 * else factor = loadLevel;
153 * loadVector.times (factor);
154 * initialLoadVector.add(loadVector);
155 * loadVector.zero();
156 * this->loadInitFlag = 1;
157 * this->loadLevel = 0.0;
158 * }
159 */
160 int _val = nls_indirectControl;
162 IR_GIVE_OPTIONAL_FIELD(ir, _val, "controllmode");
164
165 _val = IG_None;
167 this->initialGuessType = ( InitialGuess ) _val;
168
169 deltaT = 1.0;
171 if ( deltaT < 0. ) {
172 OOFEM_ERROR("deltaT < 0");
173 }
174
175 dtFunction = 0;
177
181
182 _val = SparseNonLinearSystemNM :: rlm_total;
184 this->refLoadInputMode = ( SparseNonLinearSystemNM :: referenceLoadInputModeType ) _val;
185
187
188 // called just to mark field as recognized, used later
190}
191
192
193void
194NonLinearStatic :: initializeFrom(InputRecord &ir)
195{
196 LinearStatic :: initializeFrom(ir);
197
200
204 }
205
206#ifdef __MPI_PARALLEL_MODE
207 if ( isParallel() ) {
208 //commBuff = new CommunicatorBuff (this->giveNumberOfProcesses(), CBT_dynamic);
210 communicator = new NodeCommunicator( this, commBuff, this->giveRank(),
211 this->giveNumberOfProcesses() );
212
214 nonlocalExt = 1;
216 this->giveNumberOfProcesses() );
217 }
218 }
219#endif
220}
221
222
223double NonLinearStatic :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof)
224// returns unknown quantity like displacement, velocity of equation eq
225// This function translates this request to numerical method language
226{
227 if ( tStep != this->giveCurrentStep() ) {
228 OOFEM_ERROR("unknown time step encountered");
229 }
230
231 int eq = dof->__giveEquationNumber();
232 if (mode == VM_Residual) {
233 // evaluate the residual of momentum balance for specific unknown
234 // evaluate the residual of momentum balance for specific unknown
235
236 if (eq && internalForces.isNotEmpty()) {
237 double ans = loadLevel*incrementalLoadVector.at(eq)-internalForces.at(eq);
238 if (initialLoadVector.isNotEmpty()) {
239 ans += initialLoadVector.at(eq);
240 }
241 return ans;
242 } else {
243 return 0.;
244 }
245 } else if (mode == VM_Total) {
246#ifdef DEBUG
247 if ( eq == 0 ) OOFEM_ERROR("invalid equation number");
248#endif
249 if ( totalDisplacement.isNotEmpty() ) {
250 return totalDisplacement.at(eq);
251 } else {
252 return 0.;
253 }
254 } else if (mode == VM_Incremental) {
255#ifdef DEBUG
256 if ( eq == 0 ) OOFEM_ERROR("invalid equation number");
257#endif
258 // return incrementOfDisplacement -> at(eq);
259 // return nMethod-> giveUnknownComponent(IncrementOfSolution, eq);
260 if ( incrementOfDisplacement.isNotEmpty() ) {
261 return incrementOfDisplacement.at(eq);
262 } else {
263 return 0.;
264 }
265 } else if (mode == VM_Velocity) {
266#ifdef DEBUG
267 if ( eq == 0 ) OOFEM_ERROR("invalid equation number");
268#endif
269 if ( incrementOfDisplacement.isNotEmpty() ) {
270 return incrementOfDisplacement.at(eq) / tStep->giveTimeIncrement();
271 } else {
272 return 0.;
273 }
274 } else {
275 OOFEM_ERROR("Unknown is of undefined ValueModeType for this problem");
276 }
277}
278
279TimeStep *NonLinearStatic :: giveSolutionStepWhenIcApply(bool force)
280{
281 if ( master && ( !force ) ) {
282 return master->giveSolutionStepWhenIcApply();
283 } else {
284 if ( !stepWhenIcApply ) {
286 // int nFirst = giveNumberOfFirstStep();
287 stepWhenIcApply = std :: make_unique< TimeStep >(inin, this, 0, -deltaT, deltaT, 0);
288 }
289
290 return stepWhenIcApply.get();
291 }
292}
293
294
295TimeStep *NonLinearStatic :: giveNextStep()
296{
297 int istep = giveNumberOfFirstStep();
298 int mStepNum = 1;
299 double totalTime = 0.0;
300 StateCounterType counter = 1;
301 // double deltaTtmp = deltaT;
302 double deltaTtmp = this->giveDeltaT(istep);
303
304 if ( currentStep ) {
305 istep = currentStep->giveNumber() + 1;
306 deltaTtmp = this->giveDeltaT(istep);
307 totalTime = currentStep->giveTargetTime() + deltaTtmp;
308 counter = currentStep->giveSolutionStateCounter() + 1;
309 mStepNum = currentStep->giveMetaStepNumber();
310 /*
311 if ( !this->giveMetaStep(mStepNum)->isStepValid(istep) ) {
312 mStepNum++;
313 if ( mStepNum > nMetaSteps ) {
314 OOFEM_ERROR("no next step available, mStepNum=%d > nMetaSteps=%d", mStepNum, nMetaSteps);
315 }
316 }
317 */
318 } else {
319 // first step -> generate initial step
321 currentStep = std :: make_unique< TimeStep >(* newStep);
322 }
323
324 previousStep = std :: move(currentStep);
325 currentStep = std :: make_unique< TimeStep >(istep, this, mStepNum, totalTime, deltaTtmp, counter);
326 // dt variable are set eq to 0 for statics - has no meaning
327 // *Wrong* It has meaning for viscoelastic materials.
328
329 return currentStep.get();
330}
331
332Function *
333NonLinearStatic :: giveDtFunction()
334// Returns the load-time function of the receiver.
335{
336 if ( !dtFunction ) {
337 return NULL;
338 }
339
340 return giveDomain(1)->giveFunction(dtFunction);
341}
342
343
344double
345NonLinearStatic :: giveDeltaT(int n)
346{
347
348 //do not increase deltaT on microproblem
349 if ( pScale == microScale ) {
350 return 0.;
351 }
352
353 if ( giveDtFunction() ) {
354 return giveDtFunction()->evaluateAtTime(n);
355 }
356
357 return deltaT;
358}
359
360
361void NonLinearStatic :: solveYourself()
362{
363 if ( this->isParallel() ) {
364#ifdef __VERBOSE_PARALLEL
365 // force equation numbering before setting up comm maps
367 OOFEM_LOG_INFO("[process rank %d] neq is %d\n", this->giveRank(), neq);
368#endif
369
370 // set up communication patterns
371 this->initializeCommMaps();
372 // init remote dofman list
373 // this->initRemoteDofManList ();
374 }
375 StructuralEngngModel :: solveYourself();
376}
377
378
379void
380NonLinearStatic :: solveYourselfAt(TimeStep *tStep)
381{
382 proceedStep(1, tStep);
383}
384
385
386void
387NonLinearStatic :: terminate(TimeStep *tStep)
388{
389 this->doStepOutput(tStep);
390 this->updateLoadVectors(tStep);
391 this->saveStepContext(tStep, CM_State | CM_Definition);
392}
393
394
395void
396NonLinearStatic :: updateLoadVectors(TimeStep *tStep)
397{
398 MetaStep *mstep = this->giveMetaStep( tStep->giveMetaStepNumber() );
399 double msFinalTime = mstep->giveFinalTime() - this->giveInitialTime();
400 bool isLastMetaStep = (fabs(tStep->giveTargetTime() - msFinalTime) <= 1.e-6 * mstep->giveMinDeltaT());
402 //if ((tStep->giveNumber() == mstep->giveLastStepNumber()) &&ir.hasField("fixload")) {
403 if ( isLastMetaStep ) {
405 OOFEM_LOG_INFO("Fixed load level\n");
406
407 //update initialLoadVector
409
411
414
415 this->loadInitFlag = 1;
416 }
417
418 //if (!mstep->giveAttributesRecord()->hasField("keepll")) this->loadLevelInitFlag = 1;
419 }
420 } else { // direct control
421 //update initialLoadVector after each step of direct control
422 //(here the loading is not proportional)
423 OOFEM_LOG_DEBUG("Fixed load level\n");
424
426
428
431
432 this->loadInitFlag = 1;
433 }
434
435
436 // if (isLastMetaStep) {
437 if ( isLastMetaStep && !mstep->giveAttributesRecord().hasField(_IFT_NonLinearStatic_donotfixload) ) {
438#ifdef VERBOSE
439 OOFEM_LOG_INFO("Reseting load level\n");
440#endif
443 } else {
444 cumulatedLoadLevel = 0.0;
445 }
446
447 this->loadLevel = 0.0;
448 }
449}
450
451
452void
453NonLinearStatic :: proceedStep(int di, TimeStep *tStep)
454{
455 //
456 // creates system of governing eq's and solves them at given time step
457 //
458 // first assemble problem at current time step
459 //
460
461 if ( initFlag ) {
462 //
463 // first step create space for stiffness Matrix
464 //
465 if ( !stiffnessMatrix ) {
466 stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType);
467 }
468
469 if ( !stiffnessMatrix ) {
470 OOFEM_ERROR("sparse matrix creation failed");
471 }
472
473 if ( nonlocalStiffnessFlag ) {
474 if ( !stiffnessMatrix->isAsymmetric() ) {
475 OOFEM_ERROR("stiffnessMatrix does not support asymmetric storage");
476 }
477 }
478
479 stiffnessMatrix->buildInternalStructure( this, di, EModelDefaultEquationNumbering() );
480 }
481
482#if 0
483 if ( ( mstep->giveFirstStepNumber() == tStep->giveNumber() ) ) {
484 #ifdef VERBOSE
485 OOFEM_LOG_INFO("Resetting load level\n");
486 #endif
489 } else {
490 cumulatedLoadLevel = 0.0;
491 }
492 this->loadLevel = 0.0;
493 }
494#endif
495
497#ifdef VERBOSE
498 OOFEM_LOG_DEBUG("Assembling reference load\n");
499#endif
500 //
501 // assemble the incremental reference load vector
502 //
504 refLoadInputMode, this->giveDomain(di), tStep);
505
506 loadInitFlag = 0;
507 }
508
509 if ( tStep->giveNumber() == 1 ) {
511 totalDisplacement.resize(neq);
512 totalDisplacement.zero();
513 incrementOfDisplacement.resize(neq);
515 }
516
517 //
518 // -> BEGINNING OF LOAD (OR DISPLACEMENT) STEP <-
519 //
520
521 //
522 // set-up numerical model
523 //
524 this->giveNumericalMethod( this->giveMetaStep( tStep->giveMetaStepNumber() ) );
525 //
526 // call numerical model to solve arise problem
527 //
528#ifdef VERBOSE
529 OOFEM_LOG_RELEVANT( "\n\nSolving [step number %5d.%d, time = %e]\n\n", tStep->giveNumber(), tStep->giveVersion(), tStep->giveIntrinsicTime() );
530#endif
531
532 if ( this->initialGuessType == IG_Tangent ) {
533#ifdef VERBOSE
534 OOFEM_LOG_RELEVANT("Computing initial guess\n");
535#endif
536 FloatArray extrapolatedForces;
537 this->assemblePrescribedExtrapolatedForces( extrapolatedForces, tStep, TangentStiffnessMatrix, this->giveDomain(di) );
538 extrapolatedForces.negated();
539 this->updateMatrix( * stiffnessMatrix, tStep, this->giveDomain(di) );
540 SparseLinearSystemNM *linSolver = nMethod->giveLinearSolver();
541 OOFEM_LOG_RELEVANT("solving for increment\n");
542 linSolver->solve(* stiffnessMatrix, extrapolatedForces, incrementOfDisplacement);
543 OOFEM_LOG_RELEVANT("initial guess found\n");
545 } else if ( this->initialGuessType != IG_None ) {
546 OOFEM_ERROR("Initial guess type: %d not supported", initialGuessType);
547 } else {
549 }
550
551 //totalDisplacement.printYourself();
552 if ( initialLoadVector.isNotEmpty() ) {
556 } else {
560 }
561 OOFEM_LOG_RELEVANT("Equilibrium reached at load level = %f in %d iterations\n", cumulatedLoadLevel + loadLevel, currentIterations);
565}
566
567
568void
569NonLinearStatic :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d)
570{
571 // No-op: This can't really be supported in any nice way in nlinearstatic.
572}
573
574
575void
576NonLinearStatic :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d)
577{
579 mat.zero(); // zero stiffness matrix
580#ifdef VERBOSE
581 OOFEM_LOG_DEBUG("Assembling tangent stiffness matrix\n");
582#endif
583 this->assemble(mat, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), d);
585#ifdef VERBOSE
586 OOFEM_LOG_DEBUG("Assembling secant stiffness matrix\n");
587#endif
588 mat.zero(); // zero stiffness matrix
589 this->assemble(mat, tStep, TangentAssembler(SecantStiffness), EModelDefaultEquationNumbering(), d);
590 initFlag = 0;
591 } else if ( ( stiffMode == nls_elasticStiffness ) && ( initFlag ||
592 ( this->giveMetaStep( tStep->giveMetaStepNumber() )->giveFirstStepNumber() == tStep->giveNumber() ) || ( updateElasticStiffnessFlag ) ) ) {
593#ifdef VERBOSE
594 OOFEM_LOG_DEBUG("Assembling elastic stiffness matrix\n");
595#endif
596 mat.zero(); // zero stiffness matrix
597 this->assemble(mat, tStep, TangentAssembler(ElasticStiffness),
599 initFlag = 0;
600 } else {
601 // currently no action , this method is mainly intended to
602 // assemble new tangent stiffness after each iteration
603 // when secantStiffMode is on, we use the same stiffness
604 // during iteration process
605 }
606}
607
608
609void
610NonLinearStatic :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d)
611//
612// updates some component, which is used by numerical method
613// to newly reached state. used mainly by numerical method
614// when new tangent stiffness is needed during finding
615// of new equilibrium stage.
616//
617{
618 switch ( cmpn ) {
619 case NonLinearLhs:
621 stiffnessMatrix->zero(); // zero stiffness matrix
622#ifdef VERBOSE
623 OOFEM_LOG_DEBUG("Assembling tangent stiffness matrix\n");
624#endif
625 this->assemble(* stiffnessMatrix, tStep, TangentAssembler(TangentStiffness),
628#ifdef VERBOSE
629 OOFEM_LOG_DEBUG("Assembling secant stiffness matrix\n");
630#endif
631 stiffnessMatrix->zero(); // zero stiffness matrix
632 this->assemble(* stiffnessMatrix, tStep, TangentAssembler(SecantStiffness),
634 initFlag = 0;
635 } else if ( ( stiffMode == nls_elasticStiffness ) && ( initFlag ||
636 ( this->giveMetaStep( tStep->giveMetaStepNumber() )->giveFirstStepNumber() == tStep->giveNumber() ) || ( updateElasticStiffnessFlag ) ) ) {
637#ifdef VERBOSE
638 OOFEM_LOG_DEBUG("Assembling elastic stiffness matrix\n");
639#endif
640 stiffnessMatrix->zero(); // zero stiffness matrix
641 this->assemble(* stiffnessMatrix, tStep, TangentAssembler(ElasticStiffness),
643 initFlag = 0;
644 } else {
645 // currently no action , this method is mainly intended to
646 // assemble new tangent stiffness after each iteration
647 // when secantStiffMode is on, we use the same stiffness
648 // during iteration process
649 }
650
651 break;
652 case InternalRhs:
653#ifdef VERBOSE
654 OOFEM_LOG_DEBUG("Updating internal forces\n");
655#endif
656 // update internalForces and internalForcesEBENorm concurrently
658 break;
659
660 case ExternalRhs:
661#ifdef VERBOSE
662 OOFEM_LOG_DEBUG("Updating external forces\n");
663#endif
665 break;
666
667 default:
668 OOFEM_ERROR("Unknown Type of component.");
669 }
670}
671
672
673void
674NonLinearStatic :: printOutputAt(FILE *file, TimeStep *tStep)
675{
676 if ( !this->giveDomain(1)->giveOutputManager()->testTimeStepOutput(tStep) ) {
677 return; // do not print even Solution step header
678 }
679
680 fprintf( file, "\n\nOutput for time %.3e, solution step number %d\n", tStep->giveTargetTime(), tStep->giveNumber() );
681 fprintf(file, "Reached load level : %20.6f in %d iterations\n\n",
683
684 nMethod->printState(file);
685
686 this->giveDomain(1)->giveOutputManager()->doDofManOutput(file, tStep);
687 this->giveDomain(1)->giveOutputManager()->doElementOutput(file, tStep);
688 this->printReactionForces(tStep, 1, file);
689}
690
691
692void
693NonLinearStatic :: saveContext(DataStream &stream, ContextMode mode)
694{
696
697 EngngModel :: saveContext(stream, mode);
698
699 if ( ( iores = totalDisplacement.storeYourself(stream) ) != CIO_OK ) {
700 THROW_CIOERR(iores);
701 }
702
703 if ( ( iores = incrementOfDisplacement.storeYourself(stream) ) != CIO_OK ) {
704 THROW_CIOERR(iores);
705 }
706
707 int _cm = controlMode;
708 if ( !stream.write(_cm) ) {
710 }
711
712 if ( !stream.write(loadLevel) ) {
714 }
715
716 if ( !stream.write(cumulatedLoadLevel) ) {
718 }
719
720 if ( ( iores = initialLoadVector.storeYourself(stream) ) != CIO_OK ) {
721 THROW_CIOERR(iores);
722 }
723
724 if ( ( iores = initialLoadVectorOfPrescribed.storeYourself(stream) ) != CIO_OK ) {
725 THROW_CIOERR(iores);
726 }
727}
728
729
730void
731NonLinearStatic :: restoreContext(DataStream &stream, ContextMode mode)
732{
734
735 EngngModel :: restoreContext(stream, mode);
736
737 //if ((iores = this->giveNumericalMethod(giveCurrentStep())->restoreContext (stream)) !=CIO_OK) THROW_CIOERR(iores);
738
739 if ( ( iores = totalDisplacement.restoreYourself(stream) ) != CIO_OK ) {
740 THROW_CIOERR(iores);
741 }
742
743 if ( ( iores = incrementOfDisplacement.restoreYourself(stream) ) != CIO_OK ) {
744 THROW_CIOERR(iores);
745 }
746
747 int _cm;
748 if ( !stream.read(_cm) ) {
750 }
751
753 if ( !stream.read(loadLevel) ) {
755 }
756
757 if ( !stream.read(cumulatedLoadLevel) ) {
759 }
760
761
762 // store InitialLoadVector
763 if ( ( iores = initialLoadVector.restoreYourself(stream) ) != CIO_OK ) {
764 THROW_CIOERR(iores);
765 }
766
767 if ( ( iores = initialLoadVectorOfPrescribed.restoreYourself(stream) ) != CIO_OK ) {
768 THROW_CIOERR(iores);
769 }
770}
771
772
773void
774NonLinearStatic :: updateDomainLinks()
775{
776 LinearStatic :: updateDomainLinks();
777
778 this->giveNumericalMethod( this->giveCurrentMetaStep() )->setDomain( this->giveDomain(1) );
779#ifdef __MPI_PARALLEL_MODE
780 if ( this->giveLoadBalancer() ) {
781 this->giveLoadBalancer()->setDomain( this->giveDomain(1) );
782 }
783
784#endif
785}
786
787
788void
789NonLinearStatic :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma,
790 const UnknownNumberingScheme &s, Domain *domain)
791{
792#ifdef TIME_REPORT
793 Timer _timer;
794 _timer.startTimer();
795#endif
796
797 LinearStatic :: assemble(answer, tStep, ma, s, domain);
798
799 if ( ( nonlocalStiffnessFlag ) && dynamic_cast< const TangentAssembler * >(& ma) ) {
800 // add nonlocal contribution
801 for ( auto &elem : domain->giveElements() ) {
802 static_cast< StructuralElement * >( elem.get() )->addNonlocalStiffnessContributions(answer, s, tStep);
803 }
804
805 // print storage statistics
806 answer.printStatistics();
807 }
808
809#ifdef TIME_REPORT
810 _timer.stopTimer();
811 OOFEM_LOG_DEBUG( "NonLinearStatic: User time consumed by assembly: %.2fs\n", _timer.getUtime() );
812#endif
813}
814
815
816#ifdef __OOFEG
817void
818NonLinearStatic :: showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep)
819{
820 Domain *domain = this->giveDomain(1);
821 CharType ctype;
822
823 if ( type != 1 ) {
824 return;
825 }
826
828 ctype = TangentStiffnessMatrix;
829 } else if ( stiffMode == nls_secantStiffness ) {
830 ctype = SecantStiffnessMatrix;
831 } else {
832 ctype = SecantStiffnessMatrix;
833 }
834
835 for ( auto &elem : domain->giveElements() ) {
836 elem->showSparseMtrxStructure(ctype, gc, tStep);
837 }
838
839 for ( auto &elem : domain->giveElements() ) {
840 elem->showExtendedSparseMtrxStructure(ctype, gc, tStep);
841 }
842}
843#endif
844
845
846void
847NonLinearStatic :: computeExternalLoadReactionContribution(FloatArray &reactions, TimeStep *tStep, int di)
848{
849 if ( ( di == 1 ) && ( tStep == this->giveCurrentStep() ) ) {
852 } else {
853 OOFEM_ERROR("unable to respond due to invalid solution step or domain");
854 }
855}
856
857
858void
859NonLinearStatic :: assembleIncrementalReferenceLoadVectors(FloatArray &_incrementalLoadVector,
860 FloatArray &_incrementalLoadVectorOfPrescribed,
861 SparseNonLinearSystemNM :: referenceLoadInputModeType _refMode,
862 Domain *sourceDomain, TimeStep *tStep)
863{
864 _incrementalLoadVector.resize( sourceDomain->giveEngngModel()->giveNumberOfDomainEquations( sourceDomain->giveNumber(), EModelDefaultEquationNumbering() ) );
865 _incrementalLoadVector.zero();
866 _incrementalLoadVectorOfPrescribed.resize( sourceDomain->giveEngngModel()->giveNumberOfDomainEquations( sourceDomain->giveNumber(), EModelDefaultPrescribedEquationNumbering() ) );
867 _incrementalLoadVectorOfPrescribed.zero();
868
869 if ( _refMode == SparseNonLinearSystemNM :: rlm_incremental ) {
871 this->assembleVector(_incrementalLoadVector, tStep, ExternalForceAssembler(),
872 VM_Incremental, EModelDefaultEquationNumbering(), sourceDomain);
873
874 this->assembleVector(_incrementalLoadVectorOfPrescribed, tStep, ExternalForceAssembler(),
875 VM_Incremental, EModelDefaultPrescribedEquationNumbering(), sourceDomain);
876 } else {
877 this->assembleVector(_incrementalLoadVector, tStep, ExternalForceAssembler(),
878 VM_Total, EModelDefaultEquationNumbering(), sourceDomain);
879
880 this->assembleVector(_incrementalLoadVectorOfPrescribed, tStep, ExternalForceAssembler(),
881 VM_Total, EModelDefaultPrescribedEquationNumbering(), sourceDomain);
882 }
883
885}
886
887
888int
889NonLinearStatic :: estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType)
890{
891 int count = 0, pcount = 0;
892 Domain *domain = this->giveDomain(1);
893
894 if ( packUnpackType == 0 ) {
895 for ( int map : commMap ) {
896 DofManager *dman = domain->giveDofManager(map);
897 for ( Dof *dof : *dman ) {
898 if ( dof->isPrimaryDof() && ( dof->__giveEquationNumber() ) ) {
899 count++;
900 } else {
901 pcount++;
902 }
903 }
904 }
905
906 //printf ("\nestimated count is %d\n",count);
907 return ( buff.givePackSizeOfDouble(1) * max(count, pcount) );
908 } else if ( packUnpackType == 1 ) {
909 for ( int map : commMap ) {
910 count += domain->giveElement(map)->estimatePackSize(buff);
911 }
912
913 return count;
914 }
915
916 return 0;
917}
918
919
920#ifdef __MPI_PARALLEL_MODE
922NonLinearStatic :: giveLoadBalancer()
923{
924 if ( lb ) {
925 return lb.get();
926 }
927
928 if ( loadBalancingFlag ) {
930 lb = classFactory.createLoadBalancer( "parmetis", this->giveDomain(1) );
931 return lb.get();
932 } else {
933 return nullptr;
934 }
935}
936
937
939NonLinearStatic :: giveLoadBalancerMonitor()
940{
941 if ( lbm ) {
942 return lbm.get();
943 }
944
945 if ( loadBalancingFlag ) {
946 lbm = classFactory.createLoadBalancerMonitor("wallclock", this);
947 return lbm.get();
948 } else {
949 return nullptr;
950 }
951}
952#endif
953
954void
955NonLinearStatic :: packMigratingData(TimeStep *tStep)
956{
957 Domain *domain = this->giveDomain(1);
958 int ndofman = domain->giveNumberOfDofManagers();
959 bool initialLoadVectorEmpty = initialLoadVector.isEmpty();
960 bool initialLoadVectorOfPrescribedEmpty = initialLoadVectorOfPrescribed.isEmpty();
961
962 for ( int idofman = 1; idofman <= ndofman; idofman++ ) {
963 DofManager *_dm = domain->giveDofManager(idofman);
964 for ( Dof *_dof : *_dm ) {
965 if ( _dof->isPrimaryDof() ) {
966 int _eq;
967 if ( ( _eq = _dof->__giveEquationNumber() ) ) {
968 // pack values in solution vectors
969 _dof->updateUnknownsDictionary( tStep, VM_Total, totalDisplacement.at(_eq) );
970 if ( initialLoadVectorEmpty ) {
971 _dof->updateUnknownsDictionary(tStep, VM_RhsInitial, 0.0);
972 } else {
973 _dof->updateUnknownsDictionary( tStep, VM_RhsInitial, initialLoadVector.at(_eq) );
974 }
975
976 _dof->updateUnknownsDictionary( tStep, VM_RhsIncremental, incrementalLoadVector.at(_eq) );
977 } else if ( ( _eq = _dof->__givePrescribedEquationNumber() ) ) {
978 // pack values in prescribed solution vectors
979 if ( initialLoadVectorOfPrescribedEmpty ) {
980 _dof->updateUnknownsDictionary(tStep, VM_RhsInitial, 0.0);
981 } else {
982 _dof->updateUnknownsDictionary( tStep, VM_RhsInitial, initialLoadVectorOfPrescribed.at(_eq) );
983 }
984
985 _dof->updateUnknownsDictionary( tStep, VM_RhsIncremental, incrementalLoadVectorOfPrescribed.at(_eq) );
986 }
987 } // end primary dof
988 } // end dof loop
989 } // end dofman loop
990}
991
992
993void
994NonLinearStatic :: unpackMigratingData(TimeStep *tStep)
995{
996 Domain *domain = this->giveDomain(1);
997 int ndofman = domain->giveNumberOfDofManagers();
998 //int myrank = this->giveRank();
999
1000 // resize target arrays
1002 totalDisplacement.resize(neq);
1003 incrementOfDisplacement.resize(neq);
1004 incrementalLoadVector.resize(neq);
1005 initialLoadVector.resize(neq);
1008
1009 for ( int idofman = 1; idofman <= ndofman; idofman++ ) {
1010 DofManager *_dm = domain->giveDofManager(idofman);
1011 for ( Dof *_dof : *_dm ) {
1012 if ( _dof->isPrimaryDof() ) {
1013 int _eq;
1014 if ( ( _eq = _dof->__giveEquationNumber() ) ) {
1015 // pack values in solution vectors
1016 totalDisplacement.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_Total);
1017 initialLoadVector.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_RhsInitial);
1018 incrementalLoadVector.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_RhsIncremental);
1019
1020#if 0
1021 // debug print
1022 if ( _dm->giveParallelMode() == DofManager_shared ) {
1023 fprintf(stderr, "[%d] Shared: %d(%d) -> %d\n", myrank, idofman, idof, _eq);
1024 } else {
1025 fprintf(stderr, "[%d] Local : %d(%d) -> %d\n", myrank, idofman, idof, _eq);
1026 }
1027
1028#endif
1029 } else if ( ( _eq = _dof->__givePrescribedEquationNumber() ) ) {
1030 // pack values in prescribed solution vectors
1031 initialLoadVectorOfPrescribed.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_RhsInitial);
1032 incrementalLoadVectorOfPrescribed.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_RhsIncremental);
1033
1034#if 0
1035 // debug print
1036 fprintf(stderr, "[%d] %d(%d) -> %d\n", myrank, idofman, idof, -_eq);
1037#endif
1038 }
1039 } // end primary dof
1040 } // end dof loop
1041 } // end dofman loop
1042
1043 this->initializeCommMaps(true);
1044 nMethod->reinitialize();
1045 // reinitialize error estimator (if any)
1046 if ( this->giveDomainErrorEstimator(1) ) {
1047 this->giveDomainErrorEstimator(1)->reinitialize();
1048 }
1049
1050 initFlag = true;
1051}
1052} // 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.
dofManagerParallelMode giveParallelMode() const
Definition dofmanager.h:526
virtual int __giveEquationNumber() const =0
int giveNumber()
Returns domain number.
Definition domain.h:281
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition domain.h:461
DofManager * giveDofManager(int n)
Definition domain.C:317
Element * giveElement(int n)
Definition domain.C:165
EngngModel * giveEngngModel()
Definition domain.C:419
std ::vector< std ::unique_ptr< Element > > & giveElements()
Definition domain.h:294
int estimatePackSize(DataStream &buff)
Definition element.C:1748
int giveNumberOfTimeStepWhenIcApply()
Returns the time step number, when initial conditions should apply.
Definition engngm.h:787
void initializeCommMaps(bool forceInit=false)
Definition engngm.C:2147
std::unique_ptr< LoadBalancer > lb
Load Balancer.
Definition engngm.h:304
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
@ IG_None
No special treatment for new iterations. Probably means ending up using for all free dofs.
Definition engngm.h:208
@ IG_Tangent
Solves an approximated tangent problem from the last iteration. Useful for changing Dirichlet boundar...
Definition engngm.h:209
std ::unique_ptr< TimeStep > previousStep
Previous time step.
Definition engngm.h:243
MetaStep * giveCurrentMetaStep()
Returns current meta step.
Definition engngm.C:1900
ProblemCommunicator * nonlocCommunicator
NonLocal Communicator. Necessary when nonlocal constitutive models are used.
Definition engngm.h:318
Domain * giveDomain(int n)
Definition engngm.C:1936
virtual void doStepOutput(TimeStep *tStep)
Definition engngm.C:756
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
bool loadBalancingFlag
If set to true, load balancing is active.
Definition engngm.h:307
virtual ErrorEstimator * giveDomainErrorEstimator(int n)
Definition engngm.h:372
MetaStep * giveMetaStep(int i)
Returns the i-th meta step.
Definition engngm.h:773
CommunicatorBuff * commBuff
Common Communicator buffer.
Definition engngm.h:313
void assemblePrescribedExtrapolatedForces(FloatArray &answer, TimeStep *tStep, CharType type, Domain *domain)
Definition engngm.C:1614
void saveStepContext(TimeStep *tStep, ContextMode mode)
Definition engngm.C:768
EngngModel * master
Master e-model; if defined receiver is in maintained (slave) mode.
Definition engngm.h:274
std::unique_ptr< LoadBalancerMonitor > lbm
Definition engngm.h:305
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
std ::unique_ptr< TimeStep > stepWhenIcApply
Solution step when IC (initial conditions) apply.
Definition engngm.h:239
void assembleVector(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1106
problemScale pScale
Multiscale mode.
Definition engngm.h:269
void resize(Index s)
Definition floatarray.C:94
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void add(const FloatArray &src)
Definition floatarray.C:218
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
SparseMtrxType sparseMtrxType
LinearStatic(int i, EngngModel *master=nullptr)
std ::unique_ptr< SparseMtrx > stiffnessMatrix
int giveNumber()
Returns receiver's number.
Definition metastep.h:116
double giveFinalTime()
Returns final time of the meta step.
Definition metastep.h:144
double giveMinDeltaT()
Return the minimal time step length set be the user.
Definition metastep.h:168
InputRecord & giveAttributesRecord()
Returns e-model attributes.
Definition metastep.h:122
SparseNonLinearSystemNM::referenceLoadInputModeType refLoadInputMode
FloatArray initialLoadVectorOfPrescribed
A load vector which does not scale for prescribed DOFs.
FloatArray incrementalLoadVector
FloatArray incrementalLoadVectorOfPrescribed
Incremental Load Vector for prescribed DOFs.
int dtFunction
Associated time function for time step increment.
double deltaT
Intrinsic time increment.
double giveInitialTime() override
return time at the begining of analysis
TimeStep * giveSolutionStepWhenIcApply(bool force=false) override
void proceedStep(int di, TimeStep *tStep)
LoadBalancer * giveLoadBalancer() override
void assembleIncrementalReferenceLoadVectors(FloatArray &_incrementalLoadVector, FloatArray &_incrementalLoadVectorOfPrescribed, SparseNonLinearSystemNM ::referenceLoadInputModeType _refMode, Domain *sourceDomain, TimeStep *tStep)
NonLinearStatic_controlType controlMode
Characterizes the type of control used.
NumericalMethod * giveNumericalMethod(MetaStep *mStep) override
Returns reference to receiver's numerical method.
virtual void updateLoadVectors(TimeStep *tStep)
InitialGuess initialGuessType
The initial guess type to use before starting the nonlinear solver.
NonLinearStatic_stiffnessMode stiffMode
void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) override
ConvergedReason numMetStatus
Function * giveDtFunction()
FloatArray incrementOfDisplacement
SparseNonLinearSystemNM * nMethod
Numerical method used to solve the problem.
FloatArray initialLoadVector
A load vector already applied, which does not scales.
virtual ConvergedReason solve(SparseMtrx &A, FloatArray &b, FloatArray &x)=0
virtual void zero()=0
Zeroes the receiver.
virtual void printStatistics() const
Prints the receiver statistics (one-line) to stdout.
Definition sparsemtrx.h:273
virtual void addNonlocalStiffnessContributions(SparseMtrx &dest, const UnknownNumberingScheme &s, TimeStep *tStep)
StateCounterType internalVarUpdateStamp
FloatArray internalForcesEBENorm
Norm of nodal internal forces evaluated on element by element basis (squared).
void printReactionForces(TimeStep *tStep, int id, FILE *out)
void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override
int giveVersion()
Returns receiver's version.
Definition timestep.h:148
int giveMetaStepNumber()
Returns receiver's meta step number.
Definition timestep.h:150
ConvergedReason convergedReason
Status of solution step (Converged,.
Definition timestep.h:120
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
double giveTargetTime()
Returns target time.
Definition timestep.h:164
int numberOfIterations
Number of itarations needed to achieve convergence.
Definition timestep.h:116
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
double giveIntrinsicTime()
Returns intrinsic time, e.g. time in which constitutive model is evaluated.
Definition timestep.h:166
double getUtime()
Returns total user time elapsed in seconds.
Definition timer.C:105
void startTimer()
Definition timer.C:69
void stopTimer()
Definition timer.C:77
#define THROW_CIOERR(e)
#define CM_State
Definition contextmode.h:46
#define CM_Definition
Definition contextmode.h:47
#define _IFT_EngngModel_initialGuess
Definition engngm.h:88
#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_RELEVANT(...)
Definition logger.h:142
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
long ContextMode
Definition contextmode.h:43
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.
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
@ DofManager_shared
Definition dofmanager.h:68
@ CBT_static
NonLinearStatic_stiffnessMode
Type determining the stiffness mode.
@ nls_secantInitialStiffness
The secant stiffness is used and updated only at the beginning of new load step.
@ nls_secantStiffness
The secant stiffness is used and updated whenever requested.
@ nls_tangentStiffness
The tangent stiffness is used and updated whenever requested.
@ nls_elasticStiffness
The initial elastic stiffness is used in the whole solution.
ClassFactory & classFactory
NonLinearStatic_controlType
Type determining type of loading control. This type determines the solver to be used.
@ nls_indirectControl
A generalized norm of displacement and loading vectors is controlled. In current implementation,...
@ nls_directControl
Describes the direct control where load or displacement (or both) are controlled.
@ CIO_IOERR
General IO error.
@ ExternalRhs
@ NonLinearLhs
@ InternalRhs
@ microScale
Definition problemmode.h:47
#define _IFT_NonLinearStatic_updateElasticStiffnessFlag
#define _IFT_NonLinearStatic_deltatfunction
#define _IFT_NonLinearStatic_refloadmode
#define _IFT_NonLinearStatic_stiffmode
#define _IFT_NonLinearStatic_controlmode
#define _IFT_NonLinearStatic_donotfixload
#define _IFT_NonLinearStatic_keepll
#define _IFT_NonLinearStatic_nonlocstiff
#define _IFT_NonLinearStatic_deltat
#define _IFT_NonLinearStatic_nonlocalext
oofem::oofegGraphicContext gc[OOFEG_LAST_LAYER]

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