OOFEM 3.0
Loading...
Searching...
No Matches
nrsolver.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 "nrsolver.h"
36#include "verbose.h"
37#include "timestep.h"
38#include "mathfem.h"
39// includes for ddc - not very clean (NumMethod knows what is "node" and "dof")
40#include "node.h"
41#include "element.h"
43#include "dof.h"
44#include "function.h"
45#include "linesearch.h"
46#include "classfactory.h"
47#include "exportmodulemanager.h"
48#include "engngm.h"
49#include "parallelcontext.h"
52
53#ifdef __PETSC_MODULE
54 #include "petscsolver.h"
55 #include "petscsparsemtrx.h"
56#endif
57
58#include <cstdio>
59
60namespace oofem {
61#define nrsolver_ERROR_NORM_SMALL_NUM 1.e-6
62#define NRSOLVER_MAX_REL_ERROR_BOUND 1.e20
63#define NRSOLVER_MAX_RESTARTS 4
64#define NRSOLVER_RESET_STEP_REDUCE 0.25
65#define NRSOLVER_DEFAULT_NRM_TICKS 10
66
68
69NRSolver :: NRSolver(Domain *d, EngngModel *m) :
70 SparseNonLinearSystemNM(d, m), prescribedDofs(), prescribedDofsValues()
71{
72 //
73 // constructor
74 //
75 nsmax = 60; // default maximum number of sweeps allowed
76 deltaL = 1.0;
77 NR_Mode = NR_OldMode = nrsolverModifiedNRM;
78 NR_ModeTick = -1; // do not switch to calm_NR_OldMode
79 MANRMSteps = 0;
80 numberOfPrescribedDofs = 0;
81 prescribedDofsFlag = false;
82 prescribedEqsInitFlag = false;
83 prescribedDisplacementTF = 0;
84 lsFlag = 0; // no line-search
85
86 constrainedNRFlag = false;
87 this->forceErrVecOld.resize(0);
88 this->forceErrVec.resize(0);
89 constrainedNRalpha = 0.5; // default
90
91 smConstraintVersion = 0;
92 mCalcStiffBeforeRes = true;
93
94 maxIncAllowed = 1.0e20;
95}
96
97
98NRSolver :: ~NRSolver()
99{}
100
101
102void
103NRSolver :: initializeFrom(InputRecord &ir)
104{
105 SparseNonLinearSystemNM :: initializeFrom(ir);
106
107 // Choosing a big "enough" number. (Alternative: Force input of maxinter)
108 nsmax = ( int ) 1e8;
110 if ( nsmax < 0 ) {
111 OOFEM_ERROR("nsmax < 0");
112 }
113
114 minIterations = 0;
116
117 minStepLength = 0.0;
119
120 // read if MANRM method is used
121 MANRMSteps = 0;
123 if ( MANRMSteps > 0 ) {
125 } else {
127 }
128
129 int _val = 0;
131 solverType = ( LinSystSolverType ) _val;
132 this->giveLinearSolver()->initializeFrom(ir); // make sure that linear solver is initialized from it as well
133
134 // read relative error tolerances of the solver
135 // if rtolv provided set to this tolerance both rtolf and rtold
136 rtolf.resize(1);
137 rtolf.at(1) = 1.e-3; // Default value.
138 rtold.resize(1);
139 rtold = Vec1(
140 0.0
141 ); // Default off (0.0 or negative values mean that residual is ignored)
144
145 // read optional force and displacement tolerances
148
149 prescribedDofs.clear();
151 prescribedDofsValues.clear();
155
156 numberOfPrescribedDofs = prescribedDofs.giveSize() / 2;
157 if ( numberOfPrescribedDofs != prescribedDofsValues.giveSize() ) {
158 OOFEM_ERROR("direct displacement mask size mismatch");
159 }
160
162 prescribedDofsFlag = true;
163 } else {
164 prescribedDofsFlag = false;
165 }
166
167 this->lsFlag = 0;
169
170 if ( this->lsFlag ) {
171 this->giveLineSearchSolver()->initializeFrom(ir);
172 }
173
174 int calcStiffBeforeResFlag = 1;
175 IR_GIVE_OPTIONAL_FIELD(ir, calcStiffBeforeResFlag, _IFT_NRSolver_calcstiffbeforeres);
176 if ( calcStiffBeforeResFlag == 0 ) {
177 mCalcStiffBeforeRes = false;
178 }
179
181
182
183 this->constrainedNRminiter = 0;
185 this->constrainedNRFlag = this->constrainedNRminiter != 0;
186
187
189
190 dg_forceScale.clear();
192 IntArray dofs;
193 FloatArray forces;
196 for ( int i = 0; i < dofs.giveSize(); ++i ) {
197 dg_forceScale [ dofs [ i ] ] = forces [ i ];
198 }
199 }
200
201}
202
203
205NRSolver :: solve(SparseMtrx &k, FloatArray &R, FloatArray *R0,
206 FloatArray &X, FloatArray &dX, FloatArray &F,
207 const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm,
208 int &nite, TimeStep *tStep)
209//
210// this function solve the problem of the unbalanced equilibrium
211// using NR scheme
212//
213//
214{
215 // residual, iteration increment of solution, total external force
216 FloatArray rhs, ddX, RT;
217 double RRT;
218 int neq = X.giveSize();
219 bool converged, errorOutOfRangeFlag;
220 ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
221
222 if ( engngModel->giveProblemScale() == macroScale ) {
223 OOFEM_LOG_INFO("NRSolver: Iteration");
224 if ( rtolf.at(1) > 0.0 ) {
225 OOFEM_LOG_INFO(" ForceError");
226 }
227 if ( rtold.at(1) > 0.0 ) {
228 OOFEM_LOG_INFO(" DisplError");
229 }
230 OOFEM_LOG_INFO("\n----------------------------------------------------------------------------\n");
231 }
232
233 l = 1.0;
234
236 this->giveLinearSolver();
237
238 // compute total load R = R+R0
239 RT = R;
240 if ( R0 ) {
241 RT.add(* R0);
242 }
243
244 RRT = parallel_context->localNorm(RT);
245 RRT *= RRT;
246
247 ddX.resize(neq);
248 ddX.zero();
249
250 // Fetch the matrix before evaluating internal forces.
251 // This is intentional, since its a simple way to drastically increase convergence for nonlinear problems.
252 // (This old tangent is just used)
253 // This improves convergence for many nonlinear problems, but not all. It may actually
254 // cause divergence for some nonlinear problems. Therefore a flag is used to determine if
255 // the stiffness should be evaluated before the residual (default yes). /ES
256
257 engngModel->updateComponent(tStep, NonLinearLhs, domain);
258 if ( this->prescribedDofsFlag ) {
259 if ( !prescribedEqsInitFlag ) {
260 this->initPrescribedEqs();
261 }
263 }
264
265 nite = 0;
266 for ( nite = 0; ; ++nite ) {
267 // Compute the residual
268 engngModel->initForNewIteration(domain, tStep, nite, X);
269 engngModel->updateComponent(tStep, InternalRhs, domain);
270 rhs.beDifferenceOf(RT, F);
271
272 if ( this->prescribedDofsFlag ) {
273 this->applyConstraintsToLoadIncrement(nite, k, rhs, rlm, tStep);
274 }
275
276 // convergence check
277 converged = this->checkConvergence(RT, F, rhs, ddX, X, RRT, internalForcesEBENorm, nite, errorOutOfRangeFlag);
278
279 if ( errorOutOfRangeFlag ) {
280 status = CR_DIVERGED_TOL;
281 throw ConvergenceException( "Divergence reached after iterations" );
282 break;
283 } else if ( converged && ( nite >= minIterations ) ) {
284 status = CR_CONVERGED;
285 break;
286 } else if ( nite >= nsmax ) {
287 status = CR_DIVERGED_ITS;
288 throw ConvergenceException( "Maximum number of iterations reached without convergence" );
289
290 break;
291 }
292
293 if ( nite > 0 || !mCalcStiffBeforeRes ) {
294 if ( ( NR_Mode == nrsolverFullNRM ) || ( ( NR_Mode == nrsolverAccelNRM ) && ( nite % MANRMSteps == 0 ) ) ) {
295 engngModel->updateComponent(tStep, NonLinearLhs, domain);
297 }
298 }
299
300 if ( ( nite == 0 ) && ( deltaL < 1.0 ) ) { // deltaL < 1 means no increment applied, only equilibrate current state
301 rhs.zero();
302 R.zero();
303 ddX = rhs;
304 } else {
305 // if ( engngModel->giveProblemScale() == macroScale ) {
306 // k.writeToFile("k.txt");
307 // }
308
309 linSolver->solve(k, rhs, ddX);
310 }
311
312 //
313 // update solution
314 //
315 if ( this->lsFlag && ( nite > 0 ) ) { // Why not nite == 0 ?
316 // line search
317 LineSearchNM :: LS_status LSstatus;
318 double eta;
319 this->giveLineSearchSolver()->solve(X, ddX, F, R, R0, prescribedEqs, 1.0, eta, LSstatus, tStep);
320 } else if ( this->constrainedNRFlag && ( nite > this->constrainedNRminiter ) ) {
322 if ( this->forceErrVec.computeSquaredNorm() > this->forceErrVecOld.computeSquaredNorm() ) {
323 OOFEM_LOG_INFO("Constraining increment to be %e times full increment...\n", this->constrainedNRalpha);
324 ddX.times(this->constrainedNRalpha);
325 }
326 //this->giveConstrainedNRSolver()->solve(X, & ddX, this->forceErrVec, this->forceErrVecOld, status, tStep);
327 }
328
329
331
332 double maxInc = 0.0;
333 for ( double inc : ddX ) {
334 if ( fabs(inc) > maxInc ) {
335 maxInc = fabs(inc);
336 }
337 }
338
339 if ( maxInc > maxIncAllowed ) {
340 if ( engngModel->giveProblemScale() == macroScale ) {
341 printf("Restricting increment. maxInc: %e\n", maxInc);
342 }
343 ddX.times(maxIncAllowed / maxInc);
344 }
345
347
348
349 X.add(ddX);
350 dX.add(ddX);
351
353 engngModel->updateComponent(tStep, ExternalRhs, domain);
354 RT = R;
355 if ( R0 ) {
356 RT.add(* R0);
357 }
358 }
359
360
361
362 tStep->incrementStateCounter(); // update solution state counter
363 tStep->incrementSubStepNumber();
364
365 engngModel->giveExportModuleManager()->doOutput(tStep, true);
366 }
367
368 // Modify Load vector to include "quasi reaction"
369 if ( R0 ) {
370 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
371 R.at( prescribedEqs.at(i) ) = F.at( prescribedEqs.at(i) ) - R0->at( prescribedEqs.at(i) ) - R.at( prescribedEqs.at(i) );
372 }
373 } else {
374 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
375 R.at( prescribedEqs.at(i) ) = F.at( prescribedEqs.at(i) ) - R.at( prescribedEqs.at(i) );
376 }
377 }
378
380
381#ifdef VERBOSE
383 // print quasi reactions if direct displacement control used
384 OOFEM_LOG_INFO("\n");
385 OOFEM_LOG_INFO("NRSolver: Quasi reaction table \n");
386 OOFEM_LOG_INFO("NRSolver: Node Dof Displacement Force\n");
387 double reaction;
388 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
389 reaction = R.at( prescribedEqs.at(i) );
390 if ( R0 ) {
391 reaction += R0->at( prescribedEqs.at(i) );
392 }
393 lastReactions.at(i) = reaction;
394 OOFEM_LOG_INFO("NRSolver: %-15d %-15d %-+15.5e %-+15.5e\n", prescribedDofs.at(2 * i - 1), prescribedDofs.at(2 * i),
395 X.at( prescribedEqs.at(i) ), reaction);
396 }
397 OOFEM_LOG_INFO("\n");
398 }
399#endif
400
401 return status;
402}
403
404
406NRSolver :: giveLinearSolver()
407{
408 if ( linSolver ) {
409 if ( linSolver->giveLinSystSolverType() == solverType ) {
410 return linSolver.get();
411 }
412 }
413
414 linSolver = classFactory.createSparseLinSolver(solverType, domain, engngModel);
415 if ( !linSolver ) {
416 OOFEM_ERROR("linear solver creation failed for lstype %d", solverType);
417 }
418
419 return linSolver.get();
420}
421
422
424NRSolver :: giveLineSearchSolver()
425{
426 if ( !linesearchSolver ) {
427 linesearchSolver = std :: make_unique< LineSearchNM >(domain, engngModel);
428 }
429
430 return linesearchSolver.get();
431}
432
433void
434NRSolver :: initPrescribedEqs()
435{
437 ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
438 int count = 0, ndofman = domain->giveNumberOfDofManagers();
439 IntArray localPrescribedEqs(numberOfPrescribedDofs);
440
441 for ( int j = 1; j <= ndofman; j++ ) {
442 if ( !parallel_context->isLocal( domain->giveNode(j) ) ) {
443 continue;
444 }
445 int jglobnum = domain->giveNode(j)->giveGlobalNumber();
446 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
447 int inode = prescribedDofs.at(2 * i - 1);
448 int idofid = prescribedDofs.at(2 * i);
449 if ( inode == jglobnum ) {
450 localPrescribedEqs.at(++count) = domain->giveNode(j)->giveDofWithID(idofid)->giveEquationNumber(dn);
451 continue;
452 }
453 }
454 }
455
456 prescribedEqs.resize(count);
457 for ( int i = 1; i <= count; i++ ) {
458 prescribedEqs.at(i) = localPrescribedEqs.at(i);
459 }
460
462
463 this->prescribedEqsInitFlag = true;
464}
465
466
467void
468NRSolver :: applyConstraintsToStiffness(SparseMtrx &k)
469{
470 if ( this->smConstraintVersion == k.giveVersion() ) {
471 return;
472 }
473
474#ifdef __PETSC_MODULE
475 PetscSparseMtrx *lhs = dynamic_cast< PetscSparseMtrx * >(& k);
476 if ( lhs ) {
477 Vec diag;
478 PetscScalar *ptr;
479 int eq;
480
481 lhs->createVecGlobal(& diag);
482 MatGetDiagonal(* lhs->giveMtrx(), diag);
483 VecGetArray(diag, & ptr);
484 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
485 eq = prescribedEqs.at(i) - 1;
486 MatSetValue(* ( lhs->giveMtrx() ), eq, eq, ptr [ eq ] * 1.e6, INSERT_VALUES);
487 }
488
489 MatAssemblyBegin(* lhs->giveMtrx(), MAT_FINAL_ASSEMBLY);
490 MatAssemblyEnd(* lhs->giveMtrx(), MAT_FINAL_ASSEMBLY);
491 VecRestoreArray(diag, & ptr);
492 VecDestroy(& diag);
495 }
496
497 return;
498 }
499
500#endif // __PETSC_MODULE
501 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
502 k.at( prescribedEqs.at(i), prescribedEqs.at(i) ) *= 1.e6;
503 }
504
507 }
508}
509
510
511void
512NRSolver :: applyConstraintsToLoadIncrement(int nite, const SparseMtrx &k, FloatArray &R,
514{
515 double factor = engngModel->giveDomain(1)->giveFunction(prescribedDisplacementTF)->evaluateAtTime( tStep->giveTargetTime() );
516 if ( ( rlm == rlm_total ) && ( !tStep->isTheFirstStep() ) ) {
517 //factor -= engngModel->giveDomain(1)->giveFunction(prescribedDisplacementTF)->
518 // at(tStep->givePreviousStep()->giveTime()) ;
519 factor -= engngModel->giveDomain(1)->giveFunction(prescribedDisplacementTF)->
520 evaluateAtTime( tStep->giveTargetTime() - tStep->giveTimeIncrement() );
521 }
522
523 if ( nite == 0 ) {
524#if 0
525 #ifdef __PETSC_MODULE
526 if ( solverType == ST_Petsc ) {
527 //Natural2LocalOrdering* n2lpm = engngModel->giveParallelContext(1)->giveN2Lmap();
528 //IntArray* map = n2lpm->giveN2Lmap();
529 for ( i = 1; i <= prescribedEqs.giveSize(); i++ ) {
530 eq = prescribedEqs.at(i);
531 R.at(eq) = prescribedDofsValues.at(i) * factor; // local eq
532 }
533
534 return;
535 }
536
537 #endif
538#else
539 #ifdef __PETSC_MODULE
540 const PetscSparseMtrx *lhs = dynamic_cast< const PetscSparseMtrx * >(& k);
541 if ( lhs ) {
542 Vec diag;
543 PetscScalar *ptr;
544 lhs->createVecGlobal(& diag);
545 MatGetDiagonal(* ( const_cast< PetscSparseMtrx * >(lhs)->giveMtrx() ), diag);
546 VecGetArray(diag, & ptr);
547
548 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
549 int eq = prescribedEqs.at(i) - 1;
550 R.at(eq + 1) = ptr [ eq ] * prescribedDofsValues.at(i) * factor;
551 }
552
553 VecRestoreArray(diag, & ptr);
554 VecDestroy(& diag);
555 return;
556 }
557 #endif
558#endif
559 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
560 int eq = prescribedEqs.at(i);
561 R.at(eq) = k.at(eq, eq) * prescribedDofsValues.at(i) * factor;
562 }
563 } else {
564 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
565 R.at( prescribedEqs.at(i) ) = 0.0;
566 }
567 }
568}
569
570
571void
572NRSolver :: printState(FILE *outputStream)
573{
574#ifdef VERBOSE
575 // print quasi reactions if direct displacement control used
576 fprintf(outputStream, "\nQuasi reaction table:\n\n");
577 fprintf(outputStream, " node dof force\n");
578 fprintf(outputStream, "============================\n");
579 if ( lastReactions.giveSize() == 0 ) {
580 return;
581 }
582
583 double reaction;
584 for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
585 reaction = lastReactions.at(i);
586 fprintf(outputStream, "%6d %3d %+11.5e\n", prescribedDofs.at(2 * i - 1), prescribedDofs.at(2 * i), reaction);
587 }
588 fprintf(outputStream, "============================\n\n");
589#endif
590}
591
592
593bool
594NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, FloatArray &ddX, FloatArray &X,
595 double RRT, const FloatArray &internalForcesEBENorm,
596 int nite, bool &errorOutOfRange)
597{
598 double forceErr, dispErr;
599 FloatArray dg_forceErr, dg_dispErr, dg_totalLoadLevel, dg_totalDisp;
600 bool answer;
602 ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
603
604 /*
605 * The force errors are (if possible) evaluated as relative errors.
606 * If the norm of applied load vector is zero (one may load by temperature, etc)
607 * then the norm of reaction forces is used in relative norm evaluation.
608 *
609 * Note: This is done only when all dofs are included (nccdg = 0). Not implemented if
610 * multiple convergence criteria are used.
611 *
612 */
613
614 answer = true;
615 errorOutOfRange = false;
616
617 // Store the errors associated with the dof groups
618 if ( this->constrainedNRFlag ) {
619 this->forceErrVecOld = this->forceErrVec; // copy the old values
620 this->forceErrVec.resize( internalForcesEBENorm.giveSize() );
621 forceErrVec.zero();
622 }
623
624 if ( internalForcesEBENorm.giveSize() > 1 ) { // Special treatment when just one norm is given; No grouping
625 int nccdg = this->domain->giveMaxDofID();
626 // Keeps tracks of which dof IDs are actually in use;
627 IntArray idsInUse(nccdg);
628 idsInUse.zero();
629 // zero error norms per group
630 dg_forceErr.resize(nccdg);
631 dg_forceErr.zero();
632 dg_dispErr.resize(nccdg);
633 dg_dispErr.zero();
634 dg_totalLoadLevel.resize(nccdg);
635 dg_totalLoadLevel.zero();
636 dg_totalDisp.resize(nccdg);
637 dg_totalDisp.zero();
638 // loop over dof managers
639 for ( auto &dofman : domain->giveDofManagers() ) {
640 if ( !parallel_context->isLocal( dofman.get() ) ) {
641 continue;
642 }
643
644 // loop over individual dofs
645 for ( Dof *dof : *dofman ) {
646 if ( !dof->isPrimaryDof() ) {
647 continue;
648 }
649 int eq = dof->giveEquationNumber(dn);
650 int dofid = dof->giveDofID();
651 if ( !eq ) {
652 continue;
653 }
654
655 dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq);
656 dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq);
657 dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq);
658 dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq);
659 idsInUse.at(dofid)++;
660 } // end loop over DOFs
661 } // end loop over dof managers
662
663 // loop over elements and their DOFs
664 for ( auto &elem : domain->giveElements() ) {
665 if ( elem->giveParallelMode() != Element_local ) {
666 continue;
667 }
668
669 // loop over element internal Dofs
670 for ( int idofman = 1; idofman <= elem->giveNumberOfInternalDofManagers(); idofman++ ) {
671 DofManager *dofman = elem->giveInternalDofManager(idofman);
672 // loop over individual dofs
673 for ( Dof *dof : *dofman ) {
674 if ( !dof->isPrimaryDof() ) {
675 continue;
676 }
677 int eq = dof->giveEquationNumber(dn);
678 int dofid = dof->giveDofID();
679
680 if ( !eq ) {
681 continue;
682 }
683
684 dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq);
685 dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq);
686 dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq);
687 dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq);
688 idsInUse.at(dofid)++;
689 } // end loop over DOFs
690 } // end loop over element internal dofmans
691 } // end loop over elements
692
693 // loop over boundary conditions and their internal DOFs
694 for ( auto &bc : domain->giveBcs() ) {
695 // loop over element internal Dofs
696 for ( int idofman = 1; idofman <= bc->giveNumberOfInternalDofManagers(); idofman++ ) {
697 DofManager *dofman = bc->giveInternalDofManager(idofman);
698 // loop over individual dofs
699 for ( Dof *dof : *dofman ) {
700 if ( !dof->isPrimaryDof() ) {
701 continue;
702 }
703 int eq = dof->giveEquationNumber(dn);
704 int dofid = dof->giveDofID();
705
706 if ( !eq ) {
707 continue;
708 }
709
710 dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq);
711 dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq);
712 dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq);
713 dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq);
714 idsInUse.at(dofid)++;
715 } // end loop over DOFs
716 } // end loop over element internal dofmans
717 } // end loop over elements
718
719 // exchange individual partition contributions (simultaneously for all groups)
720 FloatArray collectiveErr(nccdg);
721 parallel_context->accumulate(dg_forceErr, collectiveErr);
722 dg_forceErr = collectiveErr;
723 parallel_context->accumulate(dg_dispErr, collectiveErr);
724 dg_dispErr = collectiveErr;
725 parallel_context->accumulate(dg_totalLoadLevel, collectiveErr);
726 dg_totalLoadLevel = collectiveErr;
727 parallel_context->accumulate(dg_totalDisp, collectiveErr);
728 dg_totalDisp = collectiveErr;
729
730 if ( engngModel->giveProblemScale() == macroScale ) {
731 OOFEM_LOG_INFO("NRSolver: %-5d", nite);
732 }
733
734 int maxNumPrintouts = 6;
735 int numPrintouts = 0;
736
737 //bool zeroNorm = false;
738 // loop over dof groups and check convergence individually
739 for ( int dg = 1; dg <= nccdg; dg++ ) {
740 bool zeroFNorm = false, zeroDNorm = false;
741 // Skips the ones which aren't used in this problem (the residual will be zero for these anyway, but it is annoying to print them all)
742 if ( !idsInUse.at(dg) ) {
743 continue;
744 }
745
746 numPrintouts++;
747
748 if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts ) {
749 OOFEM_LOG_INFO( " %s:", __DofIDItemToString( ( DofIDItem ) dg ).c_str() );
750 }
751
752 if ( rtolf.at(1) > 0.0 ) {
753 // compute a relative error norm
754 if ( dg_forceScale.find(dg) != dg_forceScale.end() ) {
755 forceErr = sqrt( dg_forceErr.at(dg) / ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) +
756 idsInUse.at(dg) * dg_forceScale [ dg ] * dg_forceScale [ dg ] ) );
757 } else if ( ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) >= nrsolver_ERROR_NORM_SMALL_NUM ) {
758 forceErr = sqrt( dg_forceErr.at(dg) / ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) );
759 } else {
760 // If both external forces and internal ebe norms are zero, then the residual must be zero.
761 //zeroNorm = true; // Warning about this afterwards.
762 zeroFNorm = true;
763 forceErr = sqrt( dg_forceErr.at(dg) );
764 }
765
766 if ( std::isnan( forceErr ) || forceErr > rtolf.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) {
767 errorOutOfRange = true;
768 }
769 if ( forceErr > rtolf.at(1) ) {
770 answer = false;
771 }
772 if ( (forceErr > 0.0) && (nite == 0)) {
773 // if forceError > 0 and first iteration we report no convergence to actually
774 // apply the loading
775 answer = false;
776 }
777
778 if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts ) {
779 OOFEM_LOG_INFO(zeroFNorm ? " *%.3e" : " %.3e", forceErr);
780 }
781
782 // Store the errors from the current iteration
783 if ( this->constrainedNRFlag ) {
784 forceErrVec.at(dg) = forceErr;
785 }
786 }
787
788 if ( rtold.at(1) > 0.0 ) {
789 // compute displacement error
790 if ( dg_totalDisp.at(dg) > nrsolver_ERROR_NORM_SMALL_NUM ) {
791 dispErr = sqrt( dg_dispErr.at(dg) / dg_totalDisp.at(dg) );
792 } else {
794 //zeroNorm = true; // Warning about this afterwards.
795 //zeroDNorm = true;
796 dispErr = sqrt( dg_dispErr.at(dg) );
797 }
798 if ( std::isnan( dispErr ) || dispErr > rtold.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) {
799 errorOutOfRange = true;
800 }
801 if ( dispErr > rtold.at(1) ) {
802 answer = false;
803 }
804
805 if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts ) {
806 OOFEM_LOG_INFO(zeroDNorm ? " *%.3e" : " %.3e", dispErr);
807 }
808 }
809 }
810
811
812 if ( engngModel->giveProblemScale() == macroScale ) {
813 OOFEM_LOG_INFO("\n");
814 }
815
816 //if ( zeroNorm ) OOFEM_WARNING("Had to resort to absolute error measure (marked by *)");
817 } else { // No dof grouping
818 double dXX, dXdX;
819
820 if ( engngModel->giveProblemScale() == macroScale ) {
821 OOFEM_LOG_INFO("NRSolver: %-15d", nite);
822 } else {
823 // OOFEM_LOG_INFO(" NRSolver: %-15d", nite);
824 }
825
826
827 forceErr = parallel_context->localNorm(rhs);
828 forceErr *= forceErr;
829 dXX = parallel_context->localNorm(X);
830 dXX *= dXX; // Note: Solutions are always total global values (natural distribution makes little sense for the solution)
831 dXdX = parallel_context->localNorm(ddX);
832 dXdX *= dXdX;
833
834 if ( rtolf.at(1) > 0.0 ) {
835 // we compute a relative error norm
836 if ( ( RRT + internalForcesEBENorm.at(1) ) > nrsolver_ERROR_NORM_SMALL_NUM ) {
837 forceErr = sqrt( forceErr / ( RRT + internalForcesEBENorm.at(1) ) );
838 } else {
839 forceErr = sqrt(forceErr); // absolute norm as last resort
840 }
841 if ( fabs(forceErr) > rtolf.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) {
842 errorOutOfRange = true;
843 }
844 if ( fabs(forceErr) > rtolf.at(1) ) {
845 answer = false;
846 }
847
848 if ( engngModel->giveProblemScale() == macroScale ) {
849 OOFEM_LOG_INFO(" %-15e", forceErr);
850 }
851
852 if ( this->constrainedNRFlag ) {
853 // store the errors from the current iteration for use in the next
854 forceErrVec.at(1) = forceErr;
855 }
856 }
857
858 if ( rtold.at(1) > 0.0 ) {
859 // compute displacement error
860 // err is relative displacement change
861 if ( dXX > nrsolver_ERROR_NORM_SMALL_NUM ) {
862 dispErr = sqrt(dXdX / dXX);
863 } else {
864 dispErr = sqrt(dXdX);
865 }
866 if ( fabs(dispErr) > rtold.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) {
867 errorOutOfRange = true;
868 }
869 if ( fabs(dispErr) > rtold.at(1) ) {
870 answer = false;
871 }
872
873 if ( engngModel->giveProblemScale() == macroScale ) {
874 OOFEM_LOG_INFO(" %-15e", dispErr);
875 }
876 }
877
878 if ( engngModel->giveProblemScale() == macroScale ) {
879 OOFEM_LOG_INFO("\n");
880 }
881 } // end default case (all dofs contributing)
882
883 return answer;
884}
885} // end namespace oofem
#define REGISTER_SparseNonLinearSystemNM(class)
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 add(const FloatArray &src)
Definition floatarray.C:218
void times(double s)
Definition floatarray.C:834
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
void zero()
Sets all component to zero.
Definition intarray.C:52
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
FloatArray lastReactions
Computed reactions. They are stored in order to print them in printState method.
Definition nrsolver.h:135
double minStepLength
Definition nrsolver.h:103
int constrainedNRminiter
Minimum number of iterations before constraint is activated.
Definition nrsolver.h:147
FloatArray prescribedDofsValues
Array of prescribed values.
Definition nrsolver.h:127
double maxIncAllowed
Definition nrsolver.h:166
SparseMtrx::SparseMtrxVersionType smConstraintVersion
sparse matrix version, used to control constrains application to stiffness
Definition nrsolver.h:113
SparseLinearSystemNM * giveLinearSolver() override
Definition nrsolver.C:406
bool checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, FloatArray &ddX, FloatArray &X, double RRT, const FloatArray &internalForcesEBENorm, int nite, bool &errorOutOfRange)
Definition nrsolver.C:594
std ::unique_ptr< LineSearchNM > linesearchSolver
Line search solver.
Definition nrsolver.h:139
LinSystSolverType solverType
linear system solver ID
Definition nrsolver.h:111
void applyConstraintsToStiffness(SparseMtrx &k)
Definition nrsolver.C:468
int prescribedDisplacementTF
Load Time Function of prescribed values.
Definition nrsolver.h:129
std ::unique_ptr< SparseLinearSystemNM > linSolver
linear system solver
Definition nrsolver.h:109
double constrainedNRalpha
Scale factor for dX, dX_new = alpha * dX.
Definition nrsolver.h:145
IntArray prescribedDofs
Array of pairs identifying prescribed dofs (node, dof).
Definition nrsolver.h:125
int numberOfPrescribedDofs
number of prescribed displacement
Definition nrsolver.h:115
bool prescribedDofsFlag
Definition nrsolver.h:122
void applyConstraintsToLoadIncrement(int nite, const SparseMtrx &k, FloatArray &R, referenceLoadInputModeType rlm, TimeStep *tStep)
Definition nrsolver.C:512
LineSearchNM * giveLineSearchSolver()
Constructs and returns a line search solver.
Definition nrsolver.C:424
IntArray prescribedEqs
Array of prescribed equations.
Definition nrsolver.h:131
FloatArray rtold
Relative iterative displacement change tolerance for each group.
Definition nrsolver.h:152
nrsolver_ModeType NR_OldMode
Definition nrsolver.h:104
bool solutionDependentExternalForcesFlag
Solution dependent external forces - updating then each NR iteration.
Definition nrsolver.h:159
std ::map< int, double > dg_forceScale
Optional user supplied scale of forces used in convergence check.
Definition nrsolver.h:164
bool prescribedEqsInitFlag
Flag indicating that prescribedEqs were initialized.
Definition nrsolver.h:133
FloatArray rtolf
Relative unbalanced force tolerance for each group.
Definition nrsolver.h:150
FloatArray forceErrVec
Definition nrsolver.h:155
bool lsFlag
Flag indicating whether to use line-search.
Definition nrsolver.h:137
void initPrescribedEqs()
Initiates prescribed equations.
Definition nrsolver.C:434
bool mCalcStiffBeforeRes
Flag indicating if the stiffness should be evaluated before the residual in the first iteration.
Definition nrsolver.h:141
nrsolver_ModeType NR_Mode
Definition nrsolver.h:104
FloatArray forceErrVecOld
Definition nrsolver.h:156
bool constrainedNRFlag
Flag indicating whether to use constrained Newton.
Definition nrsolver.h:143
Domain * domain
Pointer to domain.
Definition nummet.h:84
EngngModel * engngModel
Pointer to engineering model.
Definition nummet.h:86
bool isLocal(DofManager *dman)
double accumulate(double local)
double localNorm(const FloatArray &src)
void createVecGlobal(Vec *answer) const
Creates a global vector that fits the instance of this matrix.
SparseMtrxVersionType giveVersion()
Return receiver version.
Definition sparsemtrx.h:94
virtual double & at(int i, int j)=0
Returns coefficient at position (i,j).
@ rlm_total
The reference incremental load vector is defined as totalLoadVector assembled at given time.
void incrementSubStepNumber()
Increments receiver's substep number.
Definition timestep.h:217
void incrementStateCounter()
Updates solution state counter.
Definition timestep.h:213
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
double giveTargetTime()
Returns target time.
Definition timestep.h:164
bool isTheFirstStep()
Definition timestep.C:148
#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
std::string __DofIDItemToString(DofIDItem _value)
Definition cltypes.C:329
@ Element_local
Element is local, there are no contributions from other domains to this element.
Definition element.h:88
@ CR_DIVERGED_TOL
@ CR_DIVERGED_ITS
FloatMatrixF< N, N > diag(const FloatArrayF< N > &v)
ClassFactory & classFactory
static FloatArray Vec1(const double &a)
Definition floatarray.h:605
@ ExternalRhs
@ NonLinearLhs
@ InternalRhs
@ macroScale
Definition problemmode.h:46
#define nrsolver_ERROR_NORM_SMALL_NUM
Definition nrsolver.C:61
#define NRSOLVER_MAX_REL_ERROR_BOUND
Definition nrsolver.C:62
#define _IFT_NRSolver_maxiter
Definition nrsolver.h:55
#define _IFT_NRSolver_ddfunc
Definition nrsolver.h:62
#define _IFT_NRSolver_ddm
Definition nrsolver.h:60
#define _IFT_NRSolver_rtolf
Definition nrsolver.h:65
#define _IFT_NRSolver_linesearch
Definition nrsolver.h:63
#define _IFT_NRSolver_lstype
Definition nrsolver.h:59
#define _IFT_NRSolver_ddv
Definition nrsolver.h:61
#define _IFT_NRSolver_calcstiffbeforeres
Definition nrsolver.h:67
#define _IFT_NRSolver_miniterations
Definition nrsolver.h:56
#define _IFT_NRSolver_manrmsteps
Definition nrsolver.h:58
#define _IFT_NRSolver_rtold
Definition nrsolver.h:66
#define _IFT_NRSolver_solutionDependentExternalForces
Definition nrsolver.h:73
#define _IFT_NRSolver_rtolv
Definition nrsolver.h:64
#define _IFT_NRSolver_maxinc
Definition nrsolver.h:70
#define _IFT_NRSolver_forceScaleDofs
Definition nrsolver.h:72
#define _IFT_NRSolver_minsteplength
Definition nrsolver.h:57
#define _IFT_NRSolver_forceScale
Definition nrsolver.h:71
#define _IFT_NRSolver_constrainedNRminiter
Definition nrsolver.h:69

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