-
Notifications
You must be signed in to change notification settings - Fork 244
/
residualbased_newton_raphson_strategy.h
1502 lines (1236 loc) · 55.2 KB
/
residualbased_newton_raphson_strategy.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// | / |
// ' / __| _` | __| _ \ __|
// . \ | ( | | ( |\__ \.
// _|\_\_| \__,_|\__|\___/ ____/
// Multi-Physics
//
// License: BSD License
// Kratos default license: kratos/license.txt
//
// Main authors: Riccardo Rossi
//
#if !defined(KRATOS_RESIDUALBASED_NEWTON_RAPHSON_STRATEGY)
#define KRATOS_RESIDUALBASED_NEWTON_RAPHSON_STRATEGY
// System includes
#include <iostream>
// External includes
// Project includes
#include "includes/define.h"
#include "solving_strategies/strategies/implicit_solving_strategy.h"
#include "solving_strategies/convergencecriterias/convergence_criteria.h"
#include "utilities/builtin_timer.h"
//default builder and solver
#include "solving_strategies/builder_and_solvers/residualbased_block_builder_and_solver.h"
namespace Kratos
{
///@name Kratos Globals
///@{
///@}
///@name Type Definitions
///@{
///@}
///@name Enum's
///@{
///@}
///@name Functions
///@{
///@}
///@name Kratos Classes
///@{
/**
* @class ResidualBasedNewtonRaphsonStrategy
* @ingroup KratosCore
* @brief This is the base Newton Raphson strategy
* @details This strategy iterates until the convergence is achieved (or the maximum number of iterations is surpassed) using a Newton Raphson algorithm
* @author Riccardo Rossi
*/
template <class TSparseSpace,
class TDenseSpace, // = DenseSpace<double>,
class TLinearSolver //= LinearSolver<TSparseSpace,TDenseSpace>
>
class ResidualBasedNewtonRaphsonStrategy
: public ImplicitSolvingStrategy<TSparseSpace, TDenseSpace, TLinearSolver>
{
public:
///@name Type Definitions
///@{
typedef ConvergenceCriteria<TSparseSpace, TDenseSpace> TConvergenceCriteriaType;
// Counted pointer of ClassName
KRATOS_CLASS_POINTER_DEFINITION(ResidualBasedNewtonRaphsonStrategy);
typedef SolvingStrategy<TSparseSpace, TDenseSpace> SolvingStrategyType;
typedef ImplicitSolvingStrategy<TSparseSpace, TDenseSpace, TLinearSolver> BaseType;
typedef ResidualBasedNewtonRaphsonStrategy<TSparseSpace, TDenseSpace, TLinearSolver> ClassType;
typedef typename BaseType::TBuilderAndSolverType TBuilderAndSolverType;
typedef typename BaseType::TDataType TDataType;
typedef TSparseSpace SparseSpaceType;
typedef typename BaseType::TSchemeType TSchemeType;
typedef typename BaseType::DofsArrayType DofsArrayType;
typedef typename BaseType::TSystemMatrixType TSystemMatrixType;
typedef typename BaseType::TSystemVectorType TSystemVectorType;
typedef typename BaseType::LocalSystemVectorType LocalSystemVectorType;
typedef typename BaseType::LocalSystemMatrixType LocalSystemMatrixType;
typedef typename BaseType::TSystemMatrixPointerType TSystemMatrixPointerType;
typedef typename BaseType::TSystemVectorPointerType TSystemVectorPointerType;
///@}
///@name Life Cycle
///@{
/**
* @brief Default constructor
*/
explicit ResidualBasedNewtonRaphsonStrategy() : BaseType()
{
}
/**
* @brief Default constructor. (with parameters)
* @param rModelPart The model part of the problem
* @param ThisParameters The configuration parameters
*/
explicit ResidualBasedNewtonRaphsonStrategy(ModelPart& rModelPart)
: ResidualBasedNewtonRaphsonStrategy(rModelPart, ResidualBasedNewtonRaphsonStrategy::GetDefaultParameters())
{
}
/**
* @brief Default constructor. (with parameters)
* @param rModelPart The model part of the problem
* @param ThisParameters The configuration parameters
*/
explicit ResidualBasedNewtonRaphsonStrategy(ModelPart& rModelPart, Parameters ThisParameters)
: BaseType(rModelPart),
mInitializeWasPerformed(false),
mKeepSystemConstantDuringIterations(false)
{
// Validate and assign defaults
ThisParameters = this->ValidateAndAssignParameters(ThisParameters, this->GetDefaultParameters());
this->AssignSettings(ThisParameters);
// Getting builder and solver
auto p_builder_and_solver = GetBuilderAndSolver();
if (p_builder_and_solver != nullptr) {
// Tells to the builder and solver if the reactions have to be Calculated or not
p_builder_and_solver->SetCalculateReactionsFlag(mCalculateReactionsFlag);
// Tells to the Builder And Solver if the system matrix and vectors need to
// be reshaped at each step or not
p_builder_and_solver->SetReshapeMatrixFlag(mReformDofSetAtEachStep);
} else {
KRATOS_WARNING("ResidualBasedNewtonRaphsonStrategy") << "BuilderAndSolver is not initialized. Please assign one before settings flags" << std::endl;
}
mpA = TSparseSpace::CreateEmptyMatrixPointer();
mpDx = TSparseSpace::CreateEmptyVectorPointer();
mpb = TSparseSpace::CreateEmptyVectorPointer();
}
/**
* Default constructor
* @param rModelPart The model part of the problem
* @param pScheme The integration scheme
* @param pNewLinearSolver The linear solver employed
* @param pNewConvergenceCriteria The convergence criteria employed
* @param MaxIterations The maximum number of non-linear iterations to be considered when solving the problem
* @param CalculateReactions The flag for the reaction calculation
* @param ReformDofSetAtEachStep The flag that allows to compute the modification of the DOF
* @param MoveMeshFlag The flag that allows to move the mesh
*/
explicit ResidualBasedNewtonRaphsonStrategy(
ModelPart& rModelPart,
typename TSchemeType::Pointer pScheme,
typename TLinearSolver::Pointer pNewLinearSolver,
typename TConvergenceCriteriaType::Pointer pNewConvergenceCriteria,
int MaxIterations = 30,
bool CalculateReactions = false,
bool ReformDofSetAtEachStep = false,
bool MoveMeshFlag = false)
: BaseType(rModelPart, MoveMeshFlag),
mpScheme(pScheme),
mpConvergenceCriteria(pNewConvergenceCriteria),
mReformDofSetAtEachStep(ReformDofSetAtEachStep),
mCalculateReactionsFlag(CalculateReactions),
mMaxIterationNumber(MaxIterations),
mInitializeWasPerformed(false),
mKeepSystemConstantDuringIterations(false)
{
KRATOS_TRY;
// Setting up the default builder and solver
mpBuilderAndSolver = typename TBuilderAndSolverType::Pointer(
new ResidualBasedBlockBuilderAndSolver<TSparseSpace, TDenseSpace, TLinearSolver>(pNewLinearSolver));
// Tells to the builder and solver if the reactions have to be Calculated or not
mpBuilderAndSolver->SetCalculateReactionsFlag(mCalculateReactionsFlag);
// Tells to the Builder And Solver if the system matrix and vectors need to
// be reshaped at each step or not
mpBuilderAndSolver->SetReshapeMatrixFlag(mReformDofSetAtEachStep);
// Set EchoLevel to the default value (only time is displayed)
SetEchoLevel(1);
// By default the matrices are rebuilt at each iteration
this->SetRebuildLevel(2);
mpA = TSparseSpace::CreateEmptyMatrixPointer();
mpDx = TSparseSpace::CreateEmptyVectorPointer();
mpb = TSparseSpace::CreateEmptyVectorPointer();
KRATOS_CATCH("");
}
/**
* @brief Constructor specifying the builder and solver
* @param rModelPart The model part of the problem
* @param pScheme The integration scheme
* @param pNewConvergenceCriteria The convergence criteria employed
* @param pNewBuilderAndSolver The builder and solver employed
* @param MaxIterations The maximum number of non-linear iterations to be considered when solving the problem
* @param CalculateReactions The flag for the reaction calculation
* @param ReformDofSetAtEachStep The flag that allows to compute the modification of the DOF
* @param MoveMeshFlag The flag that allows to move the mesh
*/
explicit ResidualBasedNewtonRaphsonStrategy(
ModelPart& rModelPart,
typename TSchemeType::Pointer pScheme,
typename TConvergenceCriteriaType::Pointer pNewConvergenceCriteria,
typename TBuilderAndSolverType::Pointer pNewBuilderAndSolver,
int MaxIterations = 30,
bool CalculateReactions = false,
bool ReformDofSetAtEachStep = false,
bool MoveMeshFlag = false)
: BaseType(rModelPart, MoveMeshFlag),
mpScheme(pScheme),
mpBuilderAndSolver(pNewBuilderAndSolver),
mpConvergenceCriteria(pNewConvergenceCriteria),
mReformDofSetAtEachStep(ReformDofSetAtEachStep),
mCalculateReactionsFlag(CalculateReactions),
mMaxIterationNumber(MaxIterations),
mInitializeWasPerformed(false),
mKeepSystemConstantDuringIterations(false)
{
KRATOS_TRY
// Getting builder and solver
auto p_builder_and_solver = GetBuilderAndSolver();
// Tells to the builder and solver if the reactions have to be Calculated or not
p_builder_and_solver->SetCalculateReactionsFlag(mCalculateReactionsFlag);
// Tells to the Builder And Solver if the system matrix and vectors need to
//be reshaped at each step or not
p_builder_and_solver->SetReshapeMatrixFlag(mReformDofSetAtEachStep);
// Set EchoLevel to the default value (only time is displayed)
SetEchoLevel(1);
// By default the matrices are rebuilt at each iteration
this->SetRebuildLevel(2);
mpA = TSparseSpace::CreateEmptyMatrixPointer();
mpDx = TSparseSpace::CreateEmptyVectorPointer();
mpb = TSparseSpace::CreateEmptyVectorPointer();
KRATOS_CATCH("")
}
/**
* @brief Constructor specifying the builder and solver
* @param rModelPart The model part of the problem
* @param pScheme The integration scheme
* @param pNewLinearSolver The linear solver employed
* @param pNewConvergenceCriteria The convergence criteria employed
* @param pNewBuilderAndSolver The builder and solver employed
* @param MaxIterations The maximum number of non-linear iterations to be considered when solving the problem
* @param CalculateReactions The flag for the reaction calculation
* @param ReformDofSetAtEachStep The flag that allows to compute the modification of the DOF
* @param MoveMeshFlag The flag that allows to move the mesh
*/
KRATOS_DEPRECATED_MESSAGE("Constructor deprecated, please use the constructor without linear solver")
explicit ResidualBasedNewtonRaphsonStrategy(
ModelPart& rModelPart,
typename TSchemeType::Pointer pScheme,
typename TLinearSolver::Pointer pNewLinearSolver,
typename TConvergenceCriteriaType::Pointer pNewConvergenceCriteria,
typename TBuilderAndSolverType::Pointer pNewBuilderAndSolver,
int MaxIterations = 30,
bool CalculateReactions = false,
bool ReformDofSetAtEachStep = false,
bool MoveMeshFlag = false)
: ResidualBasedNewtonRaphsonStrategy<TSparseSpace, TDenseSpace, TLinearSolver>(rModelPart, pScheme, pNewConvergenceCriteria, pNewBuilderAndSolver, MaxIterations, CalculateReactions, ReformDofSetAtEachStep, MoveMeshFlag)
{
KRATOS_TRY
KRATOS_WARNING("ResidualBasedNewtonRaphsonStrategy") << "This constructor is deprecated, please use the constructor without linear solver" << std::endl;
// Getting builder and solver
auto p_builder_and_solver = GetBuilderAndSolver();
// We check if the linear solver considered for the builder and solver is consistent
auto p_linear_solver = p_builder_and_solver->GetLinearSystemSolver();
KRATOS_ERROR_IF(p_linear_solver != pNewLinearSolver) << "Inconsistent linear solver in strategy and builder and solver. Considering the linear solver assigned to builder and solver :\n" << p_linear_solver->Info() << "\n instead of:\n" << pNewLinearSolver->Info() << std::endl;
KRATOS_CATCH("")
}
/**
* Constructor with Parameters
* @param rModelPart The model part of the problem
* @param pScheme The integration scheme
* @param pNewLinearSolver The linear solver employed
* @param pNewConvergenceCriteria The convergence criteria employed
* @param Settings Settings used in the strategy
*/
ResidualBasedNewtonRaphsonStrategy(
ModelPart& rModelPart,
typename TSchemeType::Pointer pScheme,
typename TLinearSolver::Pointer pNewLinearSolver,
typename TConvergenceCriteriaType::Pointer pNewConvergenceCriteria,
Parameters Settings)
: BaseType(rModelPart),
mpScheme(pScheme),
mpConvergenceCriteria(pNewConvergenceCriteria),
mInitializeWasPerformed(false),
mKeepSystemConstantDuringIterations(false)
{
KRATOS_TRY;
// Setting up the default builder and solver
mpBuilderAndSolver = typename TBuilderAndSolverType::Pointer(
new ResidualBasedBlockBuilderAndSolver<TSparseSpace, TDenseSpace, TLinearSolver>(pNewLinearSolver));
// Tells to the builder and solver if the reactions have to be Calculated or not
mpBuilderAndSolver->SetCalculateReactionsFlag(mCalculateReactionsFlag);
// Tells to the Builder And Solver if the system matrix and vectors need to
// be reshaped at each step or not
mpBuilderAndSolver->SetReshapeMatrixFlag(mReformDofSetAtEachStep);
// Set EchoLevel to the default value (only time is displayed)
SetEchoLevel(1);
// By default the matrices are rebuilt at each iteration
this->SetRebuildLevel(2);
mpA = TSparseSpace::CreateEmptyMatrixPointer();
mpDx = TSparseSpace::CreateEmptyVectorPointer();
mpb = TSparseSpace::CreateEmptyVectorPointer();
KRATOS_CATCH("");
}
/**
* @brief Constructor specifying the builder and solver and using Parameters
* @param rModelPart The model part of the problem
* @param pScheme The integration scheme
* @param pNewLinearSolver The linear solver employed
* @param pNewConvergenceCriteria The convergence criteria employed
* @param pNewBuilderAndSolver The builder and solver employed
* @param Settings Settings used in the strategy
*/
ResidualBasedNewtonRaphsonStrategy(
ModelPart& rModelPart,
typename TSchemeType::Pointer pScheme,
typename TConvergenceCriteriaType::Pointer pNewConvergenceCriteria,
typename TBuilderAndSolverType::Pointer pNewBuilderAndSolver,
Parameters Settings)
: BaseType(rModelPart),
mpScheme(pScheme),
mpBuilderAndSolver(pNewBuilderAndSolver),
mpConvergenceCriteria(pNewConvergenceCriteria),
mInitializeWasPerformed(false),
mKeepSystemConstantDuringIterations(false)
{
KRATOS_TRY
// Validate and assign defaults
Settings = this->ValidateAndAssignParameters(Settings, this->GetDefaultParameters());
this->AssignSettings(Settings);
// Getting builder and solver
auto p_builder_and_solver = GetBuilderAndSolver();
// Tells to the builder and solver if the reactions have to be Calculated or not
p_builder_and_solver->SetCalculateReactionsFlag(mCalculateReactionsFlag);
// Tells to the Builder And Solver if the system matrix and vectors need to
//be reshaped at each step or not
p_builder_and_solver->SetReshapeMatrixFlag(mReformDofSetAtEachStep);
// Set EchoLevel to the default value (only time is displayed)
SetEchoLevel(1);
// By default the matrices are rebuilt at each iteration
this->SetRebuildLevel(2);
mpA = TSparseSpace::CreateEmptyMatrixPointer();
mpDx = TSparseSpace::CreateEmptyVectorPointer();
mpb = TSparseSpace::CreateEmptyVectorPointer();
KRATOS_CATCH("")
}
/**
* @brief Constructor specifying the builder and solver and using Parameters
* @param rModelPart The model part of the problem
* @param pScheme The integration scheme
* @param pNewLinearSolver The linear solver employed
* @param pNewConvergenceCriteria The convergence criteria employed
* @param pNewBuilderAndSolver The builder and solver employed
* @param Parameters Settings used in the strategy
*/
KRATOS_DEPRECATED_MESSAGE("Constructor deprecated, please use the constructor without linear solver")
ResidualBasedNewtonRaphsonStrategy(
ModelPart& rModelPart,
typename TSchemeType::Pointer pScheme,
typename TLinearSolver::Pointer pNewLinearSolver,
typename TConvergenceCriteriaType::Pointer pNewConvergenceCriteria,
typename TBuilderAndSolverType::Pointer pNewBuilderAndSolver,
Parameters Settings)
: ResidualBasedNewtonRaphsonStrategy<TSparseSpace, TDenseSpace, TLinearSolver>(rModelPart, pScheme, pNewConvergenceCriteria, pNewBuilderAndSolver, Settings)
{
KRATOS_TRY
KRATOS_WARNING("ResidualBasedNewtonRaphsonStrategy") << "This constructor is deprecated, please use the constructor without linear solver" << std::endl;
// Getting builder and solver
auto p_builder_and_solver = GetBuilderAndSolver();
// We check if the linear solver considered for the builder and solver is consistent
auto p_linear_solver = p_builder_and_solver->GetLinearSystemSolver();
KRATOS_ERROR_IF(p_linear_solver != pNewLinearSolver) << "Inconsistent linear solver in strategy and builder and solver. Considering the linear solver assigned to builder and solver :\n" << p_linear_solver->Info() << "\n instead of:\n" << pNewLinearSolver->Info() << std::endl;
KRATOS_CATCH("")
}
/**
* @brief Destructor.
* @details In trilinos third party library, the linear solver's preconditioner should be freed before the system matrix. We control the deallocation order with Clear().
*/
~ResidualBasedNewtonRaphsonStrategy() override
{
// If the linear solver has not been deallocated, clean it before
// deallocating mpA. This prevents a memory error with the the ML
// solver (which holds a reference to it).
// NOTE: The linear solver is hold by the B&S
auto p_builder_and_solver = this->GetBuilderAndSolver();
if (p_builder_and_solver != nullptr) {
p_builder_and_solver->Clear();
}
// Deallocating system vectors to avoid errors in MPI. Clear calls
// TrilinosSpace::Clear for the vectors, which preserves the Map of
// current vectors, performing MPI calls in the process. Due to the
// way Python garbage collection works, this may happen after
// MPI_Finalize has already been called and is an error. Resetting
// the pointers here prevents Clear from operating with the
// (now deallocated) vectors.
mpA.reset();
mpDx.reset();
mpb.reset();
Clear();
}
/**
* @brief Set method for the time scheme
* @param pScheme The pointer to the time scheme considered
*/
void SetScheme(typename TSchemeType::Pointer pScheme)
{
mpScheme = pScheme;
};
/**
* @brief Get method for the time scheme
* @return mpScheme: The pointer to the time scheme considered
*/
typename TSchemeType::Pointer GetScheme()
{
return mpScheme;
};
/**
* @brief Set method for the builder and solver
* @param pNewBuilderAndSolver The pointer to the builder and solver considered
*/
void SetBuilderAndSolver(typename TBuilderAndSolverType::Pointer pNewBuilderAndSolver)
{
mpBuilderAndSolver = pNewBuilderAndSolver;
};
/**
* @brief Get method for the builder and solver
* @return mpBuilderAndSolver: The pointer to the builder and solver considered
*/
typename TBuilderAndSolverType::Pointer GetBuilderAndSolver()
{
return mpBuilderAndSolver;
};
/**
* @brief This method sets the flag mInitializeWasPerformed
* @param InitializePerformedFlag The flag that tells if the initialize has been computed
*/
void SetInitializePerformedFlag(bool InitializePerformedFlag = true)
{
mInitializeWasPerformed = InitializePerformedFlag;
}
/**
* @brief This method gets the flag mInitializeWasPerformed
* @return mInitializeWasPerformed: The flag that tells if the initialize has been computed
*/
bool GetInitializePerformedFlag()
{
return mInitializeWasPerformed;
}
/**
* @brief This method sets the flag mCalculateReactionsFlag
* @param CalculateReactionsFlag The flag that tells if the reactions are computed
*/
void SetCalculateReactionsFlag(bool CalculateReactionsFlag)
{
mCalculateReactionsFlag = CalculateReactionsFlag;
}
/**
* @brief This method returns the flag mCalculateReactionsFlag
* @return The flag that tells if the reactions are computed
*/
bool GetCalculateReactionsFlag()
{
return mCalculateReactionsFlag;
}
/**
* @brief This method sets the flag mFullUpdateFlag
* @param UseOldStiffnessInFirstIterationFlag The flag that tells if
*/
void SetUseOldStiffnessInFirstIterationFlag(bool UseOldStiffnessInFirstIterationFlag)
{
mUseOldStiffnessInFirstIteration = UseOldStiffnessInFirstIterationFlag;
}
/**
* @brief This method returns the flag mFullUpdateFlag
* @return The flag that tells if
*/
bool GetUseOldStiffnessInFirstIterationFlag()
{
return mUseOldStiffnessInFirstIteration;
}
/**
* @brief This method sets the flag mReformDofSetAtEachStep
* @param Flag The flag that tells if each time step the system is rebuilt
*/
void SetReformDofSetAtEachStepFlag(bool Flag)
{
mReformDofSetAtEachStep = Flag;
GetBuilderAndSolver()->SetReshapeMatrixFlag(mReformDofSetAtEachStep);
}
/**
* @brief This method returns the flag mReformDofSetAtEachStep
* @return The flag that tells if each time step the system is rebuilt
*/
bool GetReformDofSetAtEachStepFlag()
{
return mReformDofSetAtEachStep;
}
/**
* @brief This method sets the flag mMaxIterationNumber
* @param MaxIterationNumber This is the maximum number of on linear iterations
*/
void SetMaxIterationNumber(unsigned int MaxIterationNumber)
{
mMaxIterationNumber = MaxIterationNumber;
}
/**
* @brief This method gets the flag mMaxIterationNumber
* @return mMaxIterationNumber: This is the maximum number of on linear iterations
*/
unsigned int GetMaxIterationNumber()
{
return mMaxIterationNumber;
}
/**
* @brief It sets the level of echo for the solving strategy
* @param Level The level to set
* @details The different levels of echo are:
* - 0: Mute... no echo at all
* - 1: Printing time and basic information
* - 2: Printing linear solver data
* - 3: Print of debug information: Echo of stiffness matrix, Dx, b...
*/
void SetEchoLevel(int Level) override
{
BaseType::mEchoLevel = Level;
GetBuilderAndSolver()->SetEchoLevel(Level);
mpConvergenceCriteria->SetEchoLevel(Level);
}
//*********************************************************************************
/**OPERATIONS ACCESSIBLE FROM THE INPUT: **/
/**
* @brief Create method
* @param rModelPart The model part of the problem
* @param ThisParameters The configuration parameters
*/
typename SolvingStrategyType::Pointer Create(
ModelPart& rModelPart,
Parameters ThisParameters
) const override
{
return Kratos::make_shared<ClassType>(rModelPart, ThisParameters);
}
/**
* @brief Operation to predict the solution ... if it is not called a trivial predictor is used in which the
values of the solution step of interest are assumed equal to the old values
*/
void Predict() override
{
KRATOS_TRY
const DataCommunicator &r_comm = BaseType::GetModelPart().GetCommunicator().GetDataCommunicator();
//OPERATIONS THAT SHOULD BE DONE ONCE - internal check to avoid repetitions
//if the operations needed were already performed this does nothing
if (mInitializeWasPerformed == false)
Initialize();
TSystemMatrixType& rA = *mpA;
TSystemVectorType& rDx = *mpDx;
TSystemVectorType& rb = *mpb;
DofsArrayType& r_dof_set = GetBuilderAndSolver()->GetDofSet();
GetScheme()->Predict(BaseType::GetModelPart(), r_dof_set, rA, rDx, rb);
// Applying constraints if needed
auto& r_constraints_array = BaseType::GetModelPart().MasterSlaveConstraints();
const int local_number_of_constraints = r_constraints_array.size();
const int global_number_of_constraints = r_comm.SumAll(local_number_of_constraints);
if(global_number_of_constraints != 0) {
const auto& r_process_info = BaseType::GetModelPart().GetProcessInfo();
block_for_each(r_constraints_array, [&r_process_info](MasterSlaveConstraint& rConstraint){
rConstraint.ResetSlaveDofs(r_process_info);
});
block_for_each(r_constraints_array, [&r_process_info](MasterSlaveConstraint& rConstraint){
rConstraint.Apply(r_process_info);
});
// The following is needed since we need to eventually compute time derivatives after applying
// Master slave relations
TSparseSpace::SetToZero(rDx);
this->GetScheme()->Update(BaseType::GetModelPart(), r_dof_set, rA, rDx, rb);
}
// Move the mesh if needed
if (this->MoveMeshFlag() == true)
BaseType::MoveMesh();
KRATOS_CATCH("")
}
/**
* @brief Initialization of member variables and prior operations
*/
void Initialize() override
{
KRATOS_TRY;
if (mInitializeWasPerformed == false)
{
//pointers needed in the solution
typename TSchemeType::Pointer p_scheme = GetScheme();
typename TConvergenceCriteriaType::Pointer p_convergence_criteria = mpConvergenceCriteria;
//Initialize The Scheme - OPERATIONS TO BE DONE ONCE
if (p_scheme->SchemeIsInitialized() == false)
p_scheme->Initialize(BaseType::GetModelPart());
//Initialize The Elements - OPERATIONS TO BE DONE ONCE
if (p_scheme->ElementsAreInitialized() == false)
p_scheme->InitializeElements(BaseType::GetModelPart());
//Initialize The Conditions - OPERATIONS TO BE DONE ONCE
if (p_scheme->ConditionsAreInitialized() == false)
p_scheme->InitializeConditions(BaseType::GetModelPart());
//initialisation of the convergence criteria
if (p_convergence_criteria->IsInitialized() == false)
p_convergence_criteria->Initialize(BaseType::GetModelPart());
mInitializeWasPerformed = true;
}
KRATOS_CATCH("");
}
/**
* @brief Clears the internal storage
*/
void Clear() override
{
KRATOS_TRY;
// Setting to zero the internal flag to ensure that the dof sets are recalculated. Also clear the linear solver stored in the B&S
auto p_builder_and_solver = GetBuilderAndSolver();
if (p_builder_and_solver != nullptr) {
p_builder_and_solver->SetDofSetIsInitializedFlag(false);
p_builder_and_solver->Clear();
}
// Clearing the system of equations
if (mpA != nullptr)
SparseSpaceType::Clear(mpA);
if (mpDx != nullptr)
SparseSpaceType::Clear(mpDx);
if (mpb != nullptr)
SparseSpaceType::Clear(mpb);
// Clearing scheme
auto p_scheme = GetScheme();
if (p_scheme != nullptr) {
GetScheme()->Clear();
}
mInitializeWasPerformed = false;
KRATOS_CATCH("");
}
/**
* @brief This should be considered as a "post solution" convergence check which is useful for coupled analysis - the convergence criteria used is the one used inside the "solve" step
*/
bool IsConverged() override
{
KRATOS_TRY;
TSystemMatrixType& rA = *mpA;
TSystemVectorType& rDx = *mpDx;
TSystemVectorType& rb = *mpb;
if (mpConvergenceCriteria->GetActualizeRHSflag() == true)
{
TSparseSpace::SetToZero(rb);
GetBuilderAndSolver()->BuildRHS(GetScheme(), BaseType::GetModelPart(), rb);
}
return mpConvergenceCriteria->PostCriteria(BaseType::GetModelPart(), GetBuilderAndSolver()->GetDofSet(), rA, rDx, rb);
KRATOS_CATCH("");
}
/**
* @brief This operations should be called before printing the results when non trivial results
* (e.g. stresses)
* Need to be calculated given the solution of the step
* @details This operations should be called only when needed, before printing as it can involve a non
* negligible cost
*/
void CalculateOutputData() override
{
TSystemMatrixType& rA = *mpA;
TSystemVectorType& rDx = *mpDx;
TSystemVectorType& rb = *mpb;
GetScheme()->CalculateOutputData(BaseType::GetModelPart(),
GetBuilderAndSolver()->GetDofSet(),
rA, rDx, rb);
}
/**
* @brief Performs all the required operations that should be done (for each step) before solving the solution step.
* @details A member variable should be used as a flag to make sure this function is called only once per step.
*/
void InitializeSolutionStep() override
{
KRATOS_TRY;
// Pointers needed in the solution
typename TSchemeType::Pointer p_scheme = GetScheme();
typename TBuilderAndSolverType::Pointer p_builder_and_solver = GetBuilderAndSolver();
ModelPart& r_model_part = BaseType::GetModelPart();
// Set up the system, operation performed just once unless it is required
// to reform the dof set at each iteration
BuiltinTimer system_construction_time;
if (!p_builder_and_solver->GetDofSetIsInitializedFlag() || mReformDofSetAtEachStep)
{
// Setting up the list of the DOFs to be solved
BuiltinTimer setup_dofs_time;
p_builder_and_solver->SetUpDofSet(p_scheme, r_model_part);
KRATOS_INFO_IF("ResidualBasedNewtonRaphsonStrategy", BaseType::GetEchoLevel() > 0) << "Setup Dofs Time: "
<< setup_dofs_time << std::endl;
// Shaping correctly the system
BuiltinTimer setup_system_time;
p_builder_and_solver->SetUpSystem(r_model_part);
KRATOS_INFO_IF("ResidualBasedNewtonRaphsonStrategy", BaseType::GetEchoLevel() > 0) << "Setup System Time: "
<< setup_system_time << std::endl;
// Setting up the Vectors involved to the correct size
BuiltinTimer system_matrix_resize_time;
p_builder_and_solver->ResizeAndInitializeVectors(p_scheme, mpA, mpDx, mpb,
r_model_part);
KRATOS_INFO_IF("ResidualBasedNewtonRaphsonStrategy", BaseType::GetEchoLevel() > 0) << "System Matrix Resize Time: "
<< system_matrix_resize_time << std::endl;
}
KRATOS_INFO_IF("ResidualBasedNewtonRaphsonStrategy", BaseType::GetEchoLevel() > 0) << "System Construction Time: "
<< system_construction_time << std::endl;
TSystemMatrixType& rA = *mpA;
TSystemVectorType& rDx = *mpDx;
TSystemVectorType& rb = *mpb;
// Initial operations ... things that are constant over the Solution Step
p_builder_and_solver->InitializeSolutionStep(r_model_part, rA, rDx, rb);
// Initial operations ... things that are constant over the Solution Step
p_scheme->InitializeSolutionStep(r_model_part, rA, rDx, rb);
// Initialisation of the convergence criteria
if (mpConvergenceCriteria->GetActualizeRHSflag())
{
TSparseSpace::SetToZero(rb);
p_builder_and_solver->BuildRHS(p_scheme, r_model_part, rb);
}
mpConvergenceCriteria->InitializeSolutionStep(r_model_part, p_builder_and_solver->GetDofSet(), rA, rDx, rb);
if (mpConvergenceCriteria->GetActualizeRHSflag()) {
TSparseSpace::SetToZero(rb);
}
KRATOS_CATCH("");
}
/**
* @brief Performs all the required operations that should be done (for each step) after solving the solution step.
* @details A member variable should be used as a flag to make sure this function is called only once per step.
*/
void FinalizeSolutionStep() override
{
KRATOS_TRY;
ModelPart& r_model_part = BaseType::GetModelPart();
typename TSchemeType::Pointer p_scheme = GetScheme();
typename TBuilderAndSolverType::Pointer p_builder_and_solver = GetBuilderAndSolver();
TSystemMatrixType& rA = *mpA;
TSystemVectorType& rDx = *mpDx;
TSystemVectorType& rb = *mpb;
//Finalisation of the solution step,
//operations to be done after achieving convergence, for example the
//Final Residual Vector (mb) has to be saved in there
//to avoid error accumulation
p_scheme->FinalizeSolutionStep(r_model_part, rA, rDx, rb);
p_builder_and_solver->FinalizeSolutionStep(r_model_part, rA, rDx, rb);
mpConvergenceCriteria->FinalizeSolutionStep(r_model_part, p_builder_and_solver->GetDofSet(), rA, rDx, rb);
//Cleaning memory after the solution
p_scheme->Clean();
if (mReformDofSetAtEachStep == true) //deallocate the systemvectors
{
this->Clear();
}
KRATOS_CATCH("");
}
/**
* @brief Gets the current solution vector
* @param rDofSet The set of degrees of freedom (DOFs)
* @param this_solution The vector that will be filled with the current solution values
* @details This method retrieves the current solution values for the provided DOF set.
* The provided solution vector will be resized to match the size of the DOF set if necessary,
* and will be filled with the solution values corresponding to each DOF. Each value is accessed
* using the equation ID associated with each DOF.
*/
void GetCurrentSolution(DofsArrayType& rDofSet, Vector& this_solution) {
this_solution.resize(rDofSet.size());
block_for_each(rDofSet, [&](const auto& r_dof) {
this_solution[r_dof.EquationId()] = r_dof.GetSolutionStepValue();
});
}
/**
* @brief Gets the matrix of non-converged solutions and the DOF set
* @return A tuple containing the matrix of non-converged solutions and the DOF set
* @details This method returns a tuple where the first element is a matrix of non-converged solutions and the second element is the corresponding DOF set.
*/
std::tuple<Matrix, DofsArrayType> GetNonconvergedSolutions(){
return std::make_tuple(mNonconvergedSolutionsMatrix, GetBuilderAndSolver()->GetDofSet());
}
/**
* @brief Sets the state for storing non-converged solutions.
* @param state The state to set for storing non-converged solutions (true to enable, false to disable).
* @details This method enables or disables the storage of non-converged solutions at each iteration
* by setting the appropriate flag. When the flag is set to true, non-converged solutions will be stored.
*/
void SetUpNonconvergedSolutionsFlag(bool state) {
mStoreNonconvergedSolutionsFlag = state;
}
/**
* @brief Solves the current step. This function returns true if a solution has been found, false otherwise.
*/
bool SolveSolutionStep() override
{
// Pointers needed in the solution
ModelPart& r_model_part = BaseType::GetModelPart();
typename TSchemeType::Pointer p_scheme = GetScheme();
typename TBuilderAndSolverType::Pointer p_builder_and_solver = GetBuilderAndSolver();
auto& r_dof_set = p_builder_and_solver->GetDofSet();
std::vector<Vector> NonconvergedSolutions;
if (mStoreNonconvergedSolutionsFlag) {
Vector initial;
GetCurrentSolution(r_dof_set,initial);
NonconvergedSolutions.push_back(initial);
}
TSystemMatrixType& rA = *mpA;
TSystemVectorType& rDx = *mpDx;
TSystemVectorType& rb = *mpb;
//initializing the parameters of the Newton-Raphson cycle
unsigned int iteration_number = 1;
r_model_part.GetProcessInfo()[NL_ITERATION_NUMBER] = iteration_number;
bool residual_is_updated = false;
p_scheme->InitializeNonLinIteration(r_model_part, rA, rDx, rb);
mpConvergenceCriteria->InitializeNonLinearIteration(r_model_part, r_dof_set, rA, rDx, rb);
bool is_converged = mpConvergenceCriteria->PreCriteria(r_model_part, r_dof_set, rA, rDx, rb);
// Function to perform the building and the solving phase.
if (BaseType::mRebuildLevel > 0 || BaseType::mStiffnessMatrixIsBuilt == false) {
TSparseSpace::SetToZero(rA);
TSparseSpace::SetToZero(rDx);
TSparseSpace::SetToZero(rb);
if (mUseOldStiffnessInFirstIteration){
p_builder_and_solver->BuildAndSolveLinearizedOnPreviousIteration(p_scheme, r_model_part, rA, rDx, rb,BaseType::MoveMeshFlag());
} else {
p_builder_and_solver->BuildAndSolve(p_scheme, r_model_part, rA, rDx, rb);
}
} else {
TSparseSpace::SetToZero(rDx); // Dx = 0.00;
TSparseSpace::SetToZero(rb);
p_builder_and_solver->BuildRHSAndSolve(p_scheme, r_model_part, rA, rDx, rb);
}
// Debugging info
EchoInfo(iteration_number);
// Updating the results stored in the database
UpdateDatabase(rA, rDx, rb, BaseType::MoveMeshFlag());
p_scheme->FinalizeNonLinIteration(r_model_part, rA, rDx, rb);
mpConvergenceCriteria->FinalizeNonLinearIteration(r_model_part, r_dof_set, rA, rDx, rb);
if (mStoreNonconvergedSolutionsFlag) {
Vector first;
GetCurrentSolution(r_dof_set,first);
NonconvergedSolutions.push_back(first);
}
if (is_converged) {
if (mpConvergenceCriteria->GetActualizeRHSflag()) {
TSparseSpace::SetToZero(rb);
p_builder_and_solver->BuildRHS(p_scheme, r_model_part, rb);
}
is_converged = mpConvergenceCriteria->PostCriteria(r_model_part, r_dof_set, rA, rDx, rb);
}
//Iteration Cycle... performed only for NonLinearProblems
while (is_converged == false &&
iteration_number++ < mMaxIterationNumber)
{
//setting the number of iteration
r_model_part.GetProcessInfo()[NL_ITERATION_NUMBER] = iteration_number;
p_scheme->InitializeNonLinIteration(r_model_part, rA, rDx, rb);
mpConvergenceCriteria->InitializeNonLinearIteration(r_model_part, r_dof_set, rA, rDx, rb);
is_converged = mpConvergenceCriteria->PreCriteria(r_model_part, r_dof_set, rA, rDx, rb);