From e083281f407c1ac9039f90e4300ac6f8899383c3 Mon Sep 17 00:00:00 2001 From: Christoph Schmidt Date: Tue, 16 Jun 2026 16:57:04 +0200 Subject: [PATCH 01/28] Fix build error on lnm cluster thought --- src/scatra/4C_scatra_functions.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scatra/4C_scatra_functions.hpp b/src/scatra/4C_scatra_functions.hpp index 95dff063c30..d8243ad1a8a 100644 --- a/src/scatra/4C_scatra_functions.hpp +++ b/src/scatra/4C_scatra_functions.hpp @@ -13,6 +13,7 @@ #include "4C_utils_function.hpp" #include "4C_utils_function_of_time.hpp" +#include FOUR_C_NAMESPACE_OPEN From 78b926b9599dd602295603c3c5bb4262a647bd34 Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Wed, 17 Jun 2026 17:10:26 +0200 Subject: [PATCH 02/28] feat: beaminteraction -> potential: add potential reduction functions --- .../4C_beaminteraction_potential_input.cpp | 7 + .../4C_beaminteraction_potential_input.hpp | 9 + ...nteraction_potential_pair_beam_to_beam.cpp | 61 +++- ...l_reduction_strategy_red_func_pol5.4C.yaml | 263 ++++++++++++++++++ ...l_reduction_strategy_red_func_pol7.4C.yaml | 263 ++++++++++++++++++ tests/list_of_tests.cmake | 2 + 6 files changed, 593 insertions(+), 12 deletions(-) create mode 100644 tests/input_files/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol5.4C.yaml create mode 100644 tests/input_files/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol7.4C.yaml diff --git a/src/beaminteraction/src/potential/4C_beaminteraction_potential_input.cpp b/src/beaminteraction/src/potential/4C_beaminteraction_potential_input.cpp index bf2d3baf5fd..65fb2e92eae 100644 --- a/src/beaminteraction/src/potential/4C_beaminteraction_potential_input.cpp +++ b/src/beaminteraction/src/potential/4C_beaminteraction_potential_input.cpp @@ -85,6 +85,13 @@ Core::IO::InputSpec BeamInteraction::Potential::valid_parameters() .validator = null_or(positive()), .store = in_struct(&BeamPotentialParameters::potential_reduction_length)}), + parameter("potential_reduction_function", + {.description = + "Function which describes the reduction of the potential at target beam end " + "points (only applicable in combination with potential reduction strategy).", + .default_value = ReductionFunction::cosine, + .store = in_struct(&BeamPotentialParameters::potential_reduction_function)}), + group("regularization", { parameter("type", diff --git a/src/beaminteraction/src/potential/4C_beaminteraction_potential_input.hpp b/src/beaminteraction/src/potential/4C_beaminteraction_potential_input.hpp index e76630146f5..7307113941d 100644 --- a/src/beaminteraction/src/potential/4C_beaminteraction_potential_input.hpp +++ b/src/beaminteraction/src/potential/4C_beaminteraction_potential_input.hpp @@ -77,6 +77,14 @@ namespace BeamInteraction::Potential bool write_uids{}; }; + /// function for potential reduction factor + enum class ReductionFunction + { + cosine, + polynomial_5, + polynomial_7 + }; + /// Beam potential parameters struct BeamPotentialParameters { @@ -92,6 +100,7 @@ namespace BeamInteraction::Potential bool automatic_differentiation = false; SourceTargetChoice choice_source_target{}; std::optional potential_reduction_length{}; + ReductionFunction potential_reduction_function{}; BeamPotentialVisualizationParameters runtime_output_params{}; // data container for prior element lengths for potential reduction strategy diff --git a/src/beaminteraction/src/potential/4C_beaminteraction_potential_pair_beam_to_beam.cpp b/src/beaminteraction/src/potential/4C_beaminteraction_potential_pair_beam_to_beam.cpp index d07ec1bc2dd..eeaad779f82 100644 --- a/src/beaminteraction/src/potential/4C_beaminteraction_potential_pair_beam_to_beam.cpp +++ b/src/beaminteraction/src/potential/4C_beaminteraction_potential_pair_beam_to_beam.cpp @@ -13,6 +13,7 @@ #include "4C_beaminteraction_potential_input.hpp" #include "4C_fem_general_largerotations.hpp" #include "4C_fem_general_utils_integration.hpp" +#include "4C_fem_general_utils_polynomial.hpp" #include "4C_global_data.hpp" #include "4C_io_input_parameter_container.hpp" #include "4C_linalg_fixedsizematrix.hpp" @@ -3410,27 +3411,63 @@ bool BeamInteraction::BeamToBeamPotentialPairpotential_reduction_function == + BeamInteraction::Potential::ReductionFunction::cosine) + { + potential_reduction_factor_GP = 0.5 - 0.5 * std::cos(std::numbers::pi * length_to_edge / + potential_reduction_length.value()); + pot_red_fac_deriv_l_edge = + 0.5 * std::numbers::pi / potential_reduction_length.value() * + std::sin(std::numbers::pi * length_to_edge / potential_reduction_length.value()); + pot_red_fac_2ndderiv_l_edge = + 0.5 * std::numbers::pi * std::numbers::pi / + (potential_reduction_length.value() * potential_reduction_length.value()) * + std::cos(std::numbers::pi * length_to_edge / potential_reduction_length.value()); + } + else if (params()->potential_reduction_function == + BeamInteraction::Potential::ReductionFunction::polynomial_5) + { + Core::FE::Polynomial polynomial = + Core::FE::Polynomial({0, 0, 0, 10 / std::pow(potential_reduction_length.value(), 3), + -15 / std::pow(potential_reduction_length.value(), 4), + 6 / std::pow(potential_reduction_length.value(), 5)}); + + potential_reduction_factor_GP = + polynomial.evaluate(Core::FADUtils::cast_to_double(length_to_edge)); + + pot_red_fac_deriv_l_edge = + polynomial.evaluate_derivative(Core::FADUtils::cast_to_double(length_to_edge), 1); + + pot_red_fac_2ndderiv_l_edge = + polynomial.evaluate_derivative(Core::FADUtils::cast_to_double(length_to_edge), 2); + } + else if (params()->potential_reduction_function == + BeamInteraction::Potential::ReductionFunction::polynomial_7) + { + Core::FE::Polynomial polynomial = + Core::FE::Polynomial({0, 0, 0, 0, 35 / std::pow(potential_reduction_length.value(), 4), + -84 / std::pow(potential_reduction_length.value(), 5), + 70 / std::pow(potential_reduction_length.value(), 6), + -20 / std::pow(potential_reduction_length.value(), 7)}); + + potential_reduction_factor_GP = + polynomial.evaluate(Core::FADUtils::cast_to_double(length_to_edge)); + pot_red_fac_deriv_l_edge = + polynomial.evaluate_derivative(Core::FADUtils::cast_to_double(length_to_edge), 1); + + pot_red_fac_2ndderiv_l_edge = + polynomial.evaluate_derivative(Core::FADUtils::cast_to_double(length_to_edge), 2); + } } l_edge_deriv_xi_target = 0.5 * ele2length_; diff --git a/tests/input_files/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol5.4C.yaml b/tests/input_files/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol5.4C.yaml new file mode 100644 index 00000000000..67f51c127cb --- /dev/null +++ b/tests/input_files/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol5.4C.yaml @@ -0,0 +1,263 @@ +TITLE: + - "Same setup as in `beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy.4C.yaml`" + - "but with the polynomial potential reduction function of order 5" +PROBLEM TYPE: + PROBLEMTYPE: "Structure" +IO: + STDOUTEVERY: 1000 + VERBOSITY: "Standard" +IO/MONITOR STRUCTURE DBC: + INTERVAL_STEPS: 1 + PRECISION_SCREEN: 3 + FILE_TYPE: csv +STRUCTURAL DYNAMIC: + DYNAMICTYPE: "Statics" + RESULTSEVERY: 100 + RESEVERYERGY: 1 + RESTARTEVERY: 100 + TIMESTEP: 0.1 + NUMSTEP: 10 + MAXTIME: 1 + TOLDISP: 1e-08 + TOLRES: 1e-06 + MAXITER: 15 + LINEAR_SOLVER: 1 +STRUCT NOX/Printing: + Inner Iteration: false + Outer Iteration StatusTest: false +SOLVER 1: + SOLVER: "UMFPACK" + NAME: "Structure_Solver" +BINNING STRATEGY: + BIN_SIZE_LOWER_BOUND: 5 + DOMAINBOUNDINGBOX: "-10.0 -10.0 -10.0 100.0 100.0 100.0" +BEAM INTERACTION: + REPARTITIONSTRATEGY: "Everydt" +beam_potential: + potential_law_exponents: [6.0] + potential_law_prefactors: [-1.0] + type: volume + strategy: single_length_specific_small_separations_simple + cutoff_radius: 100 + potential_reduction_length: 15 + potential_reduction_function: polynomial_5 +DESIGN POINT DIRICH CONDITIONS: + - E: 1 + NUMDOF: 9 + ONOFF: [1, 1, 1, 1, 1, 1, 1, 1, 1] + VAL: [0, 0, 0, 0, 0, 0, 0, 0, 0] + FUNCT: [0, 0, 0, 0, 0, 0, 0, 0, 0] + TAG: "monitor_reaction" + - E: 2 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 0] + FUNCT: [0, 0, 0] + - E: 3 + NUMDOF: 9 + ONOFF: [1, 1, 1, 1, 1, 1, 1, 1, 1] + VAL: [1, 1, 1, 0, 0, 0, 0, 0, 0] + FUNCT: [1, 1, 1, 0, 0, 0, 0, 0, 0] + TAG: "monitor_reaction" + - E: 4 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 0] + FUNCT: [0, 0, 0] +FUNCT1: + - SYMBOLIC_FUNCTION_OF_SPACE_TIME: "28.86751346*t" +DESIGN LINE BEAM POTENTIAL CHARGE CONDITIONS: + - E: 1 + POTLAW: 1 + VAL: 1 + - E: 2 + POTLAW: 1 + VAL: 1 +DNODE-NODE TOPOLOGY: + - "NODE 1 DNODE 1" + - "NODE 2 DNODE 2" + - "NODE 3 DNODE 1" + - "NODE 4 DNODE 2" + - "NODE 5 DNODE 1" + - "NODE 6 DNODE 2" + - "NODE 7 DNODE 1" + - "NODE 8 DNODE 2" + - "NODE 9 DNODE 1" + - "NODE 10 DNODE 2" + - "NODE 11 DNODE 1" + - "NODE 12 DNODE 2" + - "NODE 13 DNODE 1" + - "NODE 14 DNODE 2" + - "NODE 15 DNODE 1" + - "NODE 16 DNODE 2" + - "NODE 17 DNODE 1" + - "NODE 18 DNODE 2" + - "NODE 19 DNODE 1" + - "NODE 20 DNODE 2" + - "NODE 21 DNODE 1" + - "NODE 22 DNODE 3" + - "NODE 23 DNODE 4" + - "NODE 24 DNODE 3" + - "NODE 25 DNODE 4" + - "NODE 26 DNODE 3" + - "NODE 27 DNODE 4" + - "NODE 28 DNODE 3" + - "NODE 29 DNODE 4" + - "NODE 30 DNODE 3" + - "NODE 31 DNODE 4" + - "NODE 32 DNODE 3" + - "NODE 33 DNODE 4" + - "NODE 34 DNODE 3" + - "NODE 35 DNODE 4" + - "NODE 36 DNODE 3" + - "NODE 37 DNODE 4" + - "NODE 38 DNODE 3" + - "NODE 39 DNODE 4" + - "NODE 40 DNODE 3" + - "NODE 41 DNODE 4" + - "NODE 42 DNODE 3" +DLINE-NODE TOPOLOGY: + - "NODE 1 DLINE 1" + - "NODE 2 DLINE 1" + - "NODE 3 DLINE 1" + - "NODE 4 DLINE 1" + - "NODE 5 DLINE 1" + - "NODE 6 DLINE 1" + - "NODE 7 DLINE 1" + - "NODE 8 DLINE 1" + - "NODE 9 DLINE 1" + - "NODE 10 DLINE 1" + - "NODE 11 DLINE 1" + - "NODE 12 DLINE 1" + - "NODE 13 DLINE 1" + - "NODE 14 DLINE 1" + - "NODE 15 DLINE 1" + - "NODE 16 DLINE 1" + - "NODE 17 DLINE 1" + - "NODE 18 DLINE 1" + - "NODE 19 DLINE 1" + - "NODE 20 DLINE 1" + - "NODE 21 DLINE 1" + - "NODE 22 DLINE 2" + - "NODE 23 DLINE 2" + - "NODE 24 DLINE 2" + - "NODE 25 DLINE 2" + - "NODE 26 DLINE 2" + - "NODE 27 DLINE 2" + - "NODE 28 DLINE 2" + - "NODE 29 DLINE 2" + - "NODE 30 DLINE 2" + - "NODE 31 DLINE 2" + - "NODE 32 DLINE 2" + - "NODE 33 DLINE 2" + - "NODE 34 DLINE 2" + - "NODE 35 DLINE 2" + - "NODE 36 DLINE 2" + - "NODE 37 DLINE 2" + - "NODE 38 DLINE 2" + - "NODE 39 DLINE 2" + - "NODE 40 DLINE 2" + - "NODE 41 DLINE 2" + - "NODE 42 DLINE 2" +NODE COORDS: + - "NODE 1 COORD 0.00000000000000 0.00000000000000 0.00000000000000" + - "NODE 2 COORD 2.88675134594813 2.88675134594813 2.88675134594813" + - "NODE 3 COORD 5.77350269189626 5.77350269189626 5.77350269189626" + - "NODE 4 COORD 8.66025403784439 8.66025403784439 8.66025403784439" + - "NODE 5 COORD 11.54700538379252 11.54700538379252 11.54700538379252" + - "NODE 6 COORD 14.43375672974065 14.43375672974065 14.43375672974065" + - "NODE 7 COORD 17.32050807568877 17.32050807568877 17.32050807568877" + - "NODE 8 COORD 20.20725942163691 20.20725942163691 20.20725942163691" + - "NODE 9 COORD 23.09401076758503 23.09401076758503 23.09401076758503" + - "NODE 10 COORD 25.98076211353316 25.98076211353316 25.98076211353316" + - "NODE 11 COORD 28.86751345948129 28.86751345948129 28.86751345948129" + - "NODE 12 COORD 31.75426480542942 31.75426480542942 31.75426480542942" + - "NODE 13 COORD 34.64101615137755 34.64101615137755 34.64101615137755" + - "NODE 14 COORD 37.52776749732568 37.52776749732568 37.52776749732568" + - "NODE 15 COORD 40.41451884327381 40.41451884327381 40.41451884327381" + - "NODE 16 COORD 43.30127018922194 43.30127018922194 43.30127018922194" + - "NODE 17 COORD 46.18802153517007 46.18802153517007 46.18802153517007" + - "NODE 18 COORD 49.07477288111819 49.07477288111819 49.07477288111819" + - "NODE 19 COORD 51.96152422706633 51.96152422706633 51.96152422706633" + - "NODE 20 COORD 54.84827557301445 54.84827557301445 54.84827557301445" + - "NODE 21 COORD 57.73502691896258 57.73502691896258 57.73502691896258" + - "NODE 22 COORD -1.22474487139159 -1.22474487139159 2.44948974278318" + - "NODE 23 COORD 1.66200647455654 1.66200647455654 5.33624108873131" + - "NODE 24 COORD 4.54875782050467 4.54875782050467 8.22299243467944" + - "NODE 25 COORD 7.43550916645280 7.43550916645280 11.10974378062756" + - "NODE 26 COORD 10.32226051240093 10.32226051240093 13.99649512657570" + - "NODE 27 COORD 13.20901185834906 13.20901185834906 16.88324647252382" + - "NODE 28 COORD 16.09576320429719 16.09576320429719 19.76999781847195" + - "NODE 29 COORD 18.98251455024532 18.98251455024532 22.65674916442008" + - "NODE 30 COORD 21.86926589619344 21.86926589619344 25.54350051036821" + - "NODE 31 COORD 24.75601724214157 24.75601724214157 28.43025185631634" + - "NODE 32 COORD 27.64276858808970 27.64276858808970 31.31700320226447" + - "NODE 33 COORD 30.52951993403783 30.52951993403783 34.20375454821260" + - "NODE 34 COORD 33.41627127998596 33.41627127998596 37.09050589416073" + - "NODE 35 COORD 36.30302262593409 36.30302262593409 39.97725724010886" + - "NODE 36 COORD 39.18977397188223 39.18977397188223 42.86400858605699" + - "NODE 37 COORD 42.07652531783035 42.07652531783035 45.75075993200512" + - "NODE 38 COORD 44.96327666377848 44.96327666377848 48.63751127795324" + - "NODE 39 COORD 47.85002800972661 47.85002800972661 51.52426262390137" + - "NODE 40 COORD 50.73677935567474 50.73677935567474 54.41101396984951" + - "NODE 41 COORD 53.62353070162287 53.62353070162287 57.29776531579763" + - "NODE 42 COORD 56.51028204757100 56.51028204757100 60.18451666174576" +STRUCTURE ELEMENTS: + - "1 BEAM3R LINE3 1 3 2 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "2 BEAM3R LINE3 3 5 4 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "3 BEAM3R LINE3 5 7 6 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "4 BEAM3R LINE3 7 9 8 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "5 BEAM3R LINE3 9 11 10 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "6 BEAM3R LINE3 11 13 12 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "7 BEAM3R LINE3 13 15 14 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "8 BEAM3R LINE3 15 17 16 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "9 BEAM3R LINE3 17 19 18 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "10 BEAM3R LINE3 19 21 20 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "11 BEAM3R LINE3 22 24 23 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "12 BEAM3R LINE3 24 26 25 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "13 BEAM3R LINE3 26 28 27 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "14 BEAM3R LINE3 28 30 29 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "15 BEAM3R LINE3 30 32 31 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "16 BEAM3R LINE3 32 34 33 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "17 BEAM3R LINE3 34 36 35 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "18 BEAM3R LINE3 36 38 37 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "19 BEAM3R LINE3 38 40 39 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "20 BEAM3R LINE3 40 42 41 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" +MATERIALS: + - MAT: 1 + MAT_BeamReissnerElastHyper: + YOUNG: 5.4e+08 + POISSONRATIO: 0.3 + DENS: 1 + CROSSAREA: 3.1415 + SHEARCORR: 1 + MOMINPOL: 0.49702 + MOMIN2: 0.24851 + MOMIN3: 0.24851 + INTERACTIONRADIUS: 1 +RESULT DESCRIPTION: + - STRUCTURE: + SPECIAL: true + QUANTITY: "beam_interaction_potential" + VALUE: -17.4774707755639 + TOLERANCE: 1e-10 diff --git a/tests/input_files/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol7.4C.yaml b/tests/input_files/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol7.4C.yaml new file mode 100644 index 00000000000..15c741c2180 --- /dev/null +++ b/tests/input_files/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol7.4C.yaml @@ -0,0 +1,263 @@ +TITLE: + - "Same setup as in `beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy.4C.yaml`" + - "but with the polynomial potential reduction function of order 7" +PROBLEM TYPE: + PROBLEMTYPE: "Structure" +IO: + STDOUTEVERY: 1000 + VERBOSITY: "Standard" +IO/MONITOR STRUCTURE DBC: + INTERVAL_STEPS: 1 + PRECISION_SCREEN: 3 + FILE_TYPE: csv +STRUCTURAL DYNAMIC: + DYNAMICTYPE: "Statics" + RESULTSEVERY: 100 + RESEVERYERGY: 1 + RESTARTEVERY: 100 + TIMESTEP: 0.1 + NUMSTEP: 10 + MAXTIME: 1 + TOLDISP: 1e-08 + TOLRES: 1e-06 + MAXITER: 15 + LINEAR_SOLVER: 1 +STRUCT NOX/Printing: + Inner Iteration: false + Outer Iteration StatusTest: false +SOLVER 1: + SOLVER: "UMFPACK" + NAME: "Structure_Solver" +BINNING STRATEGY: + BIN_SIZE_LOWER_BOUND: 5 + DOMAINBOUNDINGBOX: "-10.0 -10.0 -10.0 100.0 100.0 100.0" +BEAM INTERACTION: + REPARTITIONSTRATEGY: "Everydt" +beam_potential: + potential_law_exponents: [6.0] + potential_law_prefactors: [-1.0] + type: volume + strategy: single_length_specific_small_separations_simple + cutoff_radius: 100 + potential_reduction_length: 15 + potential_reduction_function: polynomial_7 +DESIGN POINT DIRICH CONDITIONS: + - E: 1 + NUMDOF: 9 + ONOFF: [1, 1, 1, 1, 1, 1, 1, 1, 1] + VAL: [0, 0, 0, 0, 0, 0, 0, 0, 0] + FUNCT: [0, 0, 0, 0, 0, 0, 0, 0, 0] + TAG: "monitor_reaction" + - E: 2 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 0] + FUNCT: [0, 0, 0] + - E: 3 + NUMDOF: 9 + ONOFF: [1, 1, 1, 1, 1, 1, 1, 1, 1] + VAL: [1, 1, 1, 0, 0, 0, 0, 0, 0] + FUNCT: [1, 1, 1, 0, 0, 0, 0, 0, 0] + TAG: "monitor_reaction" + - E: 4 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 0] + FUNCT: [0, 0, 0] +FUNCT1: + - SYMBOLIC_FUNCTION_OF_SPACE_TIME: "28.86751346*t" +DESIGN LINE BEAM POTENTIAL CHARGE CONDITIONS: + - E: 1 + POTLAW: 1 + VAL: 1 + - E: 2 + POTLAW: 1 + VAL: 1 +DNODE-NODE TOPOLOGY: + - "NODE 1 DNODE 1" + - "NODE 2 DNODE 2" + - "NODE 3 DNODE 1" + - "NODE 4 DNODE 2" + - "NODE 5 DNODE 1" + - "NODE 6 DNODE 2" + - "NODE 7 DNODE 1" + - "NODE 8 DNODE 2" + - "NODE 9 DNODE 1" + - "NODE 10 DNODE 2" + - "NODE 11 DNODE 1" + - "NODE 12 DNODE 2" + - "NODE 13 DNODE 1" + - "NODE 14 DNODE 2" + - "NODE 15 DNODE 1" + - "NODE 16 DNODE 2" + - "NODE 17 DNODE 1" + - "NODE 18 DNODE 2" + - "NODE 19 DNODE 1" + - "NODE 20 DNODE 2" + - "NODE 21 DNODE 1" + - "NODE 22 DNODE 3" + - "NODE 23 DNODE 4" + - "NODE 24 DNODE 3" + - "NODE 25 DNODE 4" + - "NODE 26 DNODE 3" + - "NODE 27 DNODE 4" + - "NODE 28 DNODE 3" + - "NODE 29 DNODE 4" + - "NODE 30 DNODE 3" + - "NODE 31 DNODE 4" + - "NODE 32 DNODE 3" + - "NODE 33 DNODE 4" + - "NODE 34 DNODE 3" + - "NODE 35 DNODE 4" + - "NODE 36 DNODE 3" + - "NODE 37 DNODE 4" + - "NODE 38 DNODE 3" + - "NODE 39 DNODE 4" + - "NODE 40 DNODE 3" + - "NODE 41 DNODE 4" + - "NODE 42 DNODE 3" +DLINE-NODE TOPOLOGY: + - "NODE 1 DLINE 1" + - "NODE 2 DLINE 1" + - "NODE 3 DLINE 1" + - "NODE 4 DLINE 1" + - "NODE 5 DLINE 1" + - "NODE 6 DLINE 1" + - "NODE 7 DLINE 1" + - "NODE 8 DLINE 1" + - "NODE 9 DLINE 1" + - "NODE 10 DLINE 1" + - "NODE 11 DLINE 1" + - "NODE 12 DLINE 1" + - "NODE 13 DLINE 1" + - "NODE 14 DLINE 1" + - "NODE 15 DLINE 1" + - "NODE 16 DLINE 1" + - "NODE 17 DLINE 1" + - "NODE 18 DLINE 1" + - "NODE 19 DLINE 1" + - "NODE 20 DLINE 1" + - "NODE 21 DLINE 1" + - "NODE 22 DLINE 2" + - "NODE 23 DLINE 2" + - "NODE 24 DLINE 2" + - "NODE 25 DLINE 2" + - "NODE 26 DLINE 2" + - "NODE 27 DLINE 2" + - "NODE 28 DLINE 2" + - "NODE 29 DLINE 2" + - "NODE 30 DLINE 2" + - "NODE 31 DLINE 2" + - "NODE 32 DLINE 2" + - "NODE 33 DLINE 2" + - "NODE 34 DLINE 2" + - "NODE 35 DLINE 2" + - "NODE 36 DLINE 2" + - "NODE 37 DLINE 2" + - "NODE 38 DLINE 2" + - "NODE 39 DLINE 2" + - "NODE 40 DLINE 2" + - "NODE 41 DLINE 2" + - "NODE 42 DLINE 2" +NODE COORDS: + - "NODE 1 COORD 0.00000000000000 0.00000000000000 0.00000000000000" + - "NODE 2 COORD 2.88675134594813 2.88675134594813 2.88675134594813" + - "NODE 3 COORD 5.77350269189626 5.77350269189626 5.77350269189626" + - "NODE 4 COORD 8.66025403784439 8.66025403784439 8.66025403784439" + - "NODE 5 COORD 11.54700538379252 11.54700538379252 11.54700538379252" + - "NODE 6 COORD 14.43375672974065 14.43375672974065 14.43375672974065" + - "NODE 7 COORD 17.32050807568877 17.32050807568877 17.32050807568877" + - "NODE 8 COORD 20.20725942163691 20.20725942163691 20.20725942163691" + - "NODE 9 COORD 23.09401076758503 23.09401076758503 23.09401076758503" + - "NODE 10 COORD 25.98076211353316 25.98076211353316 25.98076211353316" + - "NODE 11 COORD 28.86751345948129 28.86751345948129 28.86751345948129" + - "NODE 12 COORD 31.75426480542942 31.75426480542942 31.75426480542942" + - "NODE 13 COORD 34.64101615137755 34.64101615137755 34.64101615137755" + - "NODE 14 COORD 37.52776749732568 37.52776749732568 37.52776749732568" + - "NODE 15 COORD 40.41451884327381 40.41451884327381 40.41451884327381" + - "NODE 16 COORD 43.30127018922194 43.30127018922194 43.30127018922194" + - "NODE 17 COORD 46.18802153517007 46.18802153517007 46.18802153517007" + - "NODE 18 COORD 49.07477288111819 49.07477288111819 49.07477288111819" + - "NODE 19 COORD 51.96152422706633 51.96152422706633 51.96152422706633" + - "NODE 20 COORD 54.84827557301445 54.84827557301445 54.84827557301445" + - "NODE 21 COORD 57.73502691896258 57.73502691896258 57.73502691896258" + - "NODE 22 COORD -1.22474487139159 -1.22474487139159 2.44948974278318" + - "NODE 23 COORD 1.66200647455654 1.66200647455654 5.33624108873131" + - "NODE 24 COORD 4.54875782050467 4.54875782050467 8.22299243467944" + - "NODE 25 COORD 7.43550916645280 7.43550916645280 11.10974378062756" + - "NODE 26 COORD 10.32226051240093 10.32226051240093 13.99649512657570" + - "NODE 27 COORD 13.20901185834906 13.20901185834906 16.88324647252382" + - "NODE 28 COORD 16.09576320429719 16.09576320429719 19.76999781847195" + - "NODE 29 COORD 18.98251455024532 18.98251455024532 22.65674916442008" + - "NODE 30 COORD 21.86926589619344 21.86926589619344 25.54350051036821" + - "NODE 31 COORD 24.75601724214157 24.75601724214157 28.43025185631634" + - "NODE 32 COORD 27.64276858808970 27.64276858808970 31.31700320226447" + - "NODE 33 COORD 30.52951993403783 30.52951993403783 34.20375454821260" + - "NODE 34 COORD 33.41627127998596 33.41627127998596 37.09050589416073" + - "NODE 35 COORD 36.30302262593409 36.30302262593409 39.97725724010886" + - "NODE 36 COORD 39.18977397188223 39.18977397188223 42.86400858605699" + - "NODE 37 COORD 42.07652531783035 42.07652531783035 45.75075993200512" + - "NODE 38 COORD 44.96327666377848 44.96327666377848 48.63751127795324" + - "NODE 39 COORD 47.85002800972661 47.85002800972661 51.52426262390137" + - "NODE 40 COORD 50.73677935567474 50.73677935567474 54.41101396984951" + - "NODE 41 COORD 53.62353070162287 53.62353070162287 57.29776531579763" + - "NODE 42 COORD 56.51028204757100 56.51028204757100 60.18451666174576" +STRUCTURE ELEMENTS: + - "1 BEAM3R LINE3 1 3 2 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "2 BEAM3R LINE3 3 5 4 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "3 BEAM3R LINE3 5 7 6 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "4 BEAM3R LINE3 7 9 8 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "5 BEAM3R LINE3 9 11 10 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "6 BEAM3R LINE3 11 13 12 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "7 BEAM3R LINE3 13 15 14 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "8 BEAM3R LINE3 15 17 16 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "9 BEAM3R LINE3 17 19 18 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "10 BEAM3R LINE3 19 21 20 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "11 BEAM3R LINE3 22 24 23 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "12 BEAM3R LINE3 24 26 25 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "13 BEAM3R LINE3 26 28 27 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "14 BEAM3R LINE3 28 30 29 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "15 BEAM3R LINE3 30 32 31 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "16 BEAM3R LINE3 32 34 33 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "17 BEAM3R LINE3 34 36 35 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "18 BEAM3R LINE3 36 38 37 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "19 BEAM3R LINE3 38 40 39 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" + - "20 BEAM3R LINE3 40 42 41 MAT 1 TRIADS 0.0 -0.675510858856040 0.675510858856040 0.0 -0.675510858856040 + 0.675510858856040 0.0 -0.675510858856040 0.675510858856040 HERMITE_CENTERLINE true" +MATERIALS: + - MAT: 1 + MAT_BeamReissnerElastHyper: + YOUNG: 5.4e+08 + POISSONRATIO: 0.3 + DENS: 1 + CROSSAREA: 3.1415 + SHEARCORR: 1 + MOMINPOL: 0.49702 + MOMIN2: 0.24851 + MOMIN3: 0.24851 + INTERACTIONRADIUS: 1 +RESULT DESCRIPTION: + - STRUCTURE: + SPECIAL: true + QUANTITY: "beam_interaction_potential" + VALUE: -17.4774266763426 + TOLERANCE: 1e-10 diff --git a/tests/list_of_tests.cmake b/tests/list_of_tests.cmake index 851d5240350..54bd016c798 100644 --- a/tests/list_of_tests.cmake +++ b/tests/list_of_tests.cmake @@ -135,6 +135,8 @@ four_c_test(TEST_FILE beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapp __four_c_test_add_csv_yaml_comparison(BASED_ON ${current} RESULT_FILE xxx-101_monitor_dbc.csv REFERENCE_FILE ref/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_dbc_monitor_101.csv TOL_R 0.0 TOL_A 1e-10) four_c_test(TEST_FILE beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy.4C.yaml NP 2 RETURN_AS current) __four_c_test_add_csv_yaml_comparison(BASED_ON ${current} RESULT_FILE xxx-101_monitor_dbc.csv REFERENCE_FILE ref/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_dbc_monitor_101.csv TOL_R 0.0 TOL_A 1e-10) +four_c_test(TEST_FILE beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol5.4C.yaml NP 2) +four_c_test(TEST_FILE beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_red_func_pol7.4C.yaml NP 2) four_c_test(TEST_FILE beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_two_half_pass.4C.yaml NP 1 RETURN_AS current) __four_c_test_add_csv_yaml_comparison(BASED_ON ${current} RESULT_FILE xxx-101_monitor_dbc.csv REFERENCE_FILE ref/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_two_half_pass/beams-101_monitor_dbc.csv TOL_R 0.0 TOL_A 1e-10) __four_c_test_add_csv_yaml_comparison(BASED_ON ${current} RESULT_FILE xxx-102_monitor_dbc.csv REFERENCE_FILE ref/beam3r_herm2line3_static_vdW_singlelengthsspec_smallsepapprox_simple_end_point_potential_reduction_strategy_two_half_pass/beams-102_monitor_dbc.csv TOL_R 0.0 TOL_A 1e-10) From 3893f7f67e3a05687add3c398dddc295d0431289 Mon Sep 17 00:00:00 2001 From: Christoph Schmidt Date: Wed, 17 Jun 2026 16:23:58 +0200 Subject: [PATCH 03/28] Update the lnm cluster presets to actual current capabilities at the cluster bruteforce. --- presets/lnm/cluster/CMakePresets.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presets/lnm/cluster/CMakePresets.json b/presets/lnm/cluster/CMakePresets.json index b187ae3f450..5dd7bfdd79c 100644 --- a/presets/lnm/cluster/CMakePresets.json +++ b/presets/lnm/cluster/CMakePresets.json @@ -26,8 +26,8 @@ ], "cacheVariables": { "FOUR_C_TRILINOS_ROOT": "/lnm/packages/trilinos/2025-6/release", + "FOUR_C_WITH_PYTHON": "OFF", "FOUR_C_BOOST_ROOT": "/cluster/lib/gcc/9.1.0/boost_1_86_0", - "FOUR_C_PYTHON_ROOT": "/lnm/miniconda3/envs/python_3_12_env/bin", "FOUR_C_VTK_ROOT": "/lnm/packages/vtk/9-5-2/release" } }, From 38e152c001226558487fb69baaf3ff4d0ca87199 Mon Sep 17 00:00:00 2001 From: Maximilian Ludwig Date: Thu, 18 Jun 2026 10:00:14 +0200 Subject: [PATCH 04/28] Fix sign in 4 ele Maxwell residual --- .../terminal_units/4C_reduced_lung_terminal_unit_rheology.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reduced_lung/src/terminal_units/4C_reduced_lung_terminal_unit_rheology.cpp b/src/reduced_lung/src/terminal_units/4C_reduced_lung_terminal_unit_rheology.cpp index 5c453abe39f..1d7cdc72b3e 100644 --- a/src/reduced_lung/src/terminal_units/4C_reduced_lung_terminal_unit_rheology.cpp +++ b/src/reduced_lung/src/terminal_units/4C_reduced_lung_terminal_unit_rheology.cpp @@ -60,7 +60,7 @@ namespace ReducedLung::TerminalUnits::Rheology (four_element_maxwell_model.elasticity_E_m[i] * dt + four_element_maxwell_model.viscosity_eta_m[i])) / data.reference_volume_v0[i] * - locally_relevant_dofs.local_values_as_span()[data.lid_q[i]] + + locally_relevant_dofs.local_values_as_span()[data.lid_q[i]] - four_element_maxwell_model.viscosity_eta_m[i] / (four_element_maxwell_model.elasticity_E_m[i] * dt + four_element_maxwell_model.viscosity_eta_m[i]) * From be948f892c076d02ee4afff97277de9b12eeded9 Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Mon, 15 Jun 2026 11:05:15 +0200 Subject: [PATCH 05/28] Remove unused AAA-related functions --- src/mat/4C_mat_aaaneohooke.cpp | 2 +- src/mat/4C_mat_aaaneohooke.hpp | 9 --------- src/mat/4C_mat_elasthyper.cpp | 11 ----------- src/mat/4C_mat_elasthyper.hpp | 3 --- .../4C_mat_elast_anisoactivestress_evolution.hpp | 3 --- .../elast/4C_mat_elast_coupanisoneohooke_VarProp.hpp | 3 --- src/mat/elast/4C_mat_elast_summand.hpp | 3 --- 7 files changed, 1 insertion(+), 33 deletions(-) diff --git a/src/mat/4C_mat_aaaneohooke.cpp b/src/mat/4C_mat_aaaneohooke.cpp index 48457c2054c..0c82cef0df3 100644 --- a/src/mat/4C_mat_aaaneohooke.cpp +++ b/src/mat/4C_mat_aaaneohooke.cpp @@ -387,4 +387,4 @@ bool Mat::AAAneohooke::vis_data( return true; } -FOUR_C_NAMESPACE_CLOSE +FOUR_C_NAMESPACE_CLOSE \ No newline at end of file diff --git a/src/mat/4C_mat_aaaneohooke.hpp b/src/mat/4C_mat_aaaneohooke.hpp index 7df8f9ab839..281e928e4a8 100644 --- a/src/mat/4C_mat_aaaneohooke.hpp +++ b/src/mat/4C_mat_aaaneohooke.hpp @@ -152,17 +152,8 @@ namespace Mat //@} /// material mass density - // virtual double Density() const { return params_->GetDensity(); } double density() const override { return params_->get_parameter(params_->density, -1); } - /// shear modulus - // double shear_mod() const { return 0.5*params_->GetYoungs(-1)/(1.0+params_->GetNue()); } - double shear_mod() const - { - return 0.5 * params_->get_parameter(params_->young, -1) / - (1.0 + params_->get_parameter(params_->nue, -1)); - } - // material type Core::Materials::MaterialType material_type() const override { diff --git a/src/mat/4C_mat_elasthyper.cpp b/src/mat/4C_mat_elasthyper.cpp index 288c103a009..c9a828defb7 100644 --- a/src/mat/4C_mat_elasthyper.cpp +++ b/src/mat/4C_mat_elasthyper.cpp @@ -224,17 +224,6 @@ double Mat::ElastHyper::get_young() return young; } -/*----------------------------------------------------------------------*/ -/*----------------------------------------------------------------------*/ -void Mat::ElastHyper::setup_aaa(const Teuchos::ParameterList& params, const int eleGID) -{ - // loop map of associated potential summands - for (auto& p : potsum_) - { - p->setup_aaa(params, eleGID); - } -} - /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ void Mat::ElastHyper::setup(int numgp, const Discret::Elements::Fibers& fibers, diff --git a/src/mat/4C_mat_elasthyper.hpp b/src/mat/4C_mat_elasthyper.hpp index 33c499a60f7..4d8d7895ac8 100644 --- a/src/mat/4C_mat_elasthyper.hpp +++ b/src/mat/4C_mat_elasthyper.hpp @@ -311,9 +311,6 @@ namespace Mat /// update void update() override; - /// setup patient-specific AAA stuff - virtual void setup_aaa(const Teuchos::ParameterList& params, int eleGID); - /// return if anisotropic not split formulation virtual bool anisotropic_principal() const { return summandProperties_.anisoprinc; } diff --git a/src/mat/elast/4C_mat_elast_anisoactivestress_evolution.hpp b/src/mat/elast/4C_mat_elast_anisoactivestress_evolution.hpp index 7fd7fb0ff8a..201e2f5fd82 100644 --- a/src/mat/elast/4C_mat_elast_anisoactivestress_evolution.hpp +++ b/src/mat/elast/4C_mat_elast_anisoactivestress_evolution.hpp @@ -183,9 +183,6 @@ namespace Mat std::vector>& fibervecs ///< vector of all fiber vectors ) const override; - /// Setup of patient-specific materials - void setup_aaa(const Teuchos::ParameterList& params, const int eleGID) override {} - // update internal stress variables void update() override; diff --git a/src/mat/elast/4C_mat_elast_coupanisoneohooke_VarProp.hpp b/src/mat/elast/4C_mat_elast_coupanisoneohooke_VarProp.hpp index e9e286bb660..8d955c53a40 100644 --- a/src/mat/elast/4C_mat_elast_coupanisoneohooke_VarProp.hpp +++ b/src/mat/elast/4C_mat_elast_coupanisoneohooke_VarProp.hpp @@ -138,9 +138,6 @@ namespace Mat std::vector>& fibervecs ///< vector of all fiber vectors ) const override; - /// Setup of patient-specific materials - void setup_aaa(const Teuchos::ParameterList& params, const int eleGID) override { return; } - /// Indicator for formulation void specify_formulation( bool& isoprinc, ///< global indicator for isotropic principal formulation diff --git a/src/mat/elast/4C_mat_elast_summand.hpp b/src/mat/elast/4C_mat_elast_summand.hpp index 8e106bc5eac..0295ff2d7f8 100644 --- a/src/mat/elast/4C_mat_elast_summand.hpp +++ b/src/mat/elast/4C_mat_elast_summand.hpp @@ -113,9 +113,6 @@ namespace Mat virtual void setup(int numgp, const Discret::Elements::Fibers& fibers, const std::optional& coord_system) {}; - //! Dummy routine for setup of patient-specific materials - virtual void setup_aaa(const Teuchos::ParameterList& params, const int eleGID) {}; - /*! * @brief Post setup routine for summands. It will be called once after everything is set up. * From c50940ef7141b8ccbbbbb8f510ff36dfe44557bb Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Mon, 15 Jun 2026 12:13:32 +0200 Subject: [PATCH 06/28] Remove unused elasthyper functions --- src/mat/4C_mat_elasthyper.cpp | 15 --------------- src/mat/4C_mat_elasthyper.hpp | 3 --- .../4C_mat_elast_coupSaintVenantKirchhoff.hpp | 8 -------- src/mat/elast/4C_mat_elast_coupblatzko.hpp | 6 ------ src/mat/elast/4C_mat_elast_coupneohooke.hpp | 6 ------ src/mat/elast/4C_mat_elast_summand.hpp | 6 ------ 6 files changed, 44 deletions(-) diff --git a/src/mat/4C_mat_elasthyper.cpp b/src/mat/4C_mat_elasthyper.cpp index c9a828defb7..cac496cb24e 100644 --- a/src/mat/4C_mat_elasthyper.cpp +++ b/src/mat/4C_mat_elasthyper.cpp @@ -209,21 +209,6 @@ double Mat::ElastHyper::shear_mod(int ele_gid) const return shearmod; } -/*----------------------------------------------------------------------*/ -/*----------------------------------------------------------------------*/ -double Mat::ElastHyper::get_young() -{ - double young; - double shear; - double bulk; - young = shear = bulk = 0.; - for (auto& p : potsum_) p->add_youngs_mod(young, shear, bulk); - - if (bulk != 0. || shear != 0.) young += 9. * bulk * shear / (3. * bulk + shear); - - return young; -} - /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ void Mat::ElastHyper::setup(int numgp, const Discret::Elements::Fibers& fibers, diff --git a/src/mat/4C_mat_elasthyper.hpp b/src/mat/4C_mat_elasthyper.hpp index 4d8d7895ac8..69adbaf6de4 100644 --- a/src/mat/4C_mat_elasthyper.hpp +++ b/src/mat/4C_mat_elasthyper.hpp @@ -208,9 +208,6 @@ namespace Mat /// a shear modulus equivalent virtual double shear_mod(int ele_gid) const; - /// a young's modulus equivalent - virtual double get_young(); - /// evaluate strain energy function [[nodiscard]] double strain_energy(const Core::LinAlg::SymmetricTensor& glstrain, const EvaluationContext<3>& context, int gp, diff --git a/src/mat/elast/4C_mat_elast_coupSaintVenantKirchhoff.hpp b/src/mat/elast/4C_mat_elast_coupSaintVenantKirchhoff.hpp index 31ab8e139fe..484b39a81d0 100644 --- a/src/mat/elast/4C_mat_elast_coupSaintVenantKirchhoff.hpp +++ b/src/mat/elast/4C_mat_elast_coupSaintVenantKirchhoff.hpp @@ -123,14 +123,6 @@ namespace Mat return; }; - - /// a young's modulus equivalent - void add_youngs_mod(double& young, double& shear, double& bulk) override - { - young += 9. * params_->mue_ * (3. * params_->lambda_ + 2. * params_->mue_) / - (params_->lambda_ + params_->mue_); - }; - private: /// my material parameters Mat::Elastic::PAR::CoupSVK* params_; diff --git a/src/mat/elast/4C_mat_elast_coupblatzko.hpp b/src/mat/elast/4C_mat_elast_coupblatzko.hpp index c756c36af4f..cb41dcaa162 100644 --- a/src/mat/elast/4C_mat_elast_coupblatzko.hpp +++ b/src/mat/elast/4C_mat_elast_coupblatzko.hpp @@ -125,12 +125,6 @@ namespace Mat void add_coup_deriv_vol( const double j, double* dPj1, double* dPj2, double* dPj3, double* dPj4) override; - /// add young's modulus equivalent - void add_youngs_mod(double& young, double& shear, double& bulk) override - { - young += 2. * mue() * (1. + nue()); - }; - /// @name Access methods //@{ double mue() const { return params_->mue_; } diff --git a/src/mat/elast/4C_mat_elast_coupneohooke.hpp b/src/mat/elast/4C_mat_elast_coupneohooke.hpp index a7d2ede3d0c..0d900d8190f 100644 --- a/src/mat/elast/4C_mat_elast_coupneohooke.hpp +++ b/src/mat/elast/4C_mat_elast_coupneohooke.hpp @@ -108,12 +108,6 @@ namespace Mat int ele_gid ///< element GID ) const override; - /// add young's modulus equivalent - void add_youngs_mod(double& young, double& shear, double& bulk) override - { - young += youngs(); - }; - //@} // add strain energy diff --git a/src/mat/elast/4C_mat_elast_summand.hpp b/src/mat/elast/4C_mat_elast_summand.hpp index 0295ff2d7f8..e7ab214339b 100644 --- a/src/mat/elast/4C_mat_elast_summand.hpp +++ b/src/mat/elast/4C_mat_elast_summand.hpp @@ -144,12 +144,6 @@ namespace Mat int ele_gid ///< element GID ) const; - //! add young's modulus equivalent - virtual void add_youngs_mod(double& young, double& shear, double& bulk) - { - FOUR_C_THROW("Summand does not support calculation of youngs modulus"); - }; - /*! * @brief retrieve coefficients of first and second derivative of summand with respect to *principal invariants From c6378d319f603e8ee532def321b54c002cbf5d5f Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Mon, 15 Jun 2026 12:22:36 +0200 Subject: [PATCH 07/28] Inline elasthyper member functions and rewrite loops --- src/mat/4C_mat_elasthyper.cpp | 24 +++++++++---------- src/mat/4C_mat_elasthyper.hpp | 14 ++++------- .../elast/4C_mat_elast_couplogmixneohooke.cpp | 11 --------- .../elast/4C_mat_elast_couplogmixneohooke.hpp | 7 ++++-- .../elast/4C_mat_elast_couplogneohooke.cpp | 11 --------- .../elast/4C_mat_elast_couplogneohooke.hpp | 6 ++++- src/mat/elast/4C_mat_elast_coupneohooke.cpp | 11 --------- src/mat/elast/4C_mat_elast_coupneohooke.hpp | 6 ++++- src/mat/elast/4C_mat_elast_coupvarga.cpp | 13 ---------- src/mat/elast/4C_mat_elast_coupvarga.hpp | 9 ++++++- src/mat/elast/4C_mat_elast_isoneohooke.cpp | 8 ------- src/mat/elast/4C_mat_elast_isoneohooke.hpp | 8 +++++-- src/mat/elast/4C_mat_elast_isovarga.cpp | 9 ------- src/mat/elast/4C_mat_elast_isovarga.hpp | 9 ++++++- src/mat/elast/4C_mat_elast_summand.cpp | 9 ++----- src/mat/elast/4C_mat_elast_summand.hpp | 7 +++++- 16 files changed, 60 insertions(+), 102 deletions(-) diff --git a/src/mat/4C_mat_elasthyper.cpp b/src/mat/4C_mat_elasthyper.cpp index cac496cb24e..245f406aa95 100644 --- a/src/mat/4C_mat_elasthyper.cpp +++ b/src/mat/4C_mat_elasthyper.cpp @@ -78,14 +78,13 @@ Mat::ElastHyper::ElastHyper(Mat::PAR::ElastHyper* params) : summandProperties_(), params_(params), potsum_(0), anisotropy_() { // make sure the referenced materials in material list have quick access parameters - std::vector::const_iterator m; - for (m = params_->matids_.begin(); m != params_->matids_.end(); ++m) + for (const int matid : params_->matids_) { - const int matid = *m; - std::shared_ptr sum = Mat::Elastic::Summand::factory(matid); - if (sum == nullptr) FOUR_C_THROW("Failed to allocate"); - potsum_.push_back(sum); + auto sum = Mat::Elastic::Summand::factory(matid); + if (!sum) FOUR_C_THROW("Failed to allocate material summand for matid %d", matid); + sum->register_anisotropy_extensions(anisotropy_); + potsum_.push_back(std::move(sum)); } } @@ -150,7 +149,6 @@ void Mat::ElastHyper::unpack(Core::Communication::UnpackBuffer& buffer) summandProperties_.unpack(buffer); - // Pack anisotropy anisotropy_.unpack_anisotropy(buffer); Core::Communication::PotentiallyUnusedBufferScope potsum_scope(buffer); @@ -158,13 +156,13 @@ void Mat::ElastHyper::unpack(Core::Communication::UnpackBuffer& buffer) if (params_ != nullptr) // summands are not accessible in postprocessing mode { // make sure the referenced materials in material list have quick access parameters - std::vector::const_iterator m; - for (m = params_->matids_.begin(); m != params_->matids_.end(); ++m) + for (const int matid : params_->matids_) { - const int summand_matid = *m; - std::shared_ptr sum = Mat::Elastic::Summand::factory(summand_matid); - if (sum == nullptr) FOUR_C_THROW("Failed to allocate"); - potsum_.push_back(sum); + auto sum = Mat::Elastic::Summand::factory(matid); + + if (!sum) FOUR_C_THROW("Failed to allocate Elastic::Summand for matid %d", matid); + + potsum_.push_back(std::move(sum)); } // loop map of associated potential summands diff --git a/src/mat/4C_mat_elasthyper.hpp b/src/mat/4C_mat_elasthyper.hpp index 69adbaf6de4..fefa492be6f 100644 --- a/src/mat/4C_mat_elasthyper.hpp +++ b/src/mat/4C_mat_elasthyper.hpp @@ -53,12 +53,6 @@ namespace Mat /// @name material parameters //@{ - - // /// provide access to material/summand by its ID - // std::shared_ptr MaterialById( - // const int id ///< ID to look for in collection of summands - // ) const; - /// length of material list const int nummat_; @@ -192,7 +186,7 @@ namespace Mat } /// number of materials - virtual int num_mat() const { return params_->nummat_; } + [[nodiscard]] virtual int num_mat() const { return params_->nummat_; } /*! * @brief deliver material ID of index i'th potential summand in collection @@ -200,13 +194,13 @@ namespace Mat * @param(in) index index * @return material id */ - virtual int mat_id(unsigned index) const; + [[nodiscard]] virtual int mat_id(unsigned index) const; /// material mass density - double density() const override { return params_->density_; } + [[nodiscard]] double density() const override { return params_->density_; } /// a shear modulus equivalent - virtual double shear_mod(int ele_gid) const; + [[nodiscard]] virtual double shear_mod(int ele_gid) const; /// evaluate strain energy function [[nodiscard]] double strain_energy(const Core::LinAlg::SymmetricTensor& glstrain, diff --git a/src/mat/elast/4C_mat_elast_couplogmixneohooke.cpp b/src/mat/elast/4C_mat_elast_couplogmixneohooke.cpp index 77afcbf4c11..cfd9adc38c6 100644 --- a/src/mat/elast/4C_mat_elast_couplogmixneohooke.cpp +++ b/src/mat/elast/4C_mat_elast_couplogmixneohooke.cpp @@ -46,17 +46,6 @@ Mat::Elastic::CoupLogMixNeoHooke::CoupLogMixNeoHooke(Mat::Elastic::PAR::CoupLogM { } -void Mat::Elastic::CoupLogMixNeoHooke::add_shear_mod( - bool& haveshearmod, ///< non-zero shear modulus was added - double& shearmod, ///< variable to add upon - int ele_gid ///< element GID -) const -{ - haveshearmod = true; - - shearmod += params_->mue_; -} - void Mat::Elastic::CoupLogMixNeoHooke::add_strain_energy(double& psi, const Core::LinAlg::Matrix<3, 1>& prinv, const Core::LinAlg::Matrix<3, 1>& modinv, const Core::LinAlg::SymmetricTensor& glstrain, const int gp, const int eleGID) diff --git a/src/mat/elast/4C_mat_elast_couplogmixneohooke.hpp b/src/mat/elast/4C_mat_elast_couplogmixneohooke.hpp index fd87f54b4ce..3f9c4cc8f39 100644 --- a/src/mat/elast/4C_mat_elast_couplogmixneohooke.hpp +++ b/src/mat/elast/4C_mat_elast_couplogmixneohooke.hpp @@ -81,12 +81,15 @@ namespace Mat { return Core::Materials::mes_couplogmixneohooke; } - /// add shear modulus equivalent void add_shear_mod(bool& haveshearmod, ///< non-zero shear modulus was added double& shearmod, ///< variable to add upon int ele_gid ///< element GID - ) const override; + ) const override + { + haveshearmod = true; + shearmod += params_->mue_; + }; //@} diff --git a/src/mat/elast/4C_mat_elast_couplogneohooke.cpp b/src/mat/elast/4C_mat_elast_couplogneohooke.cpp index f4d623fa311..95fcd97a6c2 100644 --- a/src/mat/elast/4C_mat_elast_couplogneohooke.cpp +++ b/src/mat/elast/4C_mat_elast_couplogneohooke.cpp @@ -45,17 +45,6 @@ Mat::Elastic::CoupLogNeoHooke::CoupLogNeoHooke(Mat::Elastic::PAR::CoupLogNeoHook { } -void Mat::Elastic::CoupLogNeoHooke::add_shear_mod( - bool& haveshearmod, ///< non-zero shear modulus was added - double& shearmod, ///< variable to add upon - int ele_gid ///< element GID -) const -{ - haveshearmod = true; - - shearmod += params_->mue_; -} - void Mat::Elastic::CoupLogNeoHooke::add_strain_energy(double& psi, const Core::LinAlg::Matrix<3, 1>& prinv, const Core::LinAlg::Matrix<3, 1>& modinv, const Core::LinAlg::SymmetricTensor& glstrain, const int gp, const int eleGID) diff --git a/src/mat/elast/4C_mat_elast_couplogneohooke.hpp b/src/mat/elast/4C_mat_elast_couplogneohooke.hpp index 61239d8863d..49cadd859e3 100644 --- a/src/mat/elast/4C_mat_elast_couplogneohooke.hpp +++ b/src/mat/elast/4C_mat_elast_couplogneohooke.hpp @@ -97,7 +97,11 @@ namespace Mat void add_shear_mod(bool& haveshearmod, ///< non-zero shear modulus was added double& shearmod, ///< variable to add upon int ele_gid ///< element GID - ) const override; + ) const override + { + haveshearmod = true; + shearmod += params_->mue_; + }; //@} diff --git a/src/mat/elast/4C_mat_elast_coupneohooke.cpp b/src/mat/elast/4C_mat_elast_coupneohooke.cpp index 9c7d0a27a65..29e9fd232fd 100644 --- a/src/mat/elast/4C_mat_elast_coupneohooke.cpp +++ b/src/mat/elast/4C_mat_elast_coupneohooke.cpp @@ -28,17 +28,6 @@ Mat::Elastic::CoupNeoHooke::CoupNeoHooke(Mat::Elastic::PAR::CoupNeoHooke* params { } -void Mat::Elastic::CoupNeoHooke::add_shear_mod( - bool& haveshearmod, ///< non-zero shear modulus was added - double& shearmod, ///< variable to add upon - int ele_gid ///< element GID -) const -{ - haveshearmod = true; - - shearmod += 2 * params_->c_; -} - void Mat::Elastic::CoupNeoHooke::add_strain_energy(double& psi, const Core::LinAlg::Matrix<3, 1>& prinv, const Core::LinAlg::Matrix<3, 1>& modinv, const Core::LinAlg::SymmetricTensor& glstrain, const int gp, const int eleGID) diff --git a/src/mat/elast/4C_mat_elast_coupneohooke.hpp b/src/mat/elast/4C_mat_elast_coupneohooke.hpp index 0d900d8190f..84a36ac4a51 100644 --- a/src/mat/elast/4C_mat_elast_coupneohooke.hpp +++ b/src/mat/elast/4C_mat_elast_coupneohooke.hpp @@ -106,7 +106,11 @@ namespace Mat void add_shear_mod(bool& haveshearmod, ///< non-zero shear modulus was added double& shearmod, ///< variable to add upon int ele_gid ///< element GID - ) const override; + ) const override + { + haveshearmod = true; + shearmod += 2 * params_->c_; + }; //@} diff --git a/src/mat/elast/4C_mat_elast_coupvarga.cpp b/src/mat/elast/4C_mat_elast_coupvarga.cpp index 61f4c28d0df..0444f133b84 100644 --- a/src/mat/elast/4C_mat_elast_coupvarga.cpp +++ b/src/mat/elast/4C_mat_elast_coupvarga.cpp @@ -21,19 +21,6 @@ Mat::Elastic::PAR::CoupVarga::CoupVarga(const Core::Mat::PAR::Parameter::Data& m Mat::Elastic::CoupVarga::CoupVarga(Mat::Elastic::PAR::CoupVarga* params) : params_(params) {} -void Mat::Elastic::CoupVarga::add_shear_mod( - bool& haveshearmod, ///< non-zero shear modulus was added - double& shearmod, ///< variable to add upon - int ele_gid ///< element GID -) const -{ - // indeed, a shear modulus is provided - haveshearmod = haveshearmod or true; - - // material parameters for isochoric part - shearmod += params_->mue_; -} - void Mat::Elastic::CoupVarga::add_coefficients_stretches_principal( Core::LinAlg::Matrix<3, 1>& gamma, ///< see above, [gamma_1, gamma_2, gamma_3] Core::LinAlg::Matrix<6, 1>& diff --git a/src/mat/elast/4C_mat_elast_coupvarga.hpp b/src/mat/elast/4C_mat_elast_coupvarga.hpp index dd76f8b334d..1fbc15fea44 100644 --- a/src/mat/elast/4C_mat_elast_coupvarga.hpp +++ b/src/mat/elast/4C_mat_elast_coupvarga.hpp @@ -98,7 +98,14 @@ namespace Mat void add_shear_mod(bool& haveshearmod, ///< non-zero shear modulus was added double& shearmod, ///< variable to add upon int ele_gid ///< element GID - ) const override; + ) const override + { + // indeed, a shear modulus is provided + haveshearmod = true; + + // material parameters for isochoric part + shearmod += params_->mue_; + }; //@} diff --git a/src/mat/elast/4C_mat_elast_isoneohooke.cpp b/src/mat/elast/4C_mat_elast_isoneohooke.cpp index a88a1bbe215..b12d20e3979 100644 --- a/src/mat/elast/4C_mat_elast_isoneohooke.cpp +++ b/src/mat/elast/4C_mat_elast_isoneohooke.cpp @@ -19,14 +19,6 @@ Mat::Elastic::PAR::IsoNeoHooke::IsoNeoHooke(const Core::Mat::PAR::Parameter::Dat Mat::Elastic::IsoNeoHooke::IsoNeoHooke(Mat::Elastic::PAR::IsoNeoHooke* params) : params_(params) {} -void Mat::Elastic::IsoNeoHooke::add_shear_mod( - bool& haveshearmod, double& shearmod, int ele_gid) const -{ - haveshearmod = haveshearmod or true; - - shearmod += params_->mue_.at(ele_gid); -} - void Mat::Elastic::IsoNeoHooke::add_strain_energy(double& psi, const Core::LinAlg::Matrix<3, 1>& prinv, const Core::LinAlg::Matrix<3, 1>& modinv, const Core::LinAlg::SymmetricTensor& glstrain, const int gp, const int eleGID) diff --git a/src/mat/elast/4C_mat_elast_isoneohooke.hpp b/src/mat/elast/4C_mat_elast_isoneohooke.hpp index b92a84a98fe..7157e4b002e 100644 --- a/src/mat/elast/4C_mat_elast_isoneohooke.hpp +++ b/src/mat/elast/4C_mat_elast_isoneohooke.hpp @@ -82,13 +82,17 @@ namespace Mat Core::Materials::MaterialType material_type() const override { return Core::Materials::mes_isoneohooke; - } + }; /// add shear modulus equivalent void add_shear_mod(bool& haveshearmod, ///< non-zero shear modulus was added double& shearmod, ///< variable to add upon int ele_gid ///< element GID - ) const override; + ) const override + { + haveshearmod = true; + shearmod += params_->mue_.at(ele_gid); + }; //@} diff --git a/src/mat/elast/4C_mat_elast_isovarga.cpp b/src/mat/elast/4C_mat_elast_isovarga.cpp index 61d216c0d5e..28cbbc9fd40 100644 --- a/src/mat/elast/4C_mat_elast_isovarga.cpp +++ b/src/mat/elast/4C_mat_elast_isovarga.cpp @@ -20,15 +20,6 @@ Mat::Elastic::PAR::IsoVarga::IsoVarga(const Core::Mat::PAR::Parameter::Data& mat Mat::Elastic::IsoVarga::IsoVarga(Mat::Elastic::PAR::IsoVarga* params) : params_(params) {} -void Mat::Elastic::IsoVarga::add_shear_mod(bool& haveshearmod, double& shearmod, int ele_gid) const -{ - // indeed, a shear modulus is provided - haveshearmod = haveshearmod or true; - - // material parameters for isochoric part - shearmod += params_->mue_; -} - void Mat::Elastic::IsoVarga::add_coefficients_stretches_modified( Core::LinAlg::Matrix<3, 1>& modgamma, Core::LinAlg::Matrix<6, 1>& moddelta, const Core::LinAlg::Matrix<3, 1>& modstr) diff --git a/src/mat/elast/4C_mat_elast_isovarga.hpp b/src/mat/elast/4C_mat_elast_isovarga.hpp index 6eed3a83eef..c0b9251f9f7 100644 --- a/src/mat/elast/4C_mat_elast_isovarga.hpp +++ b/src/mat/elast/4C_mat_elast_isovarga.hpp @@ -99,7 +99,14 @@ namespace Mat void add_shear_mod(bool& haveshearmod, ///< non-zero shear modulus was added double& shearmod, ///< variable to add upon int ele_gid ///< element GID - ) const override; + ) const override + { + // indeed, a shear modulus is provided + haveshearmod = true; + + // material parameters for isochoric part + shearmod += params_->mue_; + }; //@} diff --git a/src/mat/elast/4C_mat_elast_summand.cpp b/src/mat/elast/4C_mat_elast_summand.cpp index 47247641623..4356ea9bf71 100644 --- a/src/mat/elast/4C_mat_elast_summand.cpp +++ b/src/mat/elast/4C_mat_elast_summand.cpp @@ -266,16 +266,11 @@ std::shared_ptr Mat::Elastic::Summand::factory(int matnum return nullptr; } -void Mat::Elastic::Summand::add_shear_mod(bool& haveshearmod, double& shearmod, int ele_gid) const -{ - FOUR_C_THROW("Mat::Elastic::Summand::AddShearMod: Add Shear Modulus not implemented - do so!"); -} - int Mat::Elastic::Summand::unique_par_object_id() const { return -1; } -void Mat::Elastic::Summand::pack(Core::Communication::PackBuffer& data) const { return; } +void Mat::Elastic::Summand::pack(Core::Communication::PackBuffer& data) const {} -void Mat::Elastic::Summand::unpack(Core::Communication::UnpackBuffer& buffer) { return; }; +void Mat::Elastic::Summand::unpack(Core::Communication::UnpackBuffer& buffer) {}; // Function which reads in the given fiber value due to the CIR-AXI-RAD nomenclature void Mat::Elastic::Summand::read_rad_axi_cir( diff --git a/src/mat/elast/4C_mat_elast_summand.hpp b/src/mat/elast/4C_mat_elast_summand.hpp index e7ab214339b..981321f6c5e 100644 --- a/src/mat/elast/4C_mat_elast_summand.hpp +++ b/src/mat/elast/4C_mat_elast_summand.hpp @@ -142,7 +142,12 @@ namespace Mat virtual void add_shear_mod(bool& haveshearmod, ///< non-zero shear modulus was added double& shearmod, ///< variable to add upon int ele_gid ///< element GID - ) const; + ) const + { + FOUR_C_THROW( + "ElastHyper Summand does not implement the calculation of shear modulus. Needs to be " + "implemented in derived class."); + }; /*! * @brief retrieve coefficients of first and second derivative of summand with respect to From 9dede7459d1225147e6cc3c2ca3565018c40010a Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Tue, 16 Jun 2026 12:11:16 +0200 Subject: [PATCH 08/28] Remove unused varying_density from so3 material --- src/mat/4C_mat_so3_material.hpp | 6 ------ src/membrane/4C_membrane_evaluate.cpp | 6 ------ 2 files changed, 12 deletions(-) diff --git a/src/mat/4C_mat_so3_material.hpp b/src/mat/4C_mat_so3_material.hpp index f629de16a53..05b7f5fc3d8 100644 --- a/src/mat/4C_mat_so3_material.hpp +++ b/src/mat/4C_mat_so3_material.hpp @@ -154,12 +154,6 @@ namespace Mat double concentration, Core::LinAlg::Matrix<9, 1>& d_F_dx); //@} - /*! - * @brief Return whether material includes a varying material density - */ - virtual bool varying_density() const { return false; } - - //! @name Handling of Gauss point data /*! * @brief Check if element kinematics and material kinematics are compatible diff --git a/src/membrane/4C_membrane_evaluate.cpp b/src/membrane/4C_membrane_evaluate.cpp index e2734888c66..5a83257b187 100644 --- a/src/membrane/4C_membrane_evaluate.cpp +++ b/src/membrane/4C_membrane_evaluate.cpp @@ -965,12 +965,6 @@ void Discret::Elements::Membrane::mem_nlnstiffmass( (*massmatrix)(noddof_* i + 2, noddof_ * j + 2) += massfactor; } } - - // check for non constant mass matrix - if (solid_material()->varying_density()) - { - FOUR_C_THROW("Varying Density not supported for Membrane"); - } } /*===============================================================================* From ede521a989094a23576498cfedefec033481aa19 Mon Sep 17 00:00:00 2001 From: Laura Engelhardt <87131304+lauraengelhardt@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:12:32 +0200 Subject: [PATCH 09/28] Improve error messages in elasthyper Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Laura Engelhardt <87131304+lauraengelhardt@users.noreply.github.com> --- src/mat/4C_mat_elasthyper.cpp | 5 ++--- src/mat/elast/4C_mat_elast_summand.hpp | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/mat/4C_mat_elasthyper.cpp b/src/mat/4C_mat_elasthyper.cpp index 245f406aa95..63f6e0560f5 100644 --- a/src/mat/4C_mat_elasthyper.cpp +++ b/src/mat/4C_mat_elasthyper.cpp @@ -81,8 +81,7 @@ Mat::ElastHyper::ElastHyper(Mat::PAR::ElastHyper* params) for (const int matid : params_->matids_) { auto sum = Mat::Elastic::Summand::factory(matid); - if (!sum) FOUR_C_THROW("Failed to allocate material summand for matid %d", matid); - + if (!sum) FOUR_C_THROW("Failed to allocate material summand for matid {}", matid); sum->register_anisotropy_extensions(anisotropy_); potsum_.push_back(std::move(sum)); } @@ -160,7 +159,7 @@ void Mat::ElastHyper::unpack(Core::Communication::UnpackBuffer& buffer) { auto sum = Mat::Elastic::Summand::factory(matid); - if (!sum) FOUR_C_THROW("Failed to allocate Elastic::Summand for matid %d", matid); + if (!sum) FOUR_C_THROW("Failed to allocate Elastic::Summand for matid {}", matid); potsum_.push_back(std::move(sum)); } diff --git a/src/mat/elast/4C_mat_elast_summand.hpp b/src/mat/elast/4C_mat_elast_summand.hpp index 981321f6c5e..f9d882e99c9 100644 --- a/src/mat/elast/4C_mat_elast_summand.hpp +++ b/src/mat/elast/4C_mat_elast_summand.hpp @@ -145,8 +145,8 @@ namespace Mat ) const { FOUR_C_THROW( - "ElastHyper Summand does not implement the calculation of shear modulus. Needs to be " - "implemented in derived class."); + "Mat::Elastic::Summand does not implement the calculation of shear modulus. Needs to " + "be implemented in derived class."); }; /*! From a73921fdbc7146a382216ca2c38c2afbe7dd6da1 Mon Sep 17 00:00:00 2001 From: Rasmus Joussen Date: Sun, 21 Jun 2026 15:23:48 +0200 Subject: [PATCH 10/28] Flush error output before MPI abort in main --- apps/global_full/4C_global_full_main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/global_full/4C_global_full_main.cpp b/apps/global_full/4C_global_full_main.cpp index 71cec455fd1..d7fd446e0a6 100644 --- a/apps/global_full/4C_global_full_main.cpp +++ b/apps/global_full/4C_global_full_main.cpp @@ -181,8 +181,10 @@ int main(int argc, char* argv[]) } catch (Core::Exception& err) { - char line[] = "=========================================================================\n"; - std::cout << "\n\n" << line << err.what_with_stacktrace() << "\n" << line << "\n" << '\n'; + constexpr std::string_view line = + "\n=========================================================================\n"; + + std::cerr << "\n" << line << err.what_with_stacktrace() << line << "\n\n" << std::flush; if (communicators.num_groups() > 1) { From 016915cd9142ea63e35412d9044348449d3e2735 Mon Sep 17 00:00:00 2001 From: reginabuehler Date: Mon, 22 Jun 2026 13:26:58 +0000 Subject: [PATCH 11/28] Update IMCS cluster preset --- presets/imcs/cluster/CMakePresets.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/presets/imcs/cluster/CMakePresets.json b/presets/imcs/cluster/CMakePresets.json index 7827ed9fa87..85e205699bd 100644 --- a/presets/imcs/cluster/CMakePresets.json +++ b/presets/imcs/cluster/CMakePresets.json @@ -11,7 +11,8 @@ "FOUR_C_ENABLE_NATIVE_OPTIMIZATIONS": "ON", "FOUR_C_WITH_ARBORX": "ON", "FOUR_C_WITH_FFTW": "ON", - "FOUR_C_WITH_GOOGLETEST": "OFF" + "FOUR_C_WITH_GOOGLETEST": "OFF", + "FOUR_C_WITH_VTK": "ON" } }, { @@ -52,4 +53,4 @@ } } ] -} \ No newline at end of file +} From 651727cacca5772026fcdf45ac16a191c69fb106 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2026 15:04:49 +0000 Subject: [PATCH 12/28] Bump actions/checkout in /.github/actions/analyze_compile_time_tracing Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/actions/analyze_compile_time_tracing/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/analyze_compile_time_tracing/action.yml b/.github/actions/analyze_compile_time_tracing/action.yml index 1a756e69d47..4403866afbd 100644 --- a/.github/actions/analyze_compile_time_tracing/action.yml +++ b/.github/actions/analyze_compile_time_tracing/action.yml @@ -18,7 +18,7 @@ runs: using: composite steps: # Analyze compile time with ClangBuildAnalyzer - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: repository: aras-p/ClangBuildAnalyzer ref: bae0cb488cce944bfc3da9850a69ad621701ebef # version 1.6.0 @@ -40,7 +40,7 @@ runs: SUMMARY_FILE: ${{ inputs.report-summary-file }} # Aggregate individual tracing files with ninjatracing - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: repository: nico/ninjatracing ref: a669e3644cf22b29cbece31dbed2cfbf34e5f48e # no releases for this repo, this is a stable commit From 996b210bcb78067873382b3b390db402416da6c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2026 15:05:02 +0000 Subject: [PATCH 13/28] Bump actions/checkout from 6 to 7 in /.github/workflows Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/buildtest.yml | 20 +++++++-------- .github/workflows/checkcode.yml | 6 ++--- .github/workflows/coverage.yml | 8 +++--- .github/workflows/docker.yml | 8 +++--- .github/workflows/docker_prebuilt_4c.yml | 4 +-- .github/workflows/documentation.yml | 4 +-- .github/workflows/nightly_tests.yml | 32 ++++++++++++------------ .github/workflows/performance_report.yml | 2 +- .github/workflows/trilinos-develop.yml | 6 ++--- 9 files changed, 45 insertions(+), 45 deletions(-) diff --git a/.github/workflows/buildtest.yml b/.github/workflows/buildtest.yml index ec488b1c6b4..7f7fff2c308 100644 --- a/.github/workflows/buildtest.yml +++ b/.github/workflows/buildtest.yml @@ -24,7 +24,7 @@ jobs: outputs: test-chunks: ${{ steps.set-matrix.outputs.chunk-array }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -62,7 +62,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing @@ -93,7 +93,7 @@ jobs: runs-on: ubuntu-latest if: github.ref != 'refs/heads/main' && (success() || failure()) steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: sparse-checkout: .github - uses: ./.github/actions/merge_junit_report_artifacts @@ -117,7 +117,7 @@ jobs: # Due to a bug in runner action the variables $GITHUB_WORKSPACE and ${{ github.workspace }} are different inside a container. https://github.com/actions/runner/issues/2058 # The repo gets cloned to `/__w/4C/4C` ($GITHUB_WORKSPACE) while ${{ github.workspace }} points to `/home/runner/work/4C/4C`.` # Use $GITHUB_WORKSPACE instead of ${{ github.workspace }} - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -170,7 +170,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing @@ -198,7 +198,7 @@ jobs: env: CCACHE_DIR: ${{ github.workspace }}/.ccache steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing @@ -233,7 +233,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: actions/download-artifact@v8 with: name: clang18_build-schema @@ -262,7 +262,7 @@ jobs: outputs: test-chunks: ${{ steps.set-matrix.outputs.chunk-array }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -300,7 +300,7 @@ jobs: matrix: test-chunk: ${{fromJson(needs.gcc13_no_optional_dependencies_build.outputs.test-chunks)}} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing @@ -331,7 +331,7 @@ jobs: runs-on: ubuntu-latest if: github.ref != 'refs/heads/main' && (success() || failure()) steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: sparse-checkout: .github - uses: ./.github/actions/merge_junit_report_artifacts diff --git a/.github/workflows/checkcode.yml b/.github/workflows/checkcode.yml index b9b5ff13203..1b1cd131e7e 100644 --- a/.github/workflows/checkcode.yml +++ b/.github/workflows/checkcode.yml @@ -20,7 +20,7 @@ jobs: env: SKIP: no-commit-to-branch steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Run pre-commit run: | ./utilities/set_up_dev_env.sh @@ -37,7 +37,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/configure_4C @@ -63,7 +63,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2df89c584a1..a253ca2e423 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -18,7 +18,7 @@ jobs: outputs: test-chunks: ${{ steps.set-matrix.outputs.chunk-array }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -62,7 +62,7 @@ jobs: apt-get update apt-get upgrade -y apt-get install -y llvm - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/download_directory @@ -102,7 +102,7 @@ jobs: needs: clang18_coverage_test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: sparse-checkout: .github - uses: ./.github/actions/merge_junit_report_artifacts @@ -117,7 +117,7 @@ jobs: image: ghcr.io/4c-multiphysics/4c-dependencies-ubuntu24.04:35e0657d options: --user root --env OMPI_ALLOW_RUN_AS_ROOT=1 --env OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 08fd30c8ebb..5b387f540cf 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -28,7 +28,7 @@ jobs: dependencies_hash: ${{ steps.check-docker-build-required.outputs.dependencies_hash }} build_docker_image: ${{ steps.check-docker-build-required.outputs.build_docker_image }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - id: check-docker-build-required uses: ./.github/actions/check_docker_build_required with: @@ -50,7 +50,7 @@ jobs: == 'true' }} steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Build and push image uses: ./.github/actions/build_dependencies with: @@ -76,7 +76,7 @@ jobs: == 'true' }} steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Build and push image uses: ./.github/actions/build_dependencies with: @@ -96,7 +96,7 @@ jobs: contents: read packages: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - id: compute-dependencies-hash uses: ./.github/actions/compute-and-check-dependencies-hash with: diff --git a/.github/workflows/docker_prebuilt_4c.yml b/.github/workflows/docker_prebuilt_4c.yml index 219bdf7ba39..284251fc555 100644 --- a/.github/workflows/docker_prebuilt_4c.yml +++ b/.github/workflows/docker_prebuilt_4c.yml @@ -23,7 +23,7 @@ jobs: id-token: write steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Log in to the Container registry uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: @@ -65,7 +65,7 @@ jobs: id-token: write steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Log in to the Container registry uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index ca1abdd61a3..e3ea9cd8c03 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -26,7 +26,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -52,7 +52,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C diff --git a/.github/workflows/nightly_tests.yml b/.github/workflows/nightly_tests.yml index 05120243630..f6f5864e674 100644 --- a/.github/workflows/nightly_tests.yml +++ b/.github/workflows/nightly_tests.yml @@ -18,7 +18,7 @@ jobs: outputs: test-chunks: ${{ steps.set-matrix.outputs.chunk-array }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -55,7 +55,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing @@ -86,7 +86,7 @@ jobs: runs-on: ubuntu-latest if: success() || failure() steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: sparse-checkout: .github - uses: ./.github/actions/merge_junit_report_artifacts @@ -105,7 +105,7 @@ jobs: outputs: test-chunks: ${{ steps.set-matrix.outputs.chunk-array }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -212,7 +212,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing @@ -243,7 +243,7 @@ jobs: runs-on: ubuntu-latest if: success() || failure() steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: sparse-checkout: .github - uses: ./.github/actions/merge_junit_report_artifacts @@ -262,7 +262,7 @@ jobs: outputs: test-chunks: ${{ steps.set-matrix.outputs.chunk-array }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -299,7 +299,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing @@ -336,7 +336,7 @@ jobs: outputs: test-chunks: ${{ steps.set-matrix.outputs.chunk-array }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -373,7 +373,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing @@ -404,7 +404,7 @@ jobs: runs-on: ubuntu-latest if: success() || failure() steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: sparse-checkout: .github - uses: ./.github/actions/merge_junit_report_artifacts @@ -423,7 +423,7 @@ jobs: outputs: test-chunks: ${{ steps.set-matrix.outputs.chunk-array }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -460,7 +460,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - name: Setup developer environment for testing @@ -491,7 +491,7 @@ jobs: runs-on: ubuntu-latest if: success() || failure() steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: sparse-checkout: .github - uses: ./.github/actions/merge_junit_report_artifacts @@ -510,7 +510,7 @@ jobs: env: CCACHE_DIR: ${{ github.workspace }}/.ccache steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check docker hash uses: ./.github/actions/compute-and-check-dependencies-hash - uses: ./.github/actions/build_4C @@ -543,7 +543,7 @@ jobs: run: | apt-get update apt-get install -y git-lfs - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: # for performance tests, we need to checkout the large meshes lfs: true diff --git a/.github/workflows/performance_report.yml b/.github/workflows/performance_report.yml index 730570e65a5..edb64dceec3 100644 --- a/.github/workflows/performance_report.yml +++ b/.github/workflows/performance_report.yml @@ -15,7 +15,7 @@ jobs: if: ${{ github.event.workflow_run.conclusion == 'success' }} runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Setup python environment run: | python -m venv $GITHUB_WORKSPACE/venv diff --git a/.github/workflows/trilinos-develop.yml b/.github/workflows/trilinos-develop.yml index 6360fcbbe11..ba4193b9d5a 100644 --- a/.github/workflows/trilinos-develop.yml +++ b/.github/workflows/trilinos-develop.yml @@ -23,7 +23,7 @@ jobs: id-token: write steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Log in to the Container registry uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: @@ -61,7 +61,7 @@ jobs: outputs: test-chunks: ${{ steps.set-matrix.outputs.chunk-array }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/build_4C with: cmake-preset: docker_assertions @@ -95,7 +95,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Setup developer environment for testing run: | cd $GITHUB_WORKSPACE From 748b712173ba38624580f7913113e3aa1790529f Mon Sep 17 00:00:00 2001 From: Christoph Schmidt Date: Tue, 16 Jun 2026 14:27:47 +0200 Subject: [PATCH 14/28] Add warning to exodus reader and minor clean-up of condition definition. --- .../src/condition/4C_fem_condition_definition.cpp | 13 ++++++------- .../src/condition/4C_fem_condition_definition.hpp | 8 ++++---- src/core/io/src/4C_io_exodus.cpp | 12 ++++++++++++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/core/fem/src/condition/4C_fem_condition_definition.cpp b/src/core/fem/src/condition/4C_fem_condition_definition.cpp index 1f4accdae78..4987aeb7f48 100644 --- a/src/core/fem/src/condition/4C_fem_condition_definition.cpp +++ b/src/core/fem/src/condition/4C_fem_condition_definition.cpp @@ -19,13 +19,12 @@ FOUR_C_NAMESPACE_OPEN -/* -----------------------------------------------------------------------------------------------* - | Class ConditionDefinition | - * -----------------------------------------------------------------------------------------------*/ - +/*----------------------------------------------------------------------* + *----------------------------------------------------------------------*/ Core::Conditions::ConditionDefinition::ConditionDefinition(std::string sectionname, - std::string conditionname, std::string description, Core::Conditions::ConditionType condtype, - bool buildgeometry, Core::Conditions::GeometryType gtype) + std::string conditionname, std::string description, + const Core::Conditions::ConditionType condtype, const bool buildgeometry, + const Core::Conditions::GeometryType gtype) : sectionname_(std::move(sectionname)), conditionname_(std::move(conditionname)), description_(std::move(description)), @@ -67,7 +66,7 @@ void Core::Conditions::ConditionDefinition::add_component(const Core::IO::InputS /*----------------------------------------------------------------------* *----------------------------------------------------------------------*/ void Core::Conditions::ConditionDefinition::read( - Core::IO::InputFile& input, std::vector& condition_specs) const + const Core::IO::InputFile& input, std::vector& condition_specs) const { Core::IO::InputParameterContainer container; try diff --git a/src/core/fem/src/condition/4C_fem_condition_definition.hpp b/src/core/fem/src/condition/4C_fem_condition_definition.hpp index c8cb73df50e..9181b78d17d 100644 --- a/src/core/fem/src/condition/4C_fem_condition_definition.hpp +++ b/src/core/fem/src/condition/4C_fem_condition_definition.hpp @@ -116,16 +116,16 @@ namespace Core::Conditions \param condition_specs vector of the validated condition specifications in the input to be filled. */ - void read(Core::IO::InputFile& input, std::vector& condition_specs) const; + void read(const Core::IO::InputFile& input, std::vector& condition_specs) const; /// name of my section in input file - std::string section_name() const { return sectionname_; } + [[nodiscard]] std::string section_name() const { return sectionname_; } /// my condition name - std::string name() const { return conditionname_; } + [[nodiscard]] std::string name() const { return conditionname_; } /// my GeometryType - Core::Conditions::GeometryType geometry_type() const { return gtype_; } + [[nodiscard]] Core::Conditions::GeometryType geometry_type() const { return gtype_; } /// Get the InputSpec for this ConditionDefinition [[nodiscard]] Core::IO::InputSpec spec() const; diff --git a/src/core/io/src/4C_io_exodus.cpp b/src/core/io/src/4C_io_exodus.cpp index d39f3d55666..cffd7843255 100644 --- a/src/core/io/src/4C_io_exodus.cpp +++ b/src/core/io/src/4C_io_exodus.cpp @@ -191,6 +191,12 @@ Core::IO::MeshInput::RawMesh<3> Core::IO::Exodus::read_exodus_file( // prefer std::string to store element type std::string ele_type(mychar); + if (ele_type.size() == 32) + { + std::cout << "WARNING: Your element block name " << ele_type + << " might be too long. Exodus only allows 32 characters for names.\n"; + } + // get ElementBlock name CHECK_EXODUS_CALL(ex_get_name(exo_handle, EX_ELEM_BLOCK, ebids[i], mychar)); @@ -242,6 +248,12 @@ Core::IO::MeshInput::RawMesh<3> Core::IO::Exodus::read_exodus_file( // prefer std::string to store name std::string nodesetname(mychar); + if (nodesetname.size() == 32) + { + std::cout << "WARNING: Your nodeset name " << nodesetname + << " might be too long. Exodus only allows 32 characters for names.\n"; + } + // get nodes in node set std::vector node_set_node_list(num_nodes_in_set); CHECK_EXODUS_CALL( From 251e2ff76c82d1646211a07b99334742fb9fb3a7 Mon Sep 17 00:00:00 2001 From: Christoph Schmidt Date: Fri, 12 Jun 2026 17:31:20 +0200 Subject: [PATCH 15/28] Adapt battery tutorial --- .../battery/tutorial_battery.4C.yaml | 279 ++++++++++-------- tests/tutorials/battery/tutorial_battery.e | Bin 35328 -> 54900 bytes tests/tutorials/battery/tutorial_battery.jou | 221 +++++++------- 3 files changed, 272 insertions(+), 228 deletions(-) diff --git a/tests/tutorials/battery/tutorial_battery.4C.yaml b/tests/tutorials/battery/tutorial_battery.4C.yaml index 977828503ab..ad846c77765 100644 --- a/tests/tutorials/battery/tutorial_battery.4C.yaml +++ b/tests/tutorials/battery/tutorial_battery.4C.yaml @@ -4,6 +4,7 @@ PROBLEM TYPE: IO: STRUCT_STRESS: "Cauchy" STDOUTEVERY: 0 + ELEMENT_MAT_ID: true IO/RUNTIME VTK OUTPUT: INTERVAL_STEPS: 1 @@ -15,8 +16,8 @@ IO/RUNTIME VTK OUTPUT/STRUCTURE: SSI CONTROL: NUMSTEP: 2 - MAXTIME: 2e+07 - TIMESTEP: 1000 + MAXTIME: 2.0e7 + TIMESTEP: 10.0e3 COUPALGO: ssi_Monolithic SCATRATIMINTTYPE: "Elch" @@ -61,7 +62,7 @@ SCALAR TRANSPORT DYNAMIC/S2I COUPLING: MESHTYING_CONDITIONS_INDEPENDENT_SETUP: true SOLVER 1: - SOLVER: "UMFPACK" + SOLVER: MUMPS MATERIALS: - MAT: 1 @@ -73,6 +74,7 @@ MATERIALS: OCP_MODEL: Function: OCP_FUNCT_NUM: 6 + - MAT: 2 MAT_MultiplicativeSplitDefgradElastHyper: NUMMATEL: 1 @@ -80,10 +82,12 @@ MATERIALS: NUMFACINEL: 1 INELDEFGRADFACIDS: [4] DENS: 4780 + - MAT: 3 ELAST_CoupNeoHooke: YOUNG: 1.8485e+11 NUE: 0.3 + - MAT: 4 MAT_InelasticDefgradPolyIntercalFracIso: SCALAR1: 1 @@ -94,18 +98,21 @@ MATERIALS: X_min: 0.152 X_max: 0.94 MATID: 1 + - MAT: 5 MAT_elchmat: NUMDOF: 2 NUMSCAL: 1 NUMPHASE: 1 PHASEIDS: [6] + - MAT: 6 MAT_elchphase: EPSILON: 1 TORTUOSITY: 1 NUMMAT: 1 MATIDS: [7] + - MAT: 7 MAT_newman: VALENCE: 1 @@ -113,6 +120,7 @@ MATERIALS: COND: 16.11 TRANSFERENCE_NR: 1.0 THERM_FAC: 1.0 + - MAT: 8 MAT_MultiplicativeSplitDefgradElastHyper: NUMMATEL: 1 @@ -120,12 +128,15 @@ MATERIALS: NUMFACINEL: 1 INELDEFGRADFACIDS: [10] DENS: 1850 + - MAT: 9 ELAST_CoupNeoHooke: YOUNG: 2.601e+10 NUE: 0.27 + - MAT: 10 MAT_InelasticDefgradNoGrowth: {} + - MAT: 11 MAT_electrode: DIFF_COEF: 1.0 @@ -135,6 +146,7 @@ MATERIALS: OCP_MODEL: Function: OCP_FUNCT_NUM: 7 + - MAT: 12 MAT_MultiplicativeSplitDefgradElastHyper: NUMMATEL: 1 @@ -142,16 +154,19 @@ MATERIALS: NUMFACINEL: 1 INELDEFGRADFACIDS: [14] DENS: 530 + - MAT: 13 ELAST_CoupNeoHooke: YOUNG: 4.9e+09 NUE: 0.42 + - MAT: 14 MAT_InelasticDefgradLinScalarAniso: SCALAR1: 1 SCALAR1_MolarGrowthFac: 1.2998e-05 SCALAR1_RefConc: 1 GrowthDirection: [1, 0, 0] + - MAT: 15 MAT_electrode: DIFF_COEF: 1.0 @@ -161,6 +176,7 @@ MATERIALS: OCP_MODEL: Function: OCP_FUNCT_NUM: 7 + - MAT: 16 MAT_MultiplicativeSplitDefgradElastHyper: NUMMATEL: 1 @@ -168,10 +184,12 @@ MATERIALS: NUMFACINEL: 1 INELDEFGRADFACIDS: [10] DENS: 8920 + - MAT: 17 ELAST_CoupNeoHooke: YOUNG: 1.15e+11 NUE: 0.34 + - MAT: 19 MAT_electrode: DIFF_COEF: 1.0 @@ -181,6 +199,7 @@ MATERIALS: OCP_MODEL: Function: OCP_FUNCT_NUM: 7 + - MAT: 20 MAT_MultiplicativeSplitDefgradElastHyper: NUMMATEL: 1 @@ -188,6 +207,7 @@ MATERIALS: NUMFACINEL: 1 INELDEFGRADFACIDS: [10] DENS: 2700 + - MAT: 21 ELAST_CoupNeoHooke: YOUNG: 6.9e+10 @@ -198,18 +218,22 @@ CLONING MATERIAL MAP: SRC_MAT: 2 TAR_FIELD: "scatra" TAR_MAT: 1 + - SRC_FIELD: "structure" SRC_MAT: 8 TAR_FIELD: "scatra" TAR_MAT: 5 + - SRC_FIELD: "structure" SRC_MAT: 12 TAR_FIELD: "scatra" TAR_MAT: 11 + - SRC_FIELD: "structure" SRC_MAT: 16 TAR_FIELD: "scatra" TAR_MAT: 15 + - SRC_FIELD: "structure" SRC_MAT: 20 TAR_FIELD: "scatra" @@ -253,198 +277,206 @@ FUNCT6: FUNCT7: - FASTPOLYNOMIAL: NUMCOEFF: 1 - COEFF: [0] + COEFF: [0.0] RESULT DESCRIPTION: - SCATRA: DIS: "scatra" NODE: 32 QUANTITY: "phi1" - VALUE: 1.26777850815654229e+01 - TOLERANCE: 1.3e-07 + VALUE: 1.17729179835590955e+02 + TOLERANCE: 1.2e-06 - SCATRA: DIS: "scatra" NODE: 32 QUANTITY: "phi2" - VALUE: 5.63408408249148287e-06 + VALUE: 5.63420877183655170e-06 TOLERANCE: 5.6e-14 - SCATRA: DIS: "scatra" NODE: 95 QUANTITY: "phi1" - VALUE: 1.2e3 + VALUE: 1.20023216963911113e+03 TOLERANCE: 1.2e-05 - SCATRA: DIS: "scatra" NODE: 95 QUANTITY: "phi2" - VALUE: 1.93918473648069017e-04 - TOLERANCE: 1.9e-12 + VALUE: 2.02652764799278619e-04 + TOLERANCE: 2.0e-12 - SCATRA: DIS: "scatra" NODE: 232 QUANTITY: "phi1" - VALUE: 4.18389051248949399e+04 - TOLERANCE: 4.2e-4 + VALUE: 4.31876698510277783e+04 + TOLERANCE: 4.3e-4 - SCATRA: DIS: "scatra" NODE: 232 QUANTITY: "phi2" - VALUE: 3.60022131383473765e+00 + VALUE: 3.60019943891482708e+00 TOLERANCE: 3.6e-08 - STRUCTURE: DIS: "structure" NODE: 32 QUANTITY: "dispx" - VALUE: -6.66773032761887734e-08 - TOLERANCE: 6.7e-15 + VALUE: 8.44280151667777646e-08 + TOLERANCE: 8.4e-16 - STRUCTURE: DIS: "structure" NODE: 32 QUANTITY: "dispy" - VALUE: -2.07081933892450716e-10 - TOLERANCE: 1.0e-16 + VALUE: -8.44280151749625117e-08 + TOLERANCE: 8.4e-16 - STRUCTURE: DIS: "structure" NODE: 32 QUANTITY: "dispz" - VALUE: 2.07081926671139049e-10 - TOLERANCE: 1.0e-16 + VALUE: -9.67592544354235016e-08 + TOLERANCE: 9.7e-16 - STRUCTURE: DIS: "structure" NODE: 95 QUANTITY: "dispx" - VALUE: -2.46786207653848376e-08 - TOLERANCE: 2.5e-16 + VALUE: 2.07719538778803939e-09 + TOLERANCE: 1.0e-16 - STRUCTURE: DIS: "structure" NODE: 95 QUANTITY: "dispy" - VALUE: 5.06484398044960120e-09 + VALUE: -8.12085065370041722e-09 TOLERANCE: 1.0e-16 - STRUCTURE: DIS: "structure" NODE: 95 QUANTITY: "dispz" - VALUE: -5.06484397125480544e-09 - TOLERANCE: 1.0e-16 + VALUE: -1.76358836650572382e-08 + TOLERANCE: 1.8e-16 - STRUCTURE: DIS: "structure" NODE: 232 QUANTITY: "dispx" - VALUE: -1.92532124495455729e-08 - TOLERANCE: 2.0e-16 + VALUE: 3.14013986975288425e-09 + TOLERANCE: 1.0e-16 - STRUCTURE: DIS: "structure" NODE: 232 QUANTITY: "dispz" - VALUE: 3.77494081961681657e-08 - TOLERANCE: 3.8e-16 + VALUE: -7.04564778319423031e-08 + TOLERANCE: 7.0e-16 PROBLEM SIZE: DIM: 3 DESIGN SURF TRANSPORT NEUMANN CONDITIONS: - - E: 12 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: surface_normal_z_cat_cc NUMDOF: 2 ONOFF: [0, 1] VAL: [0, 5.839316572e-06] - FUNCT: [0, 0] + FUNCT: [null, null] DESIGN POINT DIRICH CONDITIONS: - - E: 23 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: vertices_an_side_cc NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 24 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: vertices_cat_side_cc NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] DESIGN LINE DIRICH CONDITIONS: - - E: 16 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: curves_y_dir_an_cc NUMDOF: 3 ONOFF: [1, 0, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 17 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: curves_x_dir_an_cc NUMDOF: 3 - ONOFF: [1, 1, 0] + ONOFF: [0, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 18 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: curves_(-1_1_0)_dir_an_cc NUMDOF: 3 - ONOFF: [1, 1, 0] + ONOFF: [1, 0, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 19 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: curves_y_dir_cat_cc + NUMDOF: 3 + ONOFF: [1, 0, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + + - NODE_SET_NAME: curves_x_dir_cat_cc NUMDOF: 3 ONOFF: [0, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] + - NODE_SET_NAME: curves_(-1_1_0)_dir_cat_cc + NUMDOF: 3 + ONOFF: [1, 0, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + + - NODE_SET_NAME: curves_z_dir + NUMDOF: 3 + ONOFF: [1, 1, 0] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + DESIGN SURF DIRICH CONDITIONS: - - E: 1 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: surface_normal_z_an_cc NUMDOF: 3 - ONOFF: [1, 0, 0] + ONOFF: [0, 0, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 12 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: surface_normal_z_cat_cc NUMDOF: 3 - ONOFF: [1, 0, 0] + ONOFF: [0, 0, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 13 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: surface_normal_y NUMDOF: 3 ONOFF: [0, 1, 0] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 14 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: surface_normal_x NUMDOF: 3 - ONOFF: [0, 0, 1] + ONOFF: [1, 0, 0] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 15 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: surface_normal_(1_1_0) NUMDOF: 3 ONOFF: [0, 1, 0] VAL: [0, 0, 0] FUNCT: [null, null, null] DESIGN SURF TRANSPORT DIRICH CONDITIONS: - - E: 1 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: surface_normal_z_an_cc NUMDOF: 2 ONOFF: [0, 1] VAL: [0, 0] FUNCT: [0, 0] DESIGN VOL TRANSPORT DIRICH CONDITIONS: - - E: 2 - ENTITY_TYPE: element_block_id - NUMDOF: 2 - ONOFF: [1, 0] - VAL: [1200, 0] - FUNCT: [0, 0] - E: 4 ENTITY_TYPE: element_block_id NUMDOF: 2 ONOFF: [1, 0] VAL: [1200, 0] FUNCT: [0, 0] + - E: 5 ENTITY_TYPE: element_block_id NUMDOF: 2 @@ -457,42 +489,49 @@ DESIGN VOL INITIAL FIELD CONDITIONS: ENTITY_TYPE: element_block_id FIELD: "ScaTra" FUNCT: 1 + - E: 2 ENTITY_TYPE: element_block_id FIELD: "ScaTra" FUNCT: 2 + - E: 3 ENTITY_TYPE: element_block_id FIELD: "ScaTra" FUNCT: 3 + - E: 4 ENTITY_TYPE: element_block_id FIELD: "ScaTra" FUNCT: 4 + - E: 5 ENTITY_TYPE: element_block_id FIELD: "ScaTra" FUNCT: 5 DESIGN LINE LOCSYS CONDITIONS: - - E: 18 - ENTITY_TYPE: node_set_id - ROTANGLE: [0.7853981634, 0, 0] + - NODE_SET_NAME: curves_(-1_1_0)_dir_cat_cc + ROTANGLE: [0, 0, -0.7853981634] + FUNCT: [0, 0, 0] + USEUPDATEDNODEPOS: 0 + USECONSISTENTNODENORMAL: 0 + + - NODE_SET_NAME: curves_(-1_1_0)_dir_an_cc + ROTANGLE: [0, 0, -0.7853981634] FUNCT: [0, 0, 0] USEUPDATEDNODEPOS: 0 USECONSISTENTNODENORMAL: 0 DESIGN SURF LOCSYS CONDITIONS: - - E: 15 - ENTITY_TYPE: node_set_id - ROTANGLE: [0.7853981634, 0, 0] + - NODE_SET_NAME: surface_normal_(1_1_0) + ROTANGLE: [0, 0, -0.7853981634] FUNCT: [0, 0, 0] USEUPDATEDNODEPOS: 0 USECONSISTENTNODENORMAL: 0 DESIGN S2I KINETICS SURF CONDITIONS: - - E: 2 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cc_side(s)_an-cc_interface ConditionID: 0 INTERFACE_SIDE: "Slave" KINETIC_MODEL: "ConstantInterfaceResistance" @@ -500,12 +539,12 @@ DESIGN S2I KINETICS SURF CONDITIONS: RESISTANCE: 1e-05 E-: 1 IS_PSEUDO_CONTACT: false - - E: 3 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: an_side(t)_an-cc_interface ConditionID: 0 INTERFACE_SIDE: "Master" - - E: 4 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: an_side(s)_an-el_interface ConditionID: 1 INTERFACE_SIDE: "Slave" KINETIC_MODEL: "Butler-VolmerReduced" @@ -516,16 +555,16 @@ DESIGN S2I KINETICS SURF CONDITIONS: ALPHA_A: 0.5 ALPHA_C: 0.5 IS_PSEUDO_CONTACT: false - - E: 5 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: el_side(t)_an-el_interface ConditionID: 1 INTERFACE_SIDE: "Master" - - E: 6 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: el_side(t)_cat-el_interface ConditionID: 2 INTERFACE_SIDE: "Master" - - E: 7 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: cat_side(s)_cat-el_interface ConditionID: 2 INTERFACE_SIDE: "Slave" KINETIC_MODEL: "Butler-Volmer" @@ -536,12 +575,12 @@ DESIGN S2I KINETICS SURF CONDITIONS: ALPHA_A: 0.5 ALPHA_C: 0.5 IS_PSEUDO_CONTACT: false - - E: 8 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: cat_side(t)_cat-cc_interface ConditionID: 3 INTERFACE_SIDE: "Master" - - E: 9 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: cc_side(s)_am_cat-cc_interface ConditionID: 3 INTERFACE_SIDE: "Slave" KINETIC_MODEL: "ConstantInterfaceResistance" @@ -549,12 +588,12 @@ DESIGN S2I KINETICS SURF CONDITIONS: RESISTANCE: 1e-05 E-: 1 IS_PSEUDO_CONTACT: false - - E: 10 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: el_side(t)_el_cat-cc_interface ConditionID: 4 INTERFACE_SIDE: "Master" - - E: 11 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: cc_side(s)_el_cat-cc_interface ConditionID: 4 INTERFACE_SIDE: "Slave" KINETIC_MODEL: "NoInterfaceFlux" @@ -568,61 +607,59 @@ DESIGN ELECTRODE STATE OF CHARGE VOL CONDITIONS: ONE_HOUR: 3.6e+06 DESIGN CELL VOLTAGE SURF CONDITIONS: - - E: 1 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: surface_normal_z_an_cc ConditionID: 0 - - E: 12 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: surface_normal_z_cat_cc ConditionID: 1 DESIGN SSI INTERFACE MESHTYING SURF CONDITIONS: - - E: 2 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cc_side(s)_an-cc_interface ConditionID: 0 INTERFACE_SIDE: "Slave" S2I_KINETICS_ID: 0 - - E: 3 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: an_side(t)_an-cc_interface ConditionID: 0 INTERFACE_SIDE: "Master" S2I_KINETICS_ID: 0 - - E: 4 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: an_side(s)_an-el_interface ConditionID: 1 INTERFACE_SIDE: "Slave" S2I_KINETICS_ID: 1 - - E: 5 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: el_side(t)_an-el_interface ConditionID: 1 INTERFACE_SIDE: "Master" S2I_KINETICS_ID: 1 - - E: 6 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: el_side(t)_cat-el_interface ConditionID: 2 INTERFACE_SIDE: "Master" S2I_KINETICS_ID: 2 - - E: 7 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: cat_side(s)_cat-el_interface ConditionID: 2 INTERFACE_SIDE: "Slave" S2I_KINETICS_ID: 2 - - E: 8 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: cat_side(t)_cat-cc_interface ConditionID: 3 INTERFACE_SIDE: "Master" S2I_KINETICS_ID: 3 - - E: 9 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: cc_side(s)_am_cat-cc_interface ConditionID: 3 INTERFACE_SIDE: "Slave" S2I_KINETICS_ID: 3 - - E: 10 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: el_side(t)_el_cat-cc_interface ConditionID: 4 INTERFACE_SIDE: "Master" S2I_KINETICS_ID: 4 - - E: 11 - ENTITY_TYPE: node_set_id + + - NODE_SET_NAME: cc_side(s)_el_cat-cc_interface ConditionID: 4 INTERFACE_SIDE: "Slave" S2I_KINETICS_ID: 4 @@ -631,31 +668,31 @@ STRUCTURE GEOMETRY: FILE: "tutorial_battery.e" SHOW_INFO: "summary" ELEMENT_BLOCKS: - - ID: 1 + - NAME: anode SOLIDSCATRA: TET4: MAT: 12 KINEM: nonlinear TYPE: ElchElectrode - - ID: 2 + - NAME: electrolyte SOLIDSCATRA: TET4: MAT: 8 KINEM: nonlinear TYPE: ElchDiffCond - - ID: 3 + - NAME: cathode SOLIDSCATRA: TET4: MAT: 2 KINEM: nonlinear TYPE: ElchElectrode - - ID: 4 + - NAME: anode_cc SOLIDSCATRA: TET4: MAT: 16 KINEM: nonlinear TYPE: ElchElectrode - - ID: 5 + - NAME: cathode_cc SOLIDSCATRA: TET4: MAT: 20 diff --git a/tests/tutorials/battery/tutorial_battery.e b/tests/tutorials/battery/tutorial_battery.e index c97c207f0d5e7371ca45c59e568e9dd54e790f6d..ee9557788965a396f1afebc07b068788cf6b2e56 100644 GIT binary patch literal 54900 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 diff --git a/tests/tutorials/battery/tutorial_battery.jou b/tests/tutorials/battery/tutorial_battery.jou index 88c326dcf07..b493c33e3aa 100644 --- a/tests/tutorials/battery/tutorial_battery.jou +++ b/tests/tutorials/battery/tutorial_battery.jou @@ -32,15 +32,15 @@ $ -------------------------- $ | geometry | $ -------------------------- $ anode -create brick x {an} y {2*r*cos(theta/360*PI)} z {2*r*cos(theta/360*PI)} +create brick x {2*r*cos(theta/360*PI)} y {2*r*cos(theta/360*PI)} z {an} compress -move volume 1 x {an/2 + (2*n_c-3)*r*cos(theta/360*PI)+2*r+sep} +move volume 1 z {an/2 + (2*n_c-3)*r*cos(theta/360*PI)+2*r+sep} compress $ electrolyte -create brick x {(n_c-1)*2*r*cos(theta/360*PI)+2*r+sep} y {2*r*cos(theta/360*PI)} z {2*r*cos(theta/360*PI)} +create brick x {2*r*cos(theta/360*PI)} y {2*r*cos(theta/360*PI)} z {(n_c-1)*2*r*cos(theta/360*PI)+2*r+sep} compress -move volume 2 x {(n_c-2)*r*cos(theta/360*PI)+r+sep/2} +move volume 2 z {(n_c-2)*r*cos(theta/360*PI)+r+sep/2} compress $ cathode @@ -48,7 +48,7 @@ $ cathode # {Loop(n_c)} create sphere radius {r} # {if(i>0)} - move volume 4 x {i*2*r*cos(theta/360*PI)} + move volume 4 z {i*2*r*cos(theta/360*PI)} unite volume 3 4 compress # {endif} @@ -58,21 +58,21 @@ compress $ insert one non-connected sphere create sphere radius {r_non_conn} -move volume 4 x {-r*cos(theta/360*PI)} y {-r*cos(theta/360*PI)} z {r*cos(theta/360*PI)} +move volume 4 x {r*cos(theta/360*PI)} y {-r*cos(theta/360*PI)} z {-r*cos(theta/360*PI)} intersect volume 2 4 keep subtract volume 4 from volume 2 volume 5 id 4 $ anode current collector -create brick x {cc_an} y {2*r*cos(theta/360*PI)} z {2*r*cos(theta/360*PI)} +create brick x {2*r*cos(theta/360*PI)} y {2*r*cos(theta/360*PI)} z {cc_an} compress -move volume 5 x {cc_an/2 + an + (2*n_c-3)*r*cos(theta/360*PI)+2*r+sep} +move volume 5 z {cc_an/2 + an + (2*n_c-3)*r*cos(theta/360*PI)+2*r+sep} compress $ cathode current collector -create brick x {cc_cat} y {2*r*cos(theta/360*PI)} z {2*r*cos(theta/360*PI)} +create brick x {2*r*cos(theta/360*PI)} y {2*r*cos(theta/360*PI)} z {cc_cat} compress -move volume 6 x {-cc_cat/2-r*cos(theta/360*PI)} +move volume 6 z {-cc_cat/2-r*cos(theta/360*PI)} $ trim the connected cathode spheres to the box size and cut those spheres from the electrolyte intersect volume 2 3 keep @@ -81,14 +81,14 @@ volume 7 id 3 compress $ cut out symmetric cuboid -webcut volume all with plane zplane imprint +webcut volume all with plane xplane imprint delete volume 7 8 9 10 11 compress webcut volume all with plane yplane imprint delete volume 7 8 9 10 11 compress $ cut out symmetric wedge -webcut volume all with plane yplane rotate 45 about x imprint +webcut volume all with plane yplane rotate -45 about z imprint delete volume 7 8 9 10 11 12 compress @@ -109,25 +109,23 @@ set tetmesher optimize level 3 overconstrained off sliver off set tetmesher boundary recovery off volume 1 size {meshsize_a*r} # {if(interfacemeshsize_a>0.0)} - surface with x_max = {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep} in volume 1 size {interfacemeshsize_a} + surface with z_max = {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep} in volume 1 size {interfacemeshsize_a} # {endif} volume 2 size {meshsize_e*r} volume 3 size {meshsize_c*r} # {if(interfacemeshsize_c>0.0)} - surface with not is_plane in volume 3 size {interfacemeshsize_c} -# {endif} -# {if(contactcurveintervals_e>0 && (matching!=1 || (interfacemeshsize_a==0.0 && interfacemeshsize_c==0.0)))} - curve with length <= {2*PI*r*sin(theta/360*PI)} and with Y_Min == Y_Max in volume 2 interval {contactcurveintervals_e} + surface with not is_plane in volume 3 size {interfacemeshsize_c*r} + surface with not is_plane in volume 4 size {interfacemeshsize_c*r} # {endif} # {if(particlediameterintervals_c>0)} curve with Y_Min == 0 and Y_Max == 0 in volume 3 interval {n_c*particlediameterintervals_c} scheme equal # {endif} volume 4 size {meshsize_cat_non*r} -volume 5 size {meshsize_cc_an} -volume 6 size {meshsize_cc_cat} +volume 5 size {meshsize_cc_an*r} +volume 6 size {meshsize_cc_cat*r} mesh volume all # {if(meshrefinements_a>0)} - refine surface with x_max = {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep} in volume 1 numsplit {meshrefinements_a} bias 1.0 depth 1 smooth + refine surface with z_max = {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep} in volume 1 numsplit {meshrefinements_a} bias 1.0 depth 1 smooth # {endif} # {if(meshrefinements_c>0)} refine surface with not is_plane in volume 3 numsplit {meshrefinements_c} bias 1.0 depth 1 smooth @@ -156,130 +154,139 @@ block 3 Name "cathode" # anode side current collector block 4 volume 5 -block 4 Name "anode cc" +block 4 Name "anode_cc" # cathode side current collector block 5 volume 6 -block 5 Name "cathode cc" +block 5 Name "cathode_cc" # anode-side current collector -nodeset 1 surface with x_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol} in volume 5 -nodeset 1 Name "an-side cc" +nodeset 1 surface with z_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol} in volume 5 +nodeset 1 Name "surface_normal_z_an_cc" # current collector-side of anode-current collector interface -nodeset 2 surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 -nodeset 2 Name "cc-side (sl) of an-cc interface" +nodeset 2 surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 +nodeset 2 Name "cc_side(s)_an-cc_interface" # anode-side of anode-current collector interface -nodeset 3 surface with x_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an-tol} in volume 1 -nodeset 3 Name "an-side (ma) of an-cc interface" +nodeset 3 surface with z_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an-tol} in volume 1 +nodeset 3 Name "an_side(t)_an-cc_interface" # anode-side of anode-electrolyte interface -nodeset 4 surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 -nodeset 4 Name "an-side (sl) of an-el interface" +nodeset 4 surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 +nodeset 4 Name "an_side(s)_an-el_interface" # electrolyte-side of anode-electrolyte interface -nodeset 5 surface with x_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep-tol} in volume 2 -nodeset 5 Name "el-side (ma) of an-el interface" +nodeset 5 surface with z_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep-tol} in volume 2 +nodeset 5 Name "el_side(t)_an-el_interface" # electrolyte-side of cathode-electrolyte interface nodeset 6 surface with not is_plane in volume 2 -nodeset 6 Name "el-side (ma) of cat-el interface" +nodeset 6 Name "el_side(t)_cat-el_interface" # cathode-side of cathode-electrolyte interface nodeset 7 surface with not is_plane in volume 3 4 -#nodeset 7 Name "cat-side (sl) of cat-el interface" #commented since string is too long for the tutorial-framework, yet it is good to have descriptive names +nodeset 7 Name "cat_side(s)_cat-el_interface" # cathode-side of composite cathode-current collector interface -nodeset 8 surface with x_max <= {-r*cos(theta/360*PI) + tol} in volume 3 4 -#nodeset 8 Name "cat-side (ma) of cat-cc interface" #commented since string is too long for the tutorial-framework, yet it is good to have descriptive names +nodeset 8 surface with z_max <= {-r*cos(theta/360*PI) + tol} in volume 3 4 +nodeset 8 Name "cat_side(t)_cat-cc_interface" # current collector-side of cathode part composite cathode-current collector interface -nodeset 9 surface with x_min >= {-r*cos(theta/360*PI) - tol} and z_max <= {0.5*r*cos(theta/360*PI)} in volume 6 -nodeset 9 surface with x_min >= {-r*cos(theta/360*PI) - tol} and z_min >= {0.5*r*cos(theta/360*PI)} in volume 6 -#nodeset 9 Name "cc-side (sl) of cat-comp_cat-cc interface" #commented since string is too long for the tutorial-framework, yet it is good to have descriptive names +nodeset 9 surface with z_min >= {-r*cos(theta/360*PI) - tol} and x_max <= {r*sin(theta/360*PI)*cos(45/180*PI)+tol} in volume 6 +nodeset 9 surface with z_min >= {-r*cos(theta/360*PI) - tol} and x_min >= {r*cos(theta/360*PI)-r_non_conn-tol} in volume 6 +nodeset 9 Name "cc_side(s)_am_cat-cc_interface" # solid electrolyte-side of composite cathode-current collector interface -nodeset 10 surface with x_max <= {-r*cos(theta/360*PI) + tol} in volume 2 -#nodeset 10 Name "sol-el-side (ma) of comp_cat-cc interface" #commented since string is too long for the tutorial-framework, yet it is good to have descriptive names +nodeset 10 surface with z_max <= {-r*cos(theta/360*PI) + tol} in volume 2 +nodeset 10 Name "el_side(t)_el_cat-cc_interface" # current collector-side of cathode part composite cathode-current collector interface -nodeset 11 surface with x_min >= {-r*cos(theta/360*PI) - tol} and z_min <= {0.5*r*cos(theta/360*PI)} and z_max >= {0.5*r*cos(theta/360*PI)} in volume 6 -#nodeset 11 Name "cc-side (sl) of sol-el-comp_cat-cc interface" #commented since string is too long for the tutorial-framework, yet it is good to have descriptive names +nodeset 11 surface with z_min >= {-r*cos(theta/360*PI) - tol} and x_min == {0.0} and x_max >= {r*sin(theta/360*PI)*sin(45/180*PI) + tol} in volume 6 +nodeset 11 Name "cc_side(s)_el_cat-cc_interface" # cathode-side current collector -nodeset 12 surface with x_max <= {-r*cos(theta/360*PI)-cc_cat} in volume 6 -nodeset 12 Name "cat-side cc" +nodeset 12 surface with z_max <= {-r*cos(theta/360*PI)-cc_cat+tol} in volume 6 +nodeset 12 Name "surface_normal_z_cat_cc" # battery surface normal to y axis # add all surfaces that are normal to the y axis -nodeset 13 surface with y_max <= {-r*cos(theta/360*PI)} in volume all -# remove lines of cathode and anode as they are the slave side nodes -> no DBC can be prescribed here +nodeset 13 surface with y_max <= {-r*cos(theta/360*PI)+tol} in volume all +# remove lines of cathode and anode as they are the source side nodes -> no DBC can be prescribed here nodeset 13 node in surface with not is_plane in volume 3 4 remove -nodeset 13 node in surface with x_min >= {-r*cos(theta/360*PI)-tol} in volume 6 remove -nodeset 13 node in surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 remove -nodeset 13 node in surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 remove -nodeset 13 Name "battery surface normal to y" - -# battery surface normal to z axis -# add all surfaces that are normal to the z axis -nodeset 14 surface with z_max <= {0.0} in volume all -# remove lines of cathode and anode as they are the slave side nodes -> no DBC can be prescribed here +nodeset 13 node in surface with z_min >= {-r*cos(theta/360*PI)-tol} in volume 6 remove +nodeset 13 node in surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 remove +nodeset 13 node in surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 remove +nodeset 13 Name "surface_normal_y" + +# battery surface normal to x axis +# add all surfaces that are normal to the x axis +nodeset 14 surface with x_max <= {tol} in volume all +# remove lines of cathode and anode as they are the source side nodes -> no DBC can be prescribed here nodeset 14 node in surface with not is_plane in volume 3 4 remove -nodeset 14 node in surface with x_min >= {-r*cos(theta/360*PI)-tol} in volume 6 remove -nodeset 14 node in surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 remove -nodeset 14 node in surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 remove -nodeset 14 Name "battery surface normal to z" - -# battery surface which normal vector is (0 1 1) -# add surfaces that are normal to (0 1 1) - vector of volume 1 -nodeset 15 surface with ((x_max - x_min > {an-tol} ) && (y_max - y_min > {0.7071*r*cos(theta/360*PI)} ) && (z_max - z_min > {0.7071*r*cos(theta/360*PI)} )) in volume 1 -# add surfaces that are normal to (0 1 1) - vector of volume 2 & 3 -nodeset 15 surface with ((x_max - x_min > {r+(2*n_c - 1)*r*cos(theta/360*PI) - tol} ) && (y_max - y_min > {0.7071*r*cos(theta/360*PI)} ) && (z_max - z_min > {0.7071*r*cos(theta/360*PI)} ) && is_plane ) in volume 2 & 3 -# add surfaces that are normal to (0 1 1) - vector of volume 4 -nodeset 15 surface with (x_max - x_min > {r_non_conn - tol} ) && y_max > {-r*cos(theta/360*PI) + tol} && is_plane in volume 4 -# add surfaces that are normal to (0 1 1) - vector of volume 5 -nodeset 15 surface with ((x_max - x_min > {cc_an-tol} ) && (y_max - y_min > {0.7071*r*cos(theta/360*PI)} ) && (z_max - z_min > {0.7071*r*cos(theta/360*PI)} )) in volume 5 -# add surfaces that are normal to (0 1 1) - vector of volume 6 -nodeset 15 surface with ((x_max - x_min > {cc_cat-tol} ) && (y_max - y_min > {0.7071*r*cos(theta/360*PI)} ) && (z_max - z_min > {0.7071*r*cos(theta/360*PI)} )) in volume 6 -# remove lines of cathode and anode as they are the slave side nodes -> no DBC can be prescribed here -nodeset 15 node in surface with not is_plane in volume 3 4 remove -nodeset 15 node in surface with x_min >= {-r*cos(theta/360*PI)-tol} in volume 6 remove -nodeset 15 node in surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 remove -nodeset 15 node in surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 remove -#nodeset 15 Name "battery surface normal to (0 1 1) vector" #commented since string is too long for the tutorial-framework, yet it is good to have descriptive names - -# lines in y-direction that need a DBC -nodeset 16 curve with (((x_max - x_min) < {tol}) && ((z_max - z_min) < {tol}) && (x_max <= {-r*cos(theta/360*PI)-cc_cat})) in volume 6 -nodeset 16 curve with (((x_max - x_min) < {tol}) && ((z_max - z_min) < {tol}) && (x_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol})) in volume 5 -nodeset 16 Name "battery curves in y-direction" - -# lines in z-direction that need a DBC -nodeset 17 curve with (((x_max - x_min) < {tol}) && ((y_max - y_min) < {tol}) && (x_max <= {-r*cos(theta/360*PI)-cc_cat})) in volume 6 -nodeset 17 curve with (((x_max - x_min) < {tol}) && ((y_max - y_min) < {tol}) && (x_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol})) in volume 5 -nodeset 17 Name "battery curves in z-direction" - -# all lines in (0 1 -1) direction that need a DBC -nodeset 18 curve with ((y_max - y_min) > {tol} && (z_max - z_min) > {tol} && (x_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol})) in volume 5 -nodeset 18 curve with ((y_max - y_min) > {tol} && (z_max - z_min) > {tol} && (x_max <= {-r*cos(theta/360*PI)-cc_cat})) in volume 6 -#nodeset 18 Name "battery curves in (0 1 -1)-direction" #commented since string is too long for the tutorial-framework, yet it is good to have descriptive names - -# all lines at the battery edges in x-direction -nodeset 19 curve with ((y_max == y_min) && (z_max == z_min)) in volume all -# remove slave side nodes -nodeset 19 node in surface with not is_plane in volume 3 4 remove -nodeset 19 node in surface with x_min >= {-r*cos(theta/360*PI)-tol} in volume 6 remove -nodeset 19 node in surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 remove -nodeset 19 node in surface with x_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 remove -nodeset 19 Name "battery curves in x-direction" +nodeset 14 node in surface with z_min >= {-r*cos(theta/360*PI)-tol} in volume 6 remove +nodeset 14 node in surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 remove +nodeset 14 node in surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 remove +nodeset 14 Name "surface_normal_x" + +# lines in y-direction at cathode-side current collector +nodeset 15 curve with (((z_max - z_min) < {tol}) and ((x_max - x_min) < {tol}) and (z_max <= {-r*cos(theta/360*PI)-cc_cat+tol})) in volume 6 +nodeset 15 Name "curves_y_dir_cat_cc" + +# lines in x-direction at cathode-side current collector +nodeset 16 curve with (((z_max - z_min) < {tol}) and ((y_max - y_min) < {tol}) and (z_max <= {-r*cos(theta/360*PI)-cc_cat+tol})) in volume 6 +nodeset 16 Name "curves_x_dir_cat_cc" + +# all lines at the battery edges in z-direction +nodeset 17 curve with (((x_max - x_min) < {tol}) and ((y_max - y_min) < {tol})) in volume all +# remove source side nodes +nodeset 17 node in surface with not is_plane in volume 3 4 remove +nodeset 17 node in surface with z_min >= {-r*cos(theta/360*PI)-tol} in volume 6 remove +nodeset 17 node in surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 remove +nodeset 17 node in surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 remove +nodeset 17 Name "curves_z_dir" + +# lines in y-direction at anode-side current collector +nodeset 18 curve with (((z_max - z_min) < {tol}) and ((x_max - x_min) < {tol}) and (z_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol})) in volume 5 +nodeset 18 Name "curves_y_dir_an_cc" + +# lines in x-direction at anode-side current collector +nodeset 19 curve with (((z_max - z_min) < {tol}) and ((y_max - y_min) < {tol}) and (z_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol})) in volume 5 +nodeset 19 Name "curves_x_dir_an_cc" # all vertices at anode-side current collector -nodeset 23 vertex in surface with x_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol} in volume 5 -nodeset 23 Name "vertices an-side cc +nodeset 20 vertex in surface with z_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol} in volume 5 +nodeset 20 Name "vertices_an_side_cc" # all vertices at the cathode-side current collector -nodeset 24 vertex in surface with x_max <= {-r*cos(theta/360*PI)-cc_cat} in volume 6 -nodeset 24 Name "vertices cat-side cc" +nodeset 21 vertex in surface with z_max <= {-r*cos(theta/360*PI)-cc_cat+tol} in volume 6 +nodeset 21 Name "vertices_cat_side_cc" + +# battery surface which normal vector is (1 1 0) +# add surfaces that are normal to (1 1 0) - vector of volume 1 +nodeset 22 surface with ((z_max - z_min > {an-tol} ) and (y_max - y_min > {0.7071*r*cos(theta/360*PI)} ) and (x_max - x_min > {0.7071*r*cos(theta/360*PI)} )) in volume 1 +# add surfaces that are normal to (1 1 0) - vector of volume 2 & 3 +nodeset 22 surface with ((z_max - z_min > {r+(2*n_c - 1)*r*cos(theta/360*PI) - tol} ) and (y_max - y_min > {0.7071*r*cos(theta/360*PI)} ) and (x_max - x_min > {0.7071*r*cos(theta/360*PI)} ) and is_plane ) in volume 2 3 +# add surfaces that are normal to (1 1 0) - vector of volume 4 +nodeset 22 surface with (z_max - z_min > {r_non_conn - tol} ) and y_max > {-r*cos(theta/360*PI) + tol} and is_plane in volume 4 +# add surfaces that are normal to (1 1 0) - vector of volume 5 +nodeset 22 surface with ((z_max - z_min > {cc_an-tol} ) and (y_max - y_min > {0.7071*r*cos(theta/360*PI)} ) and (x_max - x_min > {0.7071*r*cos(theta/360*PI)} )) in volume 5 +# add surfaces that are normal to (1 1 0) - vector of volume 6 +nodeset 22 surface with ((z_max - z_min > {cc_cat-tol} ) and (y_max - y_min > {0.7071*r*cos(theta/360*PI)} ) and (x_max - x_min > {0.7071*r*cos(theta/360*PI)} )) in volume 6 +# remove lines of cathode and anode as they are the source side nodes -> no DBC can be prescribed here +nodeset 22 node in surface with not is_plane in volume 3 4 remove +nodeset 22 node in surface with z_min >= {-r*cos(theta/360*PI)-tol} in volume 6 remove +nodeset 22 node in surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+tol} in volume 5 remove +nodeset 22 node in surface with z_max <= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+tol} in volume 1 remove +nodeset 22 Name "surface_normal_(1_1_0)" + +# lines in (-1 1 0) direction at cathode-side current collector +nodeset 23 curve with ((y_max - y_min) > {tol} and (x_max - x_min) > {tol} and (z_max <= {-r*cos(theta/360*PI)-cc_cat+tol})) in volume 6 +nodeset 23 Name "curves_(-1_1_0)_dir_cat_cc" + +# lines in (-1 1 0) direction at anode-side current collector +nodeset 24 curve with ((y_max - y_min) > {tol} and (x_max - x_min) > {tol} and (z_min >= {(2*n_c-3)*r*cos(theta/360*PI)+2*r+sep+an+cc_an-tol})) in volume 5 +nodeset 24 Name "curves_(-1_1_0)_dir_an_cc" $ -------------------------- $ | scaling | @@ -289,5 +296,5 @@ volume all scale {scaling} $ -------------------------- $ | export | $ -------------------------- -export genesis "tutorial_battery.e" block all dimension 3 overwrite +export mesh "tutorial_battery.e" dimension 3 overwrite exit From 16af4b98f5aa8127fa7e1313e1b5ed5a903e2fbf Mon Sep 17 00:00:00 2001 From: Christoph Schmidt Date: Tue, 16 Jun 2026 16:56:17 +0200 Subject: [PATCH 16/28] Adapt fsi 2D tutorial --- tests/tutorials/fsi/tutorial_fsi_2d.4C.yaml | 42 +++++++------------- tests/tutorials/fsi/tutorial_fsi_2d.e | Bin 60712 -> 65012 bytes tests/tutorials/fsi/tutorial_fsi_2d.jou | 28 ++++++------- 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/tests/tutorials/fsi/tutorial_fsi_2d.4C.yaml b/tests/tutorials/fsi/tutorial_fsi_2d.4C.yaml index 8eaca9db877..74dde5e62a0 100644 --- a/tests/tutorials/fsi/tutorial_fsi_2d.4C.yaml +++ b/tests/tutorials/fsi/tutorial_fsi_2d.4C.yaml @@ -142,85 +142,71 @@ FLUID GEOMETRY: NA: ALE DESIGN POINT DIRICH CONDITIONS: - - E: 3 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_vertices NUMDOF: 2 ONOFF: [1, 1] VAL: [0, 0] FUNCT: [0, 0] - - E: 4 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_fsi_vertices NUMDOF: 2 ONOFF: [1, 1] VAL: [0, 0] FUNCT: [0, 0] - - E: 10 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow_vertices_top NUMDOF: 3 ONOFF: [1, 1, 0] VAL: [1, 0, 0] FUNCT: [1, 0, 0] - - E: 11 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_vertices NUMDOF: 3 ONOFF: [1, 1, 0] VAL: [0, 0, 0] FUNCT: [0, 0, 0] - - E: 12 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: fluid_fsi_vertices NUMDOF: 3 ONOFF: [1, 1, 0] VAL: [0, 0, 0] FUNCT: [0, 0, 0] DESIGN LINE DIRICH CONDITIONS: - - E: 1 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_clamping_curves NUMDOF: 2 ONOFF: [1, 1] VAL: [0, 0] FUNCT: [0, 0] - - E: 5 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_wall_curves NUMDOF: 3 ONOFF: [1, 1, 0] VAL: [0, 0, 0] FUNCT: [0, 0, 0] - - E: 6 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow_volume_curve_top NUMDOF: 3 ONOFF: [1, 1, 0] VAL: [1, 0, 0] FUNCT: [1, 0, 0] - - E: 7 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow_area_curve NUMDOF: 3 ONOFF: [1, 1, 0] VAL: [1, 0, 0] FUNCT: [2, 0, 0] DESIGN POINT ALE DIRICH CONDITIONS: - - E: 13 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: fluid_vertices_all NUMDOF: 2 ONOFF: [1, 1] VAL: [0, 0] FUNCT: [0, 0] DESIGN LINE ALE DIRICH CONDITIONS: - - E: 6 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow_volume_curve_top NUMDOF: 2 ONOFF: [1, 1] VAL: [0, 0] FUNCT: [0, 0] - - E: 8 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: fluid_curves_in_y-direction NUMDOF: 2 ONOFF: [1, 1] VAL: [0, 0] FUNCT: [0, 0] DESIGN FSI COUPLING LINE CONDITIONS: - - E: 2 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_fsi_curve coupling_id: 1 - - E: 9 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: fluid_fsi_curve coupling_id: 1 diff --git a/tests/tutorials/fsi/tutorial_fsi_2d.e b/tests/tutorials/fsi/tutorial_fsi_2d.e index abd53d8d42bec46c1c5679f2eee3f443fc42adef..42d5c2609279bfe0e12462dfe4b8de44df94055b 100644 GIT binary patch delta 3702 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 MnNmA96DL>y0f&!^{Qv*} diff --git a/tests/tutorials/fsi/tutorial_fsi_2d.jou b/tests/tutorials/fsi/tutorial_fsi_2d.jou index 49a341b228a..2e3881417e5 100644 --- a/tests/tutorials/fsi/tutorial_fsi_2d.jou +++ b/tests/tutorials/fsi/tutorial_fsi_2d.jou @@ -199,15 +199,15 @@ block 1 name "flexible_bottom" $ curves nodeset 1 curve in structure_ycurves -nodeset 1 name "structure clamping curves" +nodeset 1 name "structure_clamping_curves" nodeset 2 curve in group structure_fsi_xcurves -nodeset 2 name "structure fsi curve" +nodeset 2 name "structure_fsi_curve" $ vertices nodeset 3 vertex in group structure_vertex -nodeset 3 name "structure vertices" +nodeset 3 name "structure_vertices" nodeset 4 vertex in group structure_vertex_fsi -nodeset 4 name "structure fsi vertices" +nodeset 4 name "structure_fsi_vertices" $======================= Fluid $ surfaces @@ -216,25 +216,25 @@ block 2 name "fluid" $ curves nodeset 5 curve in group cavity_ycurves -nodeset 5 name "cavity wall curves" +nodeset 5 name "cavity_wall_curves" nodeset 6 curve in group inflow_vol_xcurves_top -nodeset 6 name "inflow volume curve top" +nodeset 6 name "inflow_volume_curve_top" nodeset 7 curve in group inflow_ycurves -nodeset 7 name "inflow area curve" +nodeset 7 name "inflow_area_curve" nodeset 8 curve in group fluid_ycurves -nodeset 8 name "fluid curves in y-direction" +nodeset 8 name "fluid_curves_in_y-direction" nodeset 9 curve in group cavity_fsi_xcurves -nodeset 9 name "fluid fsi curve" +nodeset 9 name "fluid_fsi_curve" $ vertices nodeset 10 vertex in group inflow_vertex_top -nodeset 10 name "inflow vertices top" +nodeset 10 name "inflow_vertices_top" nodeset 11 vertex in group cavity_vertex -nodeset 11 name "cavity vertices" +nodeset 11 name "cavity_vertices" nodeset 12 vertex in group fluid_vertex_fsi -nodeset 12 name "fluid fsi vertices" +nodeset 12 name "fluid_fsi_vertices" nodeset 13 vertex in group fluid_vertex -nodeset 13 name "fluid vertices all" +nodeset 13 name "fluid_vertices_all" $======================= export mesh -export mesh "tutorial_fsi.e" block all dimension 2 overwrite +export mesh "tutorial_fsi_2d.e" block all dimension 2 overwrite From ba70f26e52fc5f40315d14f52e67026cc62fddc9 Mon Sep 17 00:00:00 2001 From: Christoph Schmidt Date: Tue, 16 Jun 2026 18:35:09 +0200 Subject: [PATCH 17/28] Adapt fsi 3D tutorial --- tests/tutorials/fsi/tutorial_fsi_3d.4C.yaml | 183 +++++++------------- tests/tutorials/fsi/tutorial_fsi_3d.e | Bin 161832 -> 188092 bytes tests/tutorials/fsi/tutorial_fsi_3d.jou | 72 ++++---- 3 files changed, 97 insertions(+), 158 deletions(-) diff --git a/tests/tutorials/fsi/tutorial_fsi_3d.4C.yaml b/tests/tutorials/fsi/tutorial_fsi_3d.4C.yaml index b8c7c0b6985..d758c102360 100644 --- a/tests/tutorials/fsi/tutorial_fsi_3d.4C.yaml +++ b/tests/tutorials/fsi/tutorial_fsi_3d.4C.yaml @@ -105,369 +105,308 @@ FLUID GEOMETRY: NA: ALE DESIGN POINT DIRICH CONDITIONS: - - E: 32 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_vertex_front_left_bottom NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 33 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_vertex_back_left_bottom NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 34 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_vertex_back_right_bottom NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 35 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_vertex_front_right_bottom NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 36 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity-inflow_vertex_front_1 NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 36 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity-inflow_vertex_front_1 NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 38 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_vertex_front_left NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [1, 0, 0, 0] FUNCT: [1, null, null, null] - - E: 39 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_vertex_back_left NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [1, 0, 0, 0] FUNCT: [1, null, null, null] DESIGN LINE DIRICH CONDITIONS: - - E: 6 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_edge_front_left NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 7 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_edge_back_left NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 8 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_edge_back_right NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 9 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_edge_front_right NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 18 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_front_left NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 19 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_back_left NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 20 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_back_right NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 21 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_front_right NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 22 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_front_bottom NUMDOF: 4 ONOFF: [0, 0, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 23 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_back_bottom NUMDOF: 4 ONOFF: [0, 0, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 24 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_left_bottom NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 25 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_right_bottom NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 26 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity-inflow_edge NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 27 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow_edge_front NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [1, 0, 0, 0] FUNCT: [2, null, null, null] - - E: 28 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow_edge_back NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [1, 0, 0, 0] FUNCT: [2, null, null, null] - - E: 29 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_edge_left NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [1, 0, 0, 0] FUNCT: [1, null, null, null] - - E: 30 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_edge_front NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [1, 0, 0, 0] FUNCT: [1, null, null, null] - - E: 31 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_edge_back NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [1, 0, 0, 0] FUNCT: [1, null, null, null] DESIGN SURF DIRICH CONDITIONS: - - E: 1 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_surface_left NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 2 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_surface_right NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 3 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_surface_front NUMDOF: 3 ONOFF: [0, 0, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 4 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_surface_back NUMDOF: 3 ONOFF: [0, 0, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 10 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_wall_left NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 11 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_wall_right NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 12 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: fluid_wall_front NUMDOF: 4 ONOFF: [0, 0, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 13 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: fluid_wall_back NUMDOF: 4 ONOFF: [0, 0, 1, 0] VAL: [0, 0, 0, 0] FUNCT: [null, null, null, null] - - E: 15 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [1, 0, 0, 0] FUNCT: [1, null, null, null] - - E: 16 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow NUMDOF: 4 ONOFF: [1, 1, 1, 0] VAL: [1, 0, 0, 0] FUNCT: [2, null, null, null] DESIGN POINT ALE DIRICH CONDITIONS: - - E: 36 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity-inflow_vertex_front_1 NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 37 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity-inflow_vertex_front_2 NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 38 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_vertex_front_left NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 39 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_vertex_back_left NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] DESIGN LINE ALE DIRICH CONDITIONS: - - E: 18 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_front_left NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 19 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_back_left NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 20 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_back_right NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 21 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_front_right NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 24 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_left_bottom NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 25 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_edge_right_bottom NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 26 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity-inflow_edge NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 27 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow_edge_front NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 28 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow_edge_back NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 29 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_edge_left NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 30 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_edge_front NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 31 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid_edge_back NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] DESIGN SURF ALE DIRICH CONDITIONS: - - E: 10 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_wall_left NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 11 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: cavity_wall_right NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 12 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: fluid_wall_front NUMDOF: 3 ONOFF: [0, 0, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 13 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: fluid_wall_back NUMDOF: 3 ONOFF: [0, 0, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 15 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: lid NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 16 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: inflow NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] - - E: 17 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: outflow NUMDOF: 3 ONOFF: [1, 1, 1] VAL: [0, 0, 0] FUNCT: [null, null, null] DESIGN FSI COUPLING SURF CONDITIONS: - - E: 5 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: structure_coupling_surface coupling_id: 1 - - E: 14 - ENTITY_TYPE: node_set_id + - NODE_SET_NAME: fluid_coupling_surface coupling_id: 1 diff --git a/tests/tutorials/fsi/tutorial_fsi_3d.e b/tests/tutorials/fsi/tutorial_fsi_3d.e index 376ddba1199cb28ed32000b8b239cfde9309bc44..8d64ec0e8098795c1f46ac8bbafcdc86414b1847 100644 GIT binary patch delta 16622 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 Date: Wed, 13 May 2026 11:02:23 +0200 Subject: [PATCH 18/28] Further cleanup Local Newton in preparation for the Adaptive Estimate Interpolation: - The term 'constitutive update' is now used instead of 'return mapping' to avoid confusion, since our constitutive update also comprises the elastic predictor verification. Several frameworks in literature use 'return mapping' to comprise both stages, but we want to make this clear here. - Added struct for tracking all deformation tensors used for the local integration routines. These are then used consistently throughout the constitutive update routines. - Improved error handling by adding error registration settings, and only outputting detailed errors. Plastic strain rate derivative checks are now disabled by default, which has some implications for the substepping test -> changed results. Also, functions are guarded to only be evaluated if there are no evaluation errors currently. - Added tracking of plastic flow at each Gauss point to improve plasticity checks, such as the ones in the linearization and the update procedures. The update procedures are run separately per Gauss point. - Also added characteristic for viscoplastic laws: do they use yield surface or not? Important for the AEI subsequently. - Incorporated further logic from the viscoplastic inelastic factor to the dedicated Local Newton manager, such as solution and convergence quantities tracking and checking. - Added a dedicated unit tests file for the service of inelastic deformation gradient factors. - In preparation for the AEI: a method dedicated to determining the Local Newton estimate was used. This method will serve as the entry point for the AEI, along with manage_evaluation, which will be responsible for re-estimation. - Substepping: now the deformation gradient is interpolated, instead of the right CG tensor. This is also done in preparation for the AEI, to enable combining it with substepping. Integrate feedback --- ...4C_global_legacy_module_validmaterials.cpp | 122 ++-- src/mat/4C_mat_inelastic_defgrad_factors.cpp | 553 +++++++++--------- src/mat/4C_mat_inelastic_defgrad_factors.hpp | 161 +++-- ..._mat_inelastic_defgrad_factors_service.cpp | 169 +++++- ..._mat_inelastic_defgrad_factors_service.hpp | 161 ++++- src/mat/vplast/4C_mat_vplast_law.cpp | 16 +- src/mat/vplast/4C_mat_vplast_law.hpp | 57 +- .../4C_mat_vplast_reform_johnsoncook.cpp | 44 +- .../4C_mat_vplast_reform_johnsoncook.hpp | 18 +- ...at_iso_viscoplast_refJC_log_timint.4C.yaml | 5 + ...plast_refJC_log_timint_substepping.4C.yaml | 14 +- ...inelastic_defgrad_factors_service_test.cpp | 420 +++++++++++++ .../mat/4C_inelastic_defgrad_factors_test.cpp | 104 ++-- .../4C_vplast_reform_johnsoncook_test.cpp | 161 +++-- 14 files changed, 1416 insertions(+), 589 deletions(-) create mode 100644 unittests/mat/4C_inelastic_defgrad_factors_service_test.cpp diff --git a/src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp b/src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp index ee5e2145361..72bfed185c1 100644 --- a/src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp +++ b/src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp @@ -11,6 +11,7 @@ #include "4C_inpar_structure.hpp" #include "4C_io_input_field.hpp" #include "4C_io_input_spec_builders.hpp" +#include "4C_io_input_spec_storage.hpp" #include "4C_io_input_spec_validators.hpp" #include "4C_linalg_tensor_generators.hpp" #include "4C_linalg_utils_densematrix_funct.hpp" @@ -2814,6 +2815,8 @@ std::unordered_map Global::v /*----------------------------------------------------------------------*/ { using namespace Core::IO::InputSpecBuilders::Validators; + namespace ViscoplastUtils = Mat::InelasticDefgradTransvIsotropElastViscoplastUtils; + known_materials[Core::Materials::mfi_transv_isotrop_elast_viscoplast] = group( "MAT_InelasticDefgradTransvIsotropElastViscoplast", {parameter( @@ -2843,34 +2846,19 @@ std::unordered_map Global::v "yield condition: parameter F, following the " "notation in Dafalias 1989, International " "Journal of Plasticity, Vol. 5"}), - parameter( + parameter( "MAT_BEHAVIOR", {.description = "Material behavior / anisotropy type"}), - parameter( - "TIME_INTEGRATION_HIST_VARS", + parameter("TIME_INTEGRATION_HIST_VARS", {.description = "time integration of internal variables: standard | logarithmic " "(logarithmic transformation of the " "evolution equation for the plastic deformation gradient -> default)", - .default_value = Mat::InelasticDefgradTransvIsotropElastViscoplastUtils:: - TimIntType::logarithmic}), - parameter( - "LINEARIZATION", + .default_value = ViscoplastUtils::TimIntType::logarithmic}), + parameter("LINEARIZATION", {.description = "utilized material linearization: analytic | perturb_based (based on " "perturbations of the current state)", - .default_value = Mat::InelasticDefgradTransvIsotropElastViscoplastUtils:: - LinearizationType::analytic}), - parameter("MAX_PLASTIC_STRAIN_INCR", - {.description = "maximum evaluable plastic strain increment " - "used for verifying overflow errors", - .default_value = std::exp(30.0), - .validator = positive()}), - parameter("MAX_PLASTIC_STRAIN_DERIV_INCR", - {.description = "maximum evaluable increment of the plastic strain derivatives " - "w.r.t. plastic strain and equivalent stress, used for verifying " - "possible overflow errors", - .default_value = std::exp(30.0), - .validator = positive()}), + .default_value = ViscoplastUtils::LinearizationType::analytic}), parameter("MATRIX_EXP_CALC_METHOD", {.description = "chosen computation method for matrix exponential (default: " "automatic method selection based on matrix characteristics)", @@ -2903,20 +2891,22 @@ std::unordered_map Global::v {.description = "Settings for the usage of local substepping to integrate the " "viscoplastic evolution equations", .required = false}), - group("LOCAL_NEWTON", - {parameter< - Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck>( - "CONV_CHECK", + group("LOCAL_NEWTON", + {parameter("CONV_CHECK", {.description = "convergence check type", - .default_value = Mat::InelasticDefgradTransvIsotropElastViscoplastUtils:: - LocalNewtonConvCheck::residual_and_increment_ratio}), - parameter("MAX_ITER", {.description = "maximum number of iterations", - .default_value = 100, - .validator = positive()}), - parameter( - "RES_TOL", {.description = "residual tolerance (absolute residual 2-norm)", - .default_value = 1.0e-8, - .validator = positive()}), + .default_value = + ViscoplastUtils::LocalNewtonConvCheck::residual_and_increment_ratio, + .store = in_struct(&ViscoplastUtils::LocalNewtonParams::conv_check)}), + parameter("MAX_ITER", + {.description = "maximum number of iterations", + .default_value = 100, + .validator = positive(), + .store = in_struct(&ViscoplastUtils::LocalNewtonParams::max_iter)}), + parameter("RES_TOL", + {.description = "residual tolerance (absolute residual 2-norm)", + .default_value = 1.0e-8, + .validator = positive(), + .store = in_struct(&ViscoplastUtils::LocalNewtonParams::res_tol)}), parameter("MAX_EXCEEDANCE_FACT_RES_TOL", {.description = "maximum exceedance factor for the specified residual tolerance " @@ -2924,12 +2914,17 @@ std::unordered_map Global::v "continuing the simulation, if specified by the user via " "DIVER_CONT)", .default_value = 1.0e1, - .validator = positive_or_zero()}), - parameter( - "INCR_TOL", {.description = "increment tolerance (" - "ratio of |increment| / |solution|)", - .default_value = 1.0e-8, - .validator = positive()}), + .validator = positive_or_zero(), + .store = in_struct( + &ViscoplastUtils::LocalNewtonParams::max_exceedance_fact_res_tol)}), + parameter("INCR_TOL", + {.description = "increment tolerance (" + "ratio of |increment| / |solution|)", + .default_value = 1.0e-8, + .validator = positive(), + .store = in_struct(&ViscoplastUtils::LocalNewtonParams::incr_tol) + + }), parameter("MAX_EXCEEDANCE_FACT_INCR_TOL", {.description = "maximum exceedance factor for the specified increment tolerance " @@ -2937,17 +2932,54 @@ std::unordered_map Global::v "continuing the simulation, if specified by the user via " "DIVER_CONT)", .default_value = 1.0e1, - .validator = positive_or_zero()}), - parameter("DIVER_CONT", + .validator = positive_or_zero(), + .store = in_struct( + &ViscoplastUtils::LocalNewtonParams::max_exceedance_fact_incr_tol) + + }), + parameter("DIVER_CONT", {.description = "strategy to deal with divergence in the Local Newton Loop", - .default_value = - Mat::InelasticDefgradTransvIsotropElastViscoplastUtils:: - LocalNewtonDiverCont::stop}) + .default_value = ViscoplastUtils::LocalNewtonDiverCont::stop, + .store = in_struct(&ViscoplastUtils::LocalNewtonParams::diver_cont) + + }) }, {.description = "Parameters used in the Local Newton--Raphson procedure " "(viscoplastic corrector stage)", + .required = false}), + group("ERROR_REGISTRATION_SETTINGS", + {parameter("REGISTER_PLASTIC_STRAIN_INCR_OVERFLOW", + {.description = "should overflow error be registered via ErrorType when the " + "plastic strain increment exceeds the specified tolerance?", + .default_value = true, + .store = in_struct(&ViscoplastUtils::ErrorRegistrationSettings:: + register_plastic_strain_incr_overflow)}), + parameter("MAX_PLASTIC_STRAIN_INCR", + {.description = "maximum evaluable plastic strain increment " + "used for registering overflow errors", + .default_value = std::exp(30.0), + .validator = positive(), + .store = in_struct(&ViscoplastUtils::ErrorRegistrationSettings:: + max_plastic_strain_incr)}), + parameter("REGISTER_PLASTIC_STRAIN_DERIV_INCR_OVERFLOW", + {.description = "should overflow error be registered via ErrorType when " + "any of the plastic strain derivative increments exceeds " + "the specified tolerance?", + .default_value = false, + .store = in_struct(&ViscoplastUtils::ErrorRegistrationSettings:: + register_plastic_strain_deriv_incr_overflow)}), + parameter("MAX_PLASTIC_STRAIN_DERIV_INCR", + {.description = "maximum evaluable increment of the plastic strain " + "derivatives w.r.t. plastic strain and equivalent " + "stress, used for registering " + "overflow errors", + .default_value = std::exp(30.0), + .validator = positive(), + .store = in_struct(&ViscoplastUtils::ErrorRegistrationSettings:: + max_plastic_strain_deriv_incr)})}, + {.description = "Settings for registering errors within the procedures used for " + "constitutive update", .required = false})}, {.description = "Versatile transversely isotropic (or isotropic) viscoplasticity model for " "finite deformations with isotropic hardening, using user-defined " diff --git a/src/mat/4C_mat_inelastic_defgrad_factors.cpp b/src/mat/4C_mat_inelastic_defgrad_factors.cpp index b7904dd8445..b000491ab96 100644 --- a/src/mat/4C_mat_inelastic_defgrad_factors.cpp +++ b/src/mat/4C_mat_inelastic_defgrad_factors.cpp @@ -8,6 +8,7 @@ #include "4C_mat_inelastic_defgrad_factors.hpp" #include "4C_comm_mpi_utils.hpp" +#include "4C_comm_pack_helpers.hpp" #include "4C_fem_discretization.hpp" #include "4C_global_data.hpp" #include "4C_legacy_enum_definitions_materials.hpp" @@ -475,26 +476,6 @@ namespace Core::LinAlg::EigenvalInterpolationType::LOG, interp_param_list}; } - Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonParams - retrieve_local_newton_params(const Core::Mat::PAR::Parameter::Data& matdata) - { - const auto local_newton_params = ViscoplastUtils::LocalNewtonParams{ - .res_tol = matdata.parameters.group("LOCAL_NEWTON").get("RES_TOL"), - .incr_tol = matdata.parameters.group("LOCAL_NEWTON").get("INCR_TOL"), - .conv_check = matdata.parameters.group("LOCAL_NEWTON") - .get("CONV_CHECK"), - .diver_cont = matdata.parameters.group("LOCAL_NEWTON") - .get("DIVER_CONT"), - .max_iter = static_cast( - matdata.parameters.group("LOCAL_NEWTON").get("MAX_ITER")), - .max_exceedance_fact_res_tol = - matdata.parameters.group("LOCAL_NEWTON").get("MAX_EXCEEDANCE_FACT_RES_TOL"), - .max_exceedance_fact_incr_tol = - matdata.parameters.group("LOCAL_NEWTON").get("MAX_EXCEEDANCE_FACT_INCR_TOL"), - }; - - return local_newton_params; - } bool show_warnings(const unsigned int ele_gid) { @@ -701,9 +682,6 @@ Mat::PAR::InelasticDefgradTransvIsotropElastViscoplast:: matdata.parameters.get("TIME_INTEGRATION_HIST_VARS")), linearization_type_( matdata.parameters.get("LINEARIZATION")), - max_plastic_strain_incr_(matdata.parameters.get("MAX_PLASTIC_STRAIN_INCR")), - max_plastic_strain_deriv_incr_( - matdata.parameters.get("MAX_PLASTIC_STRAIN_DERIV_INCR")), use_local_substepping_( matdata.parameters.group("LOCAL_SUBSTEPPING").get("USE_SUBSTEPPING")), max_local_substepping_halve_num_(static_cast( @@ -718,7 +696,11 @@ Mat::PAR::InelasticDefgradTransvIsotropElastViscoplast:: mat_log_deriv_calc_method_( matdata.parameters.get( "MATRIX_LOG_DERIV_CALC_METHOD")), - local_newton_params_(retrieve_local_newton_params(matdata)) + local_newton_params_( + matdata.parameters.get("LOCAL_NEWTON")), + error_registration_settings_( + matdata.parameters.get( + "ERROR_REGISTRATION_SETTINGS")) { // consistency check: yield parameters in case of transversely-isotropic behavior const bool all_yield_cond_param_specified = @@ -845,7 +827,8 @@ std::shared_ptr Mat::InelasticDefgradFactors::fact dynamic_cast(current_material); // create viscoplastic law - auto viscoplastic_law = Mat::Viscoplastic::Law::factory(params->viscoplastic_law_id()); + auto viscoplastic_law = Mat::Viscoplastic::Law::factory( + params->viscoplastic_law_id(), params->error_registration_settings()); // construct fiber reader auto* fiber_reader_params = Global::Problem::instance(probinst)->materials()->parameter_by_id( @@ -1814,6 +1797,9 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::InelasticDefgradTransvIsotrop // initialize time step quantities time_step_quantities_.init(ref_temperature_); + + // initialize vector tracking plastic flow for a single Gauss point; we resize it afterwards + is_plastic_gp_.resize(1, false); } @@ -1856,9 +1842,9 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::pre_evaluate( } // set time step - FOUR_C_ASSERT(context.time_step_size, "Time step size not given in evaluation context."); + FOUR_C_ASSERT_ALWAYS(context.time_step_size, "Time step size not given in evaluation context."); time_step_tracker_.dt = *context.time_step_size; - FOUR_C_ASSERT(context.total_time, "Total time not given in evaluation context."); + FOUR_C_ASSERT_ALWAYS(context.total_time, "Total time not given in evaluation context."); time_step_tracker_.tnp = *context.total_time; // set minimum substep length @@ -1875,18 +1861,6 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::pre_evaluate( viscoplastic_law_->pre_evaluate(params, gp); } -/*--------------------------------------------------------------------* - *--------------------------------------------------------------------*/ -void Mat::InelasticDefgradTransvIsotropElastViscoplast::prepare_return_mapping() -{ - // pre-evaluate viscoplastic law - viscoplastic_law_->pre_evaluate(params_, gp_); - - // reset local iteration count - local_newton_manager_.set_iteration_count(0); -} - - /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ void Mat::InelasticDefgradTransvIsotropElastViscoplast::calculate_gamma_delta( @@ -1926,6 +1900,8 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantities( ViscoplastUtils::ErrorType& err_status, const double dt, const ViscoplastUtils::StateQuantityEvalType& eval_type) const { + ensure_error_free_evaluation(err_status); + ViscoplastUtils::StateQuantities state_quantities{}; state_quantities.eval_type = eval_type; @@ -2078,9 +2054,8 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantities( // calculate equivalent plastic strain rate using the viscoplastic law - state_quantities.curr_equiv_plastic_strain_rate = - viscoplastic_law_->evaluate_plastic_strain_rate(state_quantities.curr_equiv_stress, - plastic_strain, dt, parameter()->max_plastic_strain_incr(), err_status, update_hist_var_); + state_quantities.curr_equiv_plastic_strain_rate = viscoplastic_law_->evaluate_plastic_strain_rate( + state_quantities.curr_equiv_stress, plastic_strain, dt, err_status, update_hist_var_); if (eval_type == ViscoplastUtils::StateQuantityEvalType::plastic_strain_rate_only) { @@ -2200,6 +2175,9 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantity_deriv ViscoplastUtils::ErrorType& err_status, const double dt, const ViscoplastUtils::StateQuantityDerivEvalType& eval_type, const bool eval_state) const { + ensure_error_free_evaluation(err_status); + + ViscoplastUtils::StateQuantityDerivatives state_quantity_derivatives{}; state_quantity_derivatives.eval_type = eval_type; @@ -2554,8 +2532,8 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantity_deriv // compute the relevant derivatives of the plastic strain rate InelasticDefgradTransvIsotropElastViscoplastUtils::PlasticStrainRateDerivs evoEqFunctionDers = - viscoplastic_law_->evaluate_derivatives_of_plastic_strain_rate(equiv_stress, plastic_strain, - dt, parameter()->max_plastic_strain_deriv_incr(), err_status); + viscoplastic_law_->evaluate_derivatives_of_plastic_strain_rate( + equiv_stress, plastic_strain, dt, err_status); // return if we get an error, all other calculations are useless since substepping is // triggered @@ -2726,6 +2704,9 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_additional_cmat { const ReducedKinematics reduced_kinematics = evaluate_reduced_kinematics(*defgrad, iFin_other); const double temperature = time_step_quantities_.current_temperature[gp_]; + // calculate linearization term only if we have plastic flow + if (!is_plastic_gp_[gp_]) return; + if (parameter()->linearization_type() == ViscoplastUtils::LinearizationType::perturbation_based) { @@ -2938,7 +2919,7 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_taylor_quinney_heat_ if (not is_current_state) { // recompute the current history variables for the incoming state. This also sets the new state. - return_mapping(reduced_kinematics.defgrad, temperature); + constitutive_update(reduced_kinematics.defgrad, temperature); } // evaluate the relevant linearizations, using cached values when available @@ -3008,7 +2989,7 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_inverse_inelast // temperature was set by pre_evaluate const double temperature = params_.isParameter("temperature") ? params_.get("temperature") : ref_temperature_; - iFinM = return_mapping(reduced_kinematics.defgrad, temperature).inv_plastic_defgrad; + iFinM = constitutive_update(reduced_kinematics.defgrad, temperature).inv_plastic_defgrad; } /*--------------------------------------------------------------------* @@ -3178,20 +3159,21 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_history_variables_wr } Mat::InelasticDefgradTransvIsotropElastViscoplast::HistoryVariables -Mat::InelasticDefgradTransvIsotropElastViscoplast::return_mapping( +Mat::InelasticDefgradTransvIsotropElastViscoplast::constitutive_update( const Core::LinAlg::Matrix<3, 3>& FredM, const double temperature) { - // declare output: history variables (after return mapping) + // declare output: history variables (after the constitutive update) HistoryVariables result; - // compute right CG tensor corresponding to the given deformation gradient - Core::LinAlg::Matrix<3, 3> CredM(Core::LinAlg::Initialization::zero); - CredM.multiply_tn(1.0, FredM, FredM, 0.0); + // construct struct containing deformation tensors used for local integration + ViscoplastUtils::LocalIntegrationDeformationTensors deftensors( + FredM, time_step_quantities_.last_plastic_defgrad_inverse[gp_]); // perform non-repeatable pre-evaluation tasks (non-repeatable: not // called in the redundant evaluate call, which is already handled -> direct return // without calling this function) - prepare_return_mapping(); + viscoplastic_law_->pre_evaluate(params_, gp_); + is_plastic_gp_[gp_] = false; // set predictor: assume purely elastic behavior in this time step Core::LinAlg::Matrix<3, 3> iFinM_pred(Core::LinAlg::Initialization::zero); @@ -3201,13 +3183,13 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::return_mapping( ViscoplastUtils::ErrorType err_status = ViscoplastUtils::ErrorType::no_errors; // set current defgrad and current right CG tensor - time_step_quantities_.current_defgrad[gp_] = FredM; - time_step_quantities_.current_rightCG[gp_] = CredM; + time_step_quantities_.current_defgrad[gp_] = deftensors.defgrad; + time_step_quantities_.current_rightCG[gp_] = deftensors.right_cg; time_step_quantities_.current_temperature[gp_] = temperature; thermo_mechanical_coupling_cache_.reset(gp_); // check whether the predictor is the solution (no plastic strain during this time step) - bool pred_is_sol = - check_elastic_predictor(CredM, temperature, iFinM_pred, plastic_strain_pred, err_status); + bool pred_is_sol = check_elastic_predictor( + deftensors.right_cg, temperature, iFinM_pred, plastic_strain_pred, err_status); if ((err_status == ViscoplastUtils::ErrorType::no_errors) && (pred_is_sol)) { // update inverse inelastic defgrad and plastic strain @@ -3216,19 +3198,19 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::return_mapping( } else // predictor does not suffice { + is_plastic_gp_[gp_] = true; + err_status = ViscoplastUtils::ErrorType::no_errors; // perform local time integration - Core::LinAlg::Matrix<10, 1> x = wrap_unknowns(iFinM_pred, plastic_strain_pred); - Core::LinAlg::Matrix<10, 1> sol = viscoplastic_correction(FredM, temperature, x, err_status); + Core::LinAlg::Matrix<10, 1> sol = viscoplastic_correction(deftensors, temperature, err_status); // throw error if the Local Newton Loop cannot be evaluated with the given substepping // settings if (err_status != ViscoplastUtils::ErrorType::no_errors) { // output error and then throw (in order to display the error on // the right processor) - const std::string extended_message = - get_error_info(Mat::InelasticDefgradTransvIsotropElastViscoplastUtils:: - get_detailed_error_message_for_error_type(err_status)); - FOUR_C_THROW("{}", extended_message); + FOUR_C_THROW("{}", get_error_warning_info(std::format( + "Viscoplastic correction was not successful! Error status: {}", + EnumTools::enum_name(err_status)))); } // update inverse inelastic defgrad and plastic strain @@ -3242,8 +3224,8 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::return_mapping( time_step_quantities_.current_plastic_defgrad_inverse[gp_] = result.inv_plastic_defgrad; time_step_quantities_.current_plastic_strain[gp_] = result.plastic_strain; time_step_quantities_.current_equiv_stress[gp_] = state_quantities_.curr_equiv_stress; - time_step_quantities_.current_rightCG[gp_] = CredM; - time_step_quantities_.current_defgrad[gp_] = FredM; + time_step_quantities_.current_rightCG[gp_] = deftensors.right_cg; + time_step_quantities_.current_defgrad[gp_] = deftensors.defgrad; } return result; @@ -3254,12 +3236,18 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::return_mapping( *--------------------------------------------------------------------*/ void Mat::InelasticDefgradTransvIsotropElastViscoplast::update() { - // update history variables for the next time step - time_step_quantities_.update(); - // call update method of the viscoplastic law - viscoplastic_law_->update(); - // reset Local Newton-Raphson manager - local_newton_manager_.reset(); + for (unsigned int gp = 0; gp < num_gp_; ++gp) + { + // update history variables for the next time step + time_step_quantities_.update(gp); + // reset saved number of iterations at each Gauss point within Local Newton-Raphson manager + local_newton_manager_.reset_curr_num_iters(gp); + if (is_plastic_gp_[gp]) + { + // call update method of the viscoplastic law + viscoplastic_law_->update(gp); + } + } } @@ -3272,6 +3260,9 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::setup(const int numgp, // auxiliaries Core::LinAlg::Matrix<6, 1> temp_6x1(Core::LinAlg::Initialization::zero); + // set number of Gauss points + num_gp_ = numgp; + // resize time step quantities according to the number of Gauss points time_step_quantities_.resize(numgp); thermo_mechanical_coupling_cache_.resize(numgp); @@ -3283,6 +3274,9 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::setup(const int numgp, // of Gauss points local_newton_manager_.resize(numgp); + // resize plastic flow tracking vector with the correct number of Gauss points + is_plastic_gp_.resize(numgp, is_plastic_gp_[0]); + // read fiber and structural tensor in the case of transverse isotropy if (parameter()->mat_behavior() == ViscoplastUtils::MatBehavior::transv_isotropic) { @@ -3294,7 +3288,7 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::setup(const int numgp, } else { - m_.scale(0.0); + m_.clear(); } // set material dependent constant tensors const_mat_tensors_.set_material_const_tensors(m_); @@ -3320,6 +3314,9 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::pack_inelastic( // pack Local Newton manager local_newton_manager_.pack(data); + + // pack plastic flow tracking vector + add_to_pack(data, is_plastic_gp_); } } @@ -3342,8 +3339,13 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::unpack_inelastic( time_step_quantities_.unpack(buffer); // unpack the Local Newton manager local_newton_manager_.unpack(buffer); + // unpack the plastic flow tracking vector + extract_from_pack(buffer, is_plastic_gp_); } + // set number of Gauss points manually, since the setup method is not called + num_gp_ = time_step_quantities_.last_defgrad.size(); + // now that the fiber direction is available, we set the material-dependent constant tensors // with it const_mat_tensors_.set_material_const_tensors(m_); @@ -3363,6 +3365,8 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_local_newton_residua const Core::LinAlg::Matrix<3, 3>& last_iFinM, const double dt, ViscoplastUtils::ErrorType& err_status) { + ensure_error_free_evaluation(err_status); + // auxiliaries Core::LinAlg::Matrix<3, 3> temp3x3(Core::LinAlg::Initialization::zero); @@ -3461,6 +3465,9 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_local_newton_jacobia const Core::LinAlg::Matrix<3, 3>& last_iFinM, const double dt, ViscoplastUtils::ErrorType& err_status) { + ensure_error_free_evaluation(err_status); + + // auxiliaries Core::LinAlg::FourTensor<3> tempFourTensor(true); Core::LinAlg::Matrix<9, 9> temp9x9(Core::LinAlg::Initialization::zero); @@ -3595,18 +3602,19 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_local_newton_jacobia *--------------------------------------------------------------------*/ Core::LinAlg::Matrix<10, 1> Mat::InelasticDefgradTransvIsotropElastViscoplast::viscoplastic_correction( - const Core::LinAlg::Matrix<3, 3>& defgrad, const double temperature, - const Core::LinAlg::Matrix<10, 1>& x, ViscoplastUtils::ErrorType& err_status) + const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalIntegrationDeformationTensors& + deftensors, + const double temperature, ViscoplastUtils::ErrorType& err_status) { - // calculate right Cauchy-Green deformation tensor - Core::LinAlg::Matrix<3, 3> CM(Core::LinAlg::Initialization::zero); - CM.multiply_tn(1.0, defgrad, defgrad, 0.0); + ensure_error_free_evaluation(err_status); + + + // declare solution vector + Core::LinAlg::Matrix<10, 1> sol{Core::LinAlg::Initialization::zero}; - // define solution vector - Core::LinAlg::Matrix<10, 1> sol = x; + // declare current defgrad (tensor interpolated later on in each substep) and right CG + Core::LinAlg::Matrix<3, 3> curr_FM{Core::LinAlg::Initialization::zero}; - // declare current right CG (tensor interpolated later on in each substep) - Core::LinAlg::Matrix<3, 3> curr_CM(Core::LinAlg::Initialization::zero); // declare current temperature (interpolated later on in each substep) double curr_temp = 0.0; @@ -3625,23 +3633,30 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::viscoplastic_correction( { while (!local_substepping_utils_.end_substepping()) { - // interpolate right Cauchy-Green tensor if we use local substepping - curr_CM = tensor_interpolator_.get_interpolated_matrix( - {time_step_quantities_.last_rightCG[gp_], CM}, {0.0, 1.0}, + // interpolate deformation gradient if we use local substepping, and calculate the right + // Cauchy-Green deformation tensor accordingly + curr_FM = tensor_interpolator_.get_interpolated_matrix( + {time_step_quantities_.last_defgrad[gp_], deftensors.defgrad}, {0.0, 1.0}, local_substepping_utils_.get_normalized_next_time_param(time_step_tracker_.dt), tensor_interp_err_status); - FOUR_C_ASSERT_ALWAYS( - tensor_interp_err_status == Core::LinAlg::TensorInterpolationErrorType::NoErrors, - "Tensor interpolation failed with err: {}", - Core::LinAlg::make_error_message(tensor_interp_err_status)); + if (tensor_interp_err_status != Core::LinAlg::TensorInterpolationErrorType::NoErrors) + { + FOUR_C_THROW( + "{}", get_error_warning_info(std::format("Tensor interpolation failed with err: {}", + Core::LinAlg::make_error_message(tensor_interp_err_status)))); + } + ViscoplastUtils::LocalIntegrationDeformationTensors curr_deftensors( + curr_FM, time_step_quantities_.last_substep_plastic_defgrad_inverse[gp_]); + // interpolate temperature curr_temp = std::lerp(time_step_quantities_.last_temperature[gp_], temperature, local_substepping_utils_.get_normalized_next_time_param(time_step_tracker_.dt)); // perform substep local Newton loop - local_newton_loop(curr_CM, curr_temp, time_step_quantities_.last_substep_plastic_strain[gp_], - time_step_quantities_.last_substep_plastic_defgrad_inverse[gp_], - local_substepping_utils_.get_substep_size(), sol, err_status); + err_status = ViscoplastUtils::ErrorType::no_errors; + sol = local_newton_loop(curr_deftensors, curr_temp, + time_step_quantities_.last_substep_plastic_strain[gp_], + local_substepping_utils_.get_substep_size(), err_status); // update Local Newton quantities local_newton_manager_.update_after_local_newton(gp_); @@ -3657,19 +3672,19 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::viscoplastic_correction( extract_inverse_inelastic_defgrad(sol); time_step_quantities_.last_substep_plastic_strain[gp_] = sol(9); // update last substep history variables of the viscoplastic flow rule - viscoplastic_law_->update_gp_state(gp_); + viscoplastic_law_->update_gp_state_after_substep(gp_); } else { // halve and prepare a new substep - bool halving_success = halve_and_prepare_new_substep(sol, CM); + bool halving_success = halve_and_prepare_new_substep(sol, curr_deftensors.right_cg); // if the halving number was exceeded --> return with error if (!halving_success) { - const std::string extended_message = - get_error_info(Mat::InelasticDefgradTransvIsotropElastViscoplastUtils:: - get_detailed_error_message_for_error_type(err_status)); - FOUR_C_THROW("{}", extended_message); + FOUR_C_THROW( + "{}", get_error_warning_info(std::format( + "Maximum halving number for substepping was reached! Error status: {}", + EnumTools::enum_name(err_status)))); } } } @@ -3678,9 +3693,15 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::viscoplastic_correction( else { // perform local Newton loop - local_newton_loop(CM, temperature, time_step_quantities_.last_plastic_strain[gp_], - time_step_quantities_.last_plastic_defgrad_inverse[gp_], time_step_tracker_.dt, sol, - err_status); + + sol = local_newton_loop(deftensors, temperature, time_step_quantities_.last_plastic_strain[gp_], + time_step_tracker_.dt, err_status); + if (err_status != ViscoplastUtils::ErrorType::no_errors) + { + FOUR_C_THROW("{}", get_error_warning_info(std::format( + "There was an error within the local Newton! Error status: {}", + EnumTools::enum_name(err_status)))); + } // update Local Newton quantities and reset iteration counter local_newton_manager_.update_after_local_newton(gp_); @@ -3693,15 +3714,18 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::viscoplastic_correction( /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ -void Mat::InelasticDefgradTransvIsotropElastViscoplast::local_newton_loop( - const Core::LinAlg::Matrix<3, 3>& CM, const double temperature, - const double last_plastic_strain, const Core::LinAlg::Matrix<3, 3>& last_iFinM, const double dt, - Core::LinAlg::Matrix<10, 1>& sol, +Core::LinAlg::Matrix<10, 1> Mat::InelasticDefgradTransvIsotropElastViscoplast::local_newton_loop( + const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalIntegrationDeformationTensors& + deftensors, + const double temperature, const double last_plastic_strain, const double dt, InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status) { + ensure_error_free_evaluation(err_status); + // auxiliaries Core::LinAlg::Matrix<10, 1> temp10x1(Core::LinAlg::Initialization::zero); + // Jacobian matrix Core::LinAlg::Matrix<10, 10> jacMat(Core::LinAlg::Initialization::zero); // increment of the solution variables @@ -3709,16 +3733,31 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::local_newton_loop( // residual of both equations Core::LinAlg::Matrix<10, 1> residual(Core::LinAlg::Initialization::zero); - // initialize quantities checked for convergence - ViscoplastUtils::LocalNewtonConvQuantities conv_quantities{ - .residual_norm = 1.0, .increment_norm = 1.0}; - // initialize evaluation management action ViscoplastUtils::EvaluationAction eval_action{ ViscoplastUtils::EvaluationAction::continue_current_iteration}; - // reset Local Newton iteration count - local_newton_manager_.set_iteration_count(0); + // initialize local Newton + local_newton_manager_.reset_iter(); + temp10x1 = determine_local_newton_init_estimate(dt, deftensors, last_plastic_strain, err_status); + local_newton_manager_.save_init_estimate_and_reset_convergence_quantities(temp10x1); + // handle eventual error in the initial estimate determination + if (err_status != ViscoplastUtils::ErrorType::no_errors) + { + // for substepping, we exit with the set error status and retry the computation with a smaller + // substep (eventually) + if (parameter()->use_local_substepping()) + { + return Core::LinAlg::Matrix<10, 1>{Core::LinAlg::Initialization::zero}; + } + // without substepping, we throw directly + else + { + FOUR_C_THROW( + "{}", get_error_warning_info("Could not compute initial estimate for the local Newton!")); + } + } + // local Newton-Raphson loop while (true) @@ -3726,15 +3765,12 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::local_newton_loop( // set error status to no_errors err_status = ViscoplastUtils::ErrorType::no_errors; - // increment iteration counter - local_newton_manager_.increment_iteration_count(); - // evaluate residual - residual = evaluate_local_newton_residual( - CM, temperature, sol, last_plastic_strain, last_iFinM, dt, err_status); + residual = evaluate_local_newton_residual(deftensors.right_cg, temperature, + local_newton_manager_.sol(), last_plastic_strain, + deftensors.elastic_predictor_inverse_plastic_defgrad, dt, err_status); // error management after residual evaluation - temp10x1.update(1.0, sol, 0.0); manage_evaluation(err_status, eval_action); switch (eval_action) { @@ -3745,40 +3781,37 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::local_newton_loop( } case (ViscoplastUtils::EvaluationAction::continue_with_next_iteration): { - // recompute dx after conducting adjustments to solution vector - dx.update(1.0, sol, -1.0, temp10x1, 0.0); - // proceed with next iteration after performing adjustments due // to errors + local_newton_manager_.increment_iter(); continue; } case (ViscoplastUtils::EvaluationAction::exit_with_error): { // exit with the set error status - return; + return Core::LinAlg::Matrix<10, 1>{Core::LinAlg::Initialization::zero}; } default: { - FOUR_C_THROW("Invalid evaluation action {} for error status {} after residual evaluation", - EnumTools::enum_name(eval_action), EnumTools::enum_name(err_status)); + FOUR_C_THROW( + "{}", get_error_warning_info(std::format( + "Invalid evaluation action {} for error status {} after residual evaluation", + EnumTools::enum_name(eval_action), EnumTools::enum_name(err_status)))); } } - // if we continue, then the residual evaluation was successful - - // verify convergence - conv_quantities.residual_norm = residual.norm2(); - const bool is_converged = is_local_newton_converged(conv_quantities); + // if we continue, then the residual evaluation was successful; verify convergence next + local_newton_manager_.set_residual_norm(residual); // exit in case of convergence - if (is_converged) + if (local_newton_manager_.is_local_newton_converged()) { - return; + return local_newton_manager_.sol(); } - // check if maximum iteration is exceeded - if (local_newton_manager_.iter() > local_newton_manager_.params().max_iter) + // check if maximum iteration is reached + if (local_newton_manager_.is_max_iter_reached()) { // set non-convergence error err_status = @@ -3789,24 +3822,24 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::local_newton_loop( // for a smaller substep size; hence, we return with the set error status if (parameter()->use_local_substepping()) { - return; + return Core::LinAlg::Matrix<10, 1>{ + Core::LinAlg::Initialization::zero}; // exit with the set error status } // for one-step processes, we account for the set divergence continuation strategy else { - verify_local_newton_exit(conv_quantities, err_status); - return; + verify_local_newton_exit(err_status); + return local_newton_manager_.sol(); } } else { // check whether the Local Newton is 'stuck' - if (is_local_newton_stuck(conv_quantities)) + if (local_newton_manager_.is_local_newton_stuck()) { // error management routine after the 'stuck' verification err_status = InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType:: no_convergence_local_newton; - temp10x1.update(1.0, sol, 0.0); manage_evaluation(err_status, eval_action); switch (eval_action) { @@ -3817,34 +3850,36 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::local_newton_loop( } case (ViscoplastUtils::EvaluationAction::continue_with_next_iteration): { - // recompute dx after conducting adjustments to solution vector - dx.update(1.0, sol, -1.0, temp10x1, 0.0); - // proceed with next iteration after performing adjustments due // to errors + local_newton_manager_.increment_iter(); continue; } case (ViscoplastUtils::EvaluationAction::exit_with_error): { // exit with the set error status - return; + return Core::LinAlg::Matrix<10, 1>{Core::LinAlg::Initialization::zero}; } default: { - FOUR_C_THROW( - "Invalid evaluation action {} for error status {} after verification of stuck " - "Local Newton", - EnumTools::enum_name(eval_action), EnumTools::enum_name(err_status)); + FOUR_C_THROW("{}", + get_error_warning_info(std::format( + "Invalid evaluation action {} for error status {} after verification of stuck " + "Local Newton", + EnumTools::enum_name(eval_action), EnumTools::enum_name(err_status)))); } } } } // evaluate Jacobian - jacMat = evaluate_local_newton_jacobian( - CM, temperature, sol, last_plastic_strain, last_iFinM, dt, err_status); + jacMat = evaluate_local_newton_jacobian(deftensors.right_cg, temperature, + local_newton_manager_.sol(), last_plastic_strain, + deftensors.elastic_predictor_inverse_plastic_defgrad, dt, err_status); + // error management after Jacobian evaluation manage_evaluation(err_status, eval_action); + switch (eval_action) { case (ViscoplastUtils::EvaluationAction::continue_current_iteration): @@ -3856,17 +3891,20 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::local_newton_loop( { // proceed with next iteration after performing adjustments due // to errors + local_newton_manager_.increment_iter(); continue; } case (ViscoplastUtils::EvaluationAction::exit_with_error): { // exit with the set error status - return; + return Core::LinAlg::Matrix<10, 1>{Core::LinAlg::Initialization::zero}; } default: { - FOUR_C_THROW("Invalid evaluation action {} for error status {} after Jacobian evaluation", - EnumTools::enum_name(eval_action), EnumTools::enum_name(err_status)); + FOUR_C_THROW( + "{}", get_error_warning_info(std::format( + "Invalid evaluation action {} for error status {} after Jacobian evaluation", + EnumTools::enum_name(eval_action), EnumTools::enum_name(err_status)))); } } @@ -3889,97 +3927,36 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::local_newton_loop( { // proceed with next iteration after performing adjustments due // to errors + local_newton_manager_.increment_iter(); continue; } case (ViscoplastUtils::EvaluationAction::exit_with_error): { // exit with the set error status - return; + return Core::LinAlg::Matrix<10, 1>{Core::LinAlg::Initialization::zero}; } + default: { FOUR_C_THROW( - "Invalid evaluation action {} for error status {} after solving linear system", - EnumTools::enum_name(eval_action), EnumTools::enum_name(err_status)); + "{}", get_error_warning_info(std::format("Invalid evaluation action {} for error " + "status {} after solving linear system", + EnumTools::enum_name(eval_action), EnumTools::enum_name(err_status)))); } } } - // update solution vector and relative increment - sol.update(1.0, dx, 1.0); - const double sol_norm = sol.norm2(); - const double dx_norm = dx.norm2(); - FOUR_C_ASSERT_ALWAYS(sol_norm >= 1.0e-8, - "The solution vector in local iteration {} is nearly 0, with 2-norm: {}! Something went " - "wrong, since such mechanical states are not expected!", - local_newton_manager_.iter(), sol_norm); - conv_quantities.increment_norm = dx_norm / sol_norm; - } -} + // update solution vector, iteration counter and increment norm + local_newton_manager_.increment_solution_vector(dx); -/*--------------------------------------------------------------------* - *--------------------------------------------------------------------*/ -bool Mat::InelasticDefgradTransvIsotropElastViscoplast::is_local_newton_converged( - const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvQuantities& - conv_quantities) -{ - // check for convergence - switch (local_newton_manager_.params().conv_check) - { - case InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck::residual: - return (conv_quantities.residual_norm <= local_newton_manager_.params().res_tol); - break; - case InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck::increment_ratio: - return (conv_quantities.increment_norm <= local_newton_manager_.params().incr_tol); - break; - case InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck:: - residual_and_increment_ratio: - return (conv_quantities.residual_norm <= local_newton_manager_.params().res_tol && - conv_quantities.increment_norm <= local_newton_manager_.params().incr_tol); - break; - default: - FOUR_C_THROW("You should not be here (convergence checking of the Local Newton Loop)"); + local_newton_manager_.increment_iter(); } } -/*--------------------------------------------------------------------* - *--------------------------------------------------------------------*/ -bool Mat::InelasticDefgradTransvIsotropElastViscoplast::is_local_newton_stuck( - const ViscoplastUtils::LocalNewtonConvQuantities& conv_quantities) -{ - // check for "stuck" Local Newton, i.e., the increment does not change much but there is not a - // converged state (check only feasible after the first iteration, since dx must be available) - if ((local_newton_manager_.iter() > 1) && (conv_quantities.increment_norm < 1.0e-15)) - { - // only in the case that the residual is verified, we set an - // error status - switch (local_newton_manager_.params().conv_check) - { - case InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck::residual: - case FourC::Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck:: - residual_and_increment_ratio: - { - return (conv_quantities.residual_norm > local_newton_manager_.params().res_tol); - } - case ViscoplastUtils::LocalNewtonConvCheck::increment_ratio: - { - return false; - } - default: - FOUR_C_THROW( - "You should not be here with convergence check type {} (check: is Local Newton " - "stuck?)", - EnumTools::enum_name(local_newton_manager_.params().conv_check)); - } - } - - return false; -} /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ void Mat::InelasticDefgradTransvIsotropElastViscoplast::verify_local_newton_exit( - const ViscoplastUtils::LocalNewtonConvQuantities& conv_quantities, InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status) { switch (local_newton_manager_.params().diver_cont) @@ -3987,10 +3964,10 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::verify_local_newton_exit case FourC::Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonDiverCont::stop: { // throw error: there is no convergence - const std::string extended_message = - get_error_info(Mat::InelasticDefgradTransvIsotropElastViscoplastUtils:: - get_detailed_error_message_for_error_type(err_status)); - FOUR_C_THROW("{}", extended_message); + FOUR_C_THROW( + "{}", get_error_warning_info( + ViscoplastUtils::get_detailed_error_message_for_error_type(err_status))); + return; } case FourC::Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonDiverCont:: continue_sim: @@ -4003,8 +3980,9 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::verify_local_newton_exit std::cout << std::format( "WARNING: The Local Newton Loop for ele_gid = {}, gp = {} did not reach " "convergence after {} iterations: residual = {}, increment = {}\n", - ele_gid_, gp_, local_newton_manager_.iter(), conv_quantities.residual_norm, - conv_quantities.increment_norm); + ele_gid_, gp_, local_newton_manager_.iter(), + local_newton_manager_.convergence_quantities().residual_norm, + local_newton_manager_.convergence_quantities().increment_norm); } // safeguard check: is the current solution within the bounds posed by the @@ -4014,11 +3992,11 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::verify_local_newton_exit continue_sim_with_safeguard) { const bool residual_within_bounds = - conv_quantities.residual_norm < + local_newton_manager_.convergence_quantities().residual_norm < (local_newton_manager_.params().res_tol * local_newton_manager_.params().max_exceedance_fact_res_tol); const bool incr_ratio_within_bounds = - conv_quantities.increment_norm < + local_newton_manager_.convergence_quantities().increment_norm < (local_newton_manager_.params().incr_tol * local_newton_manager_.params().max_exceedance_fact_incr_tol); @@ -4027,41 +4005,63 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::verify_local_newton_exit case FourC::Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck:: residual: { - FOUR_C_ASSERT_ALWAYS(residual_within_bounds, - "Residual {} exceeds the residual tolerance {} by more than the set " - "exceedance tolerance factor {}!", - conv_quantities.residual_norm, local_newton_manager_.params().res_tol, - local_newton_manager_.params().max_exceedance_fact_res_tol); + if (!residual_within_bounds) + { + FOUR_C_THROW( + "{}", get_error_warning_info(std::format( + "Residual {} exceeds the residual tolerance {} by more than the set " + "exceedance tolerance factor {}! Error status: {}", + local_newton_manager_.convergence_quantities().residual_norm, + local_newton_manager_.params().res_tol, + local_newton_manager_.params().max_exceedance_fact_res_tol, + EnumTools::enum_name(err_status)))); + } + break; } case FourC::Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck:: increment_ratio: { - FOUR_C_ASSERT_ALWAYS(incr_ratio_within_bounds, - "Relative increment {} exceeds the increment tolerance {} by more " - "than the set exceedance tolerance factor {}!", - conv_quantities.increment_norm, local_newton_manager_.params().incr_tol, - local_newton_manager_.params().max_exceedance_fact_incr_tol); + if (!incr_ratio_within_bounds) + { + FOUR_C_THROW( + "{}", get_error_warning_info(std::format( + "Relative increment {} exceeds the increment tolerance {} by more " + "than the set exceedance tolerance factor {}! Error status: {}", + local_newton_manager_.convergence_quantities().increment_norm, + local_newton_manager_.params().incr_tol, + local_newton_manager_.params().max_exceedance_fact_incr_tol, + EnumTools::enum_name(err_status)))); + } break; } case FourC::Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck:: residual_and_increment_ratio: { - FOUR_C_ASSERT_ALWAYS(residual_within_bounds && incr_ratio_within_bounds, - "Residual {} and relative increment {} exceed the tolerances {} and {} by " - "more than the set exceedance tolerance factors {} and {}!", - conv_quantities.residual_norm, conv_quantities.increment_norm, - local_newton_manager_.params().res_tol, local_newton_manager_.params().incr_tol, - local_newton_manager_.params().max_exceedance_fact_res_tol, - local_newton_manager_.params().max_exceedance_fact_incr_tol); + if ((!residual_within_bounds) || (!incr_ratio_within_bounds)) + { + FOUR_C_THROW("{}", + get_error_warning_info(std::format( + "Residual {} and relative increment {} exceed the tolerances {} and {} by " + "more than the set exceedance tolerance factors {} and {}! Error status: {}", + local_newton_manager_.convergence_quantities().residual_norm, + local_newton_manager_.convergence_quantities().increment_norm, + local_newton_manager_.params().res_tol, + local_newton_manager_.params().incr_tol, + local_newton_manager_.params().max_exceedance_fact_res_tol, + local_newton_manager_.params().max_exceedance_fact_incr_tol, + EnumTools::enum_name(err_status)))); + } break; } default: - FOUR_C_THROW("Invalid convergence check {} (verification of safe Local Newton exit)", - EnumTools::enum_name(local_newton_manager_.params().conv_check)); + FOUR_C_THROW( + "{}", get_error_warning_info(std::format( + "Invalid convergence check {} (verification of safe Local Newton exit)", + EnumTools::enum_name(local_newton_manager_.params().conv_check)))); } } @@ -4072,13 +4072,16 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::verify_local_newton_exit } default: FOUR_C_THROW( - "You should not be here (divergence management strategy for Local Newton " - "Loop)"); + "{}", get_error_warning_info( + "You should not be here (divergence management strategy for Local Newton " + "Loop)")); } // safeguard for the function: each path must either return of throw - FOUR_C_THROW("The Local Newton scheme cannot be safely exited! Uncaught exception with error {}", - err_status); + FOUR_C_THROW( + "{}", get_error_warning_info(std::format( + "The Local Newton scheme cannot be safely exited! Uncaught exception with error {}", + EnumTools::enum_name(err_status)))); } /*--------------------------------------------------------------------* @@ -4087,7 +4090,8 @@ bool Mat::InelasticDefgradTransvIsotropElastViscoplast::solve_local_newton_linea const Core::LinAlg::Matrix<10, 1>& residual, const Core::LinAlg::Matrix<10, 10>& jacobian, Core::LinAlg::Matrix<10, 1>& dx) { - // auxiliaries: use copies of the residual and jacobian to avoid modifying the original variables + // auxiliaries: use copies of the residual and jacobian to avoid modifying the original + // variables Core::LinAlg::Matrix<10, 1> temp_negative_residual(Core::LinAlg::Initialization::zero); Core::LinAlg::Matrix<10, 10> temp_jacobian(Core::LinAlg::Initialization::zero); @@ -4113,12 +4117,14 @@ bool Mat::InelasticDefgradTransvIsotropElastViscoplast::check_elastic_predictor( const Core::LinAlg::Matrix<3, 3>& iFinM_pred, const double plastic_strain_pred, ViscoplastUtils::ErrorType& err_status) { + ensure_error_free_evaluation(err_status); + + // evaluate state with this elastic predictor and the minimum possible time step state_quantities_ = evaluate_state_quantities(CM, temperature, iFinM_pred, plastic_strain_pred, err_status, time_step_tracker_.min_dt, ViscoplastUtils::StateQuantityEvalType::plastic_strain_rate_only); - // check if the predicted plastic strain rate is 0 -> for flow rules with yield functions, // this means that the predictor is correct return (state_quantities_.curr_equiv_plastic_strain_rate * time_step_tracker_.dt <= @@ -4211,7 +4217,7 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_additional_cmat perturbed_CM.multiply_tn(1.0, perturbed_FM, perturbed_FM, 0.0); // get corresponding inverse inelastic defgrad - perturbed_iFinM = return_mapping(perturbed_FM, temperature).inv_plastic_defgrad; + perturbed_iFinM = constitutive_update(perturbed_FM, temperature).inv_plastic_defgrad; Core::LinAlg::Matrix<9, 1> perturbed_iFinV(Core::LinAlg::Initialization::zero); Core::LinAlg::Voigt::matrix_3x3_to_9x1(perturbed_iFinM, perturbed_iFinV); @@ -4265,7 +4271,7 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_od_stiff_mat_pe // run return-mapping with the perturbed temperature const HistoryVariables perturbed_history_variables = - return_mapping(FredM, perturbed_temperature); + constitutive_update(FredM, perturbed_temperature); Core::LinAlg::Matrix<9, 1> perturbed_iFinV(Core::LinAlg::Initialization::zero); Core::LinAlg::Voigt::matrix_3x3_to_9x1( @@ -4304,7 +4310,7 @@ Mat::HeatSource Mat::InelasticDefgradTransvIsotropElastViscoplast:: // Evaluate the incoming state params_.set("temperature", temperature); viscoplastic_law_->pre_evaluate(params_, gp_); - return_mapping(FredM, temperature); + constitutive_update(FredM, temperature); update_hist_var_ = false; // no update of the current values during perturbed evaluations const auto unperturbed_state_quantities = state_quantities_; @@ -4352,7 +4358,7 @@ Mat::HeatSource Mat::InelasticDefgradTransvIsotropElastViscoplast:: // run return-mapping with the perturbed deformation gradient. This populates the // state_quantities_ - return_mapping(perturbed_FM, temperature); + constitutive_update(perturbed_FM, temperature); result.derivative_wrt_cauchy_green(i) += delta_sign / (4.0 * pert_fact) * evaluate_taylor_quinney(state_quantities_); @@ -4375,7 +4381,7 @@ Mat::HeatSource Mat::InelasticDefgradTransvIsotropElastViscoplast:: viscoplastic_law_->pre_evaluate(params_, gp_); // run return-mapping with the perturbed temperature. This populates the state_quantities_ - return_mapping(FredM, perturbed_temperature); + constitutive_update(FredM, perturbed_temperature); result.derivative_wrt_temperature += delta_sign / (2 * delta_T_perturbation) * evaluate_taylor_quinney(state_quantities_); @@ -4418,22 +4424,22 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplast::manage_evaluation( eval_action = ViscoplastUtils::EvaluationAction::exit_with_error; return; } + // without evaluation management strategy, we can throw directly else { - FOUR_C_THROW( - "The Local Newton evaluation has failed with err status {} and there is no evaluation " - "management strategy " - "selected!", - err_status); + FOUR_C_THROW("{}", get_error_warning_info(std::format( + "The Local Newton evaluation has failed and there is no evaluation " + "management strategy " + "selected! Error status: {}", + EnumTools::enum_name(err_status)))); } } } - /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ -std::string Mat::InelasticDefgradTransvIsotropElastViscoplast::get_error_info( +std::string Mat::InelasticDefgradTransvIsotropElastViscoplast::get_error_warning_info( const std::string& base_error_string) const { // auxiliaries @@ -4444,7 +4450,11 @@ std::string Mat::InelasticDefgradTransvIsotropElastViscoplast::get_error_info( temp_ostream << std::fixed << std::setprecision(16) << std::endl; // declare the extended error message - std::string extended_error_string{local_substepping_utils_.get_info()}; + std::string extended_error_string{}; + if (parameter()->use_local_substepping()) + { + extended_error_string += local_substepping_utils_.get_info(); + } // get relevant error info extended_error_string += "BASE ERROR: \n"; @@ -4616,4 +4626,19 @@ bool Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_output_data( return viscoplastic_law_->evaluate_output_data(name, data); } +/*--------------------------------------------------------------------* + *--------------------------------------------------------------------*/ +Core::LinAlg::Matrix<10, 1> +Mat::InelasticDefgradTransvIsotropElastViscoplast::determine_local_newton_init_estimate( + const double dt, + const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalIntegrationDeformationTensors& + deftensors, + const double last_plastic_strain, + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status) const +{ + ensure_error_free_evaluation(err_status); + + // we use the elastic predictor + return wrap_unknowns(deftensors.elastic_predictor_inverse_plastic_defgrad, last_plastic_strain); +} FOUR_C_NAMESPACE_CLOSE diff --git a/src/mat/4C_mat_inelastic_defgrad_factors.hpp b/src/mat/4C_mat_inelastic_defgrad_factors.hpp index b68f6b10d90..b03151b9bcb 100644 --- a/src/mat/4C_mat_inelastic_defgrad_factors.hpp +++ b/src/mat/4C_mat_inelastic_defgrad_factors.hpp @@ -381,14 +381,6 @@ namespace Mat { return linearization_type_; } - //! get maximum, numerically evaluable plastic strain increment - [[nodiscard]] double max_plastic_strain_incr() const { return max_plastic_strain_incr_; } - //! get maximum, numerically evaluable value for the increment of - //! the plastic strain derivatives (dt * derivative) - [[nodiscard]] double max_plastic_strain_deriv_incr() const - { - return max_plastic_strain_deriv_incr_; - } //! get computation method for the matrix exponential [[nodiscard]] Core::LinAlg::MatrixExpCalcMethod mat_exp_calc_method() const { @@ -415,6 +407,12 @@ namespace Mat { return local_newton_params_; } + //! get error registration settings + [[nodiscard]] InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings() const + { + return error_registration_settings_; + } private: //! ID of the viscoplasticity law @@ -443,13 +441,6 @@ namespace Mat //! linearization method (analytic | perturbation based) InelasticDefgradTransvIsotropElastViscoplastUtils::LinearizationType linearization_type_; - //! maximum, numerically evaluable plastic strain increment - const double max_plastic_strain_incr_; - - //! maximum, numerically evaluable increment of - //! plastic strain derivatives (time_step * derivative) - const double max_plastic_strain_deriv_incr_; - //! use local substepping to integrate the viscoplastic evolution equations const bool use_local_substepping_; @@ -473,6 +464,10 @@ namespace Mat //! Local Newton--Raphson parameters const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonParams local_newton_params_; + + //! get error registration settings for the constitutive update + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings_; }; } // namespace PAR @@ -1559,19 +1554,6 @@ namespace Mat void pre_evaluate(const Teuchos::ParameterList& params, const EvaluationContext<3>& context, int gp, int eleGID) override; - /*! - * Perform all preparation tasks for the return mapping in the current timestep. - * In contrast to the pre_evaluate method, these tasks shall not be repeated in case of the - * redundant evaluate call, see Issue #121 at https://github.com/4C-multiphysics/4C/issues/121. - * This means that the current, public pre-evaluate method performs only the safely repeatable - * pre-evaluation tasks. This also means that we prepare and perform the return mapping within - * evaluate_inverse_inelastic_defgrad only if we are not in the - * redundant call (see quick-fix PR #131 at - * https://github.com/4C-multiphysics/4C/pull/131). - * - */ - void prepare_return_mapping(); - void update() override; void pack_inelastic(Core::Communication::PackBuffer& data) const override; @@ -1644,10 +1626,13 @@ namespace Mat //! tensors associated with the director vector) InelasticDefgradTransvIsotropElastViscoplastUtils::ConstMatTensors const_mat_tensors_; - //! current Gauss Point - int gp_{-1}; + //! current Gauss point + unsigned int gp_{0}; + //! total number of Gauss points + unsigned int num_gp_{0}; + //! current element ID - int ele_gid_{-1}; + unsigned int ele_gid_{0}; //! parameter list Teuchos::ParameterList params_; @@ -1708,6 +1693,9 @@ namespace Mat //! dedicated Local Newton manager containing settings and iteration data InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager local_newton_manager_; + //! vector tracking whether there is plastic flow at each Gauss point + std::vector is_plastic_gp_; + /*! * @brief Calculate the Holzapfel gamma and delta values of the isotropic elastic material * components @@ -1764,28 +1752,6 @@ namespace Mat const double last_plastic_strain, const Core::LinAlg::Matrix<3, 3>& last_iFinM, const double dt, InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status); - - /*! - * @brief Determine whether the Local Newton Loop has converged. - * - * @param[in] conv_quantities quantities verified for convergence - * @return boolean: true = converged - */ - bool is_local_newton_converged( - const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvQuantities& - conv_quantities); - - /*! - * @brief After an unsuccessful convergence check: determine whether the Local Newton is - * stuck, i.e., the relative solution increment is nearly 0, but there is no convergence yet. - * - * @param[in] conv_quantities quantities verified for convergence - * @return boolean: true = stuck - */ - bool is_local_newton_stuck( - const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvQuantities& - conv_quantities); - /*! * @brief After an unsuccessful convergence check and after the maximum number of local * iterations has been exceeded: verifies whether the Local Newton scheme can be safely exited @@ -1794,15 +1760,11 @@ namespace Mat * @note If no error is thrown in this verification routine, then the Local Newton scheme can be * safely exited. The error status is reset to no_errors to continue with the computation. * - * @param[in] conv_quantities quantities verified for convergence * @param[in,out] err_status error status */ void verify_local_newton_exit( - const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvQuantities& - conv_quantities, InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status); - /*! * @brief Solve local Newton linear system \f$ \boldsymbol{J} \mathrm{d}\boldsymbol{x} = - * \boldsymbol{r} \f$ to update the iteration vector @@ -1816,8 +1778,6 @@ namespace Mat bool solve_local_newton_linear_system(const Core::LinAlg::Matrix<10, 1>& residual, const Core::LinAlg::Matrix<10, 10>& jacobian, Core::LinAlg::Matrix<10, 1>& dx); - - /*! * @brief For a given right Cauchy_Green tensor and the Local NR Loop unknown vector, * compute the 10 x 10 Jacobian matrix required for the Local Newton Loop and the @@ -1849,22 +1809,22 @@ namespace Mat InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status); /*! - * @brief Performs the viscoplastic corrector step of the return mapping. + * @brief Performs the viscoplastic corrector step of the constitutive update. * * @note Uses local substepping if specified so by the user; the current time step is halved if * problematic numerical states, marked with an error status, are encountered * - * @param[in] defgrad deformation gradient \f$ \boldsymbol{F} \f$ in matrix form + * @param[in] deftensors deformation tensors used for local time integration (reset if + * substepping is used) * @param[in] temperature absolute temperature - * @param[in] x initial guess of Local Newton Loop, composed of the components of the - * inverse inelastic deformation gradient \f$ \boldsymbol{F}_{\text{in}}^{-1} \f$ - * and plastic strain \f$ \varepsilon_{\text{p}} \f$ * @param[out] err_status error status * @return solution vector of the Local Newton Loop, structured analogously to the initial guess * x */ - Core::LinAlg::Matrix<10, 1> viscoplastic_correction(const Core::LinAlg::Matrix<3, 3>& defgrad, - const double temperature, const Core::LinAlg::Matrix<10, 1>& x, + Core::LinAlg::Matrix<10, 1> viscoplastic_correction( + const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalIntegrationDeformationTensors& + deftensors, + const double temperature, InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status); /*! @@ -1874,22 +1834,22 @@ namespace Mat * @note The method does not perform local substepping internally, but only determines the * solution of a single substep in the substep loop. * - * @param[in] CM right Cauchy-Green deformation tensor at current time instant + * @param[in] deftensors deformation tensors used for local time integration * @param[in] temperature absolute temperature * @param[in] last_plastic_strain plastic strain at the previous time instant - * @param[in] last_iFinM inverse inelastic deformation gradient at the previous time instant * @param[in] dt time step size to use for evaluation - * @param[in,out] sol current (in) / updated (out) solution of the Local Newton Loop - * @param[in,out] err_status error status + * @param[out] err_status error status + * @return solution of the Local Newton Loop */ - void local_newton_loop(const Core::LinAlg::Matrix<3, 3>& CM, const double temperature, - const double last_plastic_strain, const Core::LinAlg::Matrix<3, 3>& last_iFinM, - const double dt, Core::LinAlg::Matrix<10, 1>& sol, + Core::LinAlg::Matrix<10, 1> local_newton_loop( + const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalIntegrationDeformationTensors& + deftensors, + const double temperature, const double last_plastic_strain, const double dt, InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status); /*! - * @brief History variables computed by the return mapping procedure. + * @brief History variables computed by the constitutive update procedure. */ struct HistoryVariables { @@ -1900,7 +1860,7 @@ namespace Mat }; /*! - * @brief Performs return mapping (elastic predictor - viscoplastic / plastic corrector + * @brief Performs constitutive update (elastic predictor - viscoplastic corrector * procedure) for the current GP and updates the current values of the time_step_quantities_. * It first evaluates whether the elastic predictor is a consistent * solution, and performs the local time integration (Local Newton Loop) afterwards if that is @@ -1912,10 +1872,10 @@ namespace Mat * @param[in] temperature current absolute temperature. Stored in time_step_quantities_. * @return the history variables * - * @note After a return_mapping, the state_quantitities_ are valid for the current GP and + * @note After a constitutive_update, the state_quantitities_ are valid for the current GP and * state defined by FredM and temperature. */ - HistoryVariables return_mapping( + HistoryVariables constitutive_update( const Core::LinAlg::Matrix<3, 3>& FredM, const double temperature); /** @@ -2028,7 +1988,7 @@ namespace Mat * * * @param[in] err_status error status - * @param[out] eval_action action to be performed subsequently in the Local Newton Loop + * @param[out] eval_action action to be performed subsequently in the local Newton Loop */ void manage_evaluation( const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status, @@ -2082,17 +2042,48 @@ namespace Mat const Core::LinAlg::Matrix<3, 3>& FredM, const double temperature); /*! - * @brief Get an extensive error message to be displayed when the - * simulation terminates. This is useful for debugging the time - * integration in more detail. This message contains a base error - * message which describes what failed in short form - this is - * then extended with information on the element ID, the Gauss - * Point, the last_ values and so on... + * @brief Gets extensive error / warning message to be displayed, which is useful for debugging + * the time integration in more detail. This message contains a base error message which + * describes what failed in short form - this is then extended with information on the element + * ID, the Gauss Point, the last_ values and so on... * * @param[in] base_error_string base error message to be extended * with further information */ - [[nodiscard]] std::string get_error_info(const std::string& base_error_string) const; + [[nodiscard]] std::string get_error_warning_info(const std::string& base_error_string) const; + + /// ensure an error-free evaluation status -> throws if this is not the case + void ensure_error_free_evaluation( + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status) const + { + if (err_status != InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType::no_errors) + { + FOUR_C_THROW( + "{}", std::format("Unhandled error with status {}! This method should not be called!", + EnumTools::enum_name(err_status))); + } + } + + + /*! + * @brief Determines the initial estimate to be used within the Local Newton. + * If adaptive estimate interpolation is used, this method also prepares everything for the + * further re-estimations. + * + * @param[in] dt time step / substep size + * @param[in] deftensors deformation tensors used for local time integration + * @param[in] last_plastic_strain equivalent plastic strain at the previously converged + * time instant + * @param[in] err_status error status after the procedure + * @return initial estimate containing the inverse inelastic defgrad (components 0 - 8), and + * the equivalent plastic strain (component 9) for the Local Newton within this time step / + * substep + */ + [[nodiscard]] Core::LinAlg::Matrix<10, 1> determine_local_newton_init_estimate(const double dt, + const InelasticDefgradTransvIsotropElastViscoplastUtils::LocalIntegrationDeformationTensors& + deftensors, + const double last_plastic_strain, + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status) const; }; } // namespace Mat diff --git a/src/mat/4C_mat_inelastic_defgrad_factors_service.cpp b/src/mat/4C_mat_inelastic_defgrad_factors_service.cpp index 4009b8a51b4..997aacec9ad 100644 --- a/src/mat/4C_mat_inelastic_defgrad_factors_service.cpp +++ b/src/mat/4C_mat_inelastic_defgrad_factors_service.cpp @@ -278,6 +278,11 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::TimeStepQuantities: void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::TimeStepQuantities::pre_evaluate( const unsigned int gp) { + FOUR_C_ASSERT_ALWAYS(gp < last_plastic_defgrad_inverse.size(), + "You try to pre-evaluate the time step quantities at GP {}, but the object has only {} Gauss " + "points", + gp, last_plastic_defgrad_inverse.size()); + // set consistent last substep values last_substep_plastic_defgrad_inverse[gp] = last_plastic_defgrad_inverse[gp]; last_substep_plastic_strain[gp] = last_plastic_strain[gp]; @@ -285,17 +290,23 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::TimeStepQuantities: /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ -void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::TimeStepQuantities::update() +void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::TimeStepQuantities::update( + const unsigned int gp) { + FOUR_C_ASSERT_ALWAYS(gp < last_plastic_defgrad_inverse.size(), + "You try to update the time step quantities at GP {}, but the object has only {} Gauss " + "points", + gp, last_plastic_defgrad_inverse.size()); + // update history variables for the next time step - last_defgrad = current_defgrad; - last_rightCG = current_rightCG; - last_plastic_defgrad_inverse = current_plastic_defgrad_inverse; - last_substep_plastic_defgrad_inverse = current_plastic_defgrad_inverse; - last_plastic_strain = current_plastic_strain; - last_equiv_stress = current_equiv_stress; - last_substep_plastic_strain = current_plastic_strain; - last_temperature = current_temperature; + last_defgrad[gp] = current_defgrad[gp]; + last_rightCG[gp] = current_rightCG[gp]; + last_plastic_defgrad_inverse[gp] = current_plastic_defgrad_inverse[gp]; + last_substep_plastic_defgrad_inverse[gp] = current_plastic_defgrad_inverse[gp]; + last_plastic_strain[gp] = current_plastic_strain[gp]; + last_substep_plastic_strain[gp] = current_plastic_strain[gp]; + last_equiv_stress[gp] = current_equiv_stress[gp]; + last_temperature[gp] = current_temperature[gp]; } @@ -406,8 +417,14 @@ Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager::Loca // know it at this point in time curr_num_iters_.resize(1, 0); - // set initial number of iterations to 0 + // set initial number of iterations iter_ = 0; + + // initialize solution vector and convergence quantities with dummy values; they will be set + // anyway to more meaningful values when starting the local Newton within the material model + sol_ = Core::LinAlg::Matrix<10, 1>(Core::LinAlg::Initialization::zero); + convergence_quantities_.residual_norm = 0.0; + convergence_quantities_.increment_norm = 0.0; } /*--------------------------------------------------------------------* @@ -441,9 +458,123 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager: /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ -void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager::reset() +void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager:: + reset_curr_num_iters(const unsigned int gp) { - std::ranges::fill(curr_num_iters_, 0); + FOUR_C_ASSERT_ALWAYS(gp < curr_num_iters_.size(), + "You try to reset the current number of iterations within the Local Newton manager at Gauss " + "point {}, but the object only has {} Gauss points", + gp, curr_num_iters_.size()); + + curr_num_iters_[gp] = 0; +} + + +/*--------------------------------------------------------------------* + *--------------------------------------------------------------------*/ +void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager:: + save_init_estimate_and_reset_convergence_quantities( + const Core::LinAlg::Matrix<10, 1>& init_estimate) +{ + // --> set initial estimate + sol_ = init_estimate; + + // --> set quantities used for convergence checks + + // residual norm + convergence_quantities_.residual_norm = 0.0; + // if the convergence check requires verifying the residual norm, we must ensure that the value + // set here is larger than the tolerance, to perform the check at least once, in the next + // iteration + if (params_.conv_check == LocalNewtonConvCheck::residual || + params_.conv_check == LocalNewtonConvCheck::residual_and_increment_ratio) + { + convergence_quantities_.residual_norm = 2.0 * params_.res_tol; + } + + // increment norm: ratio of increment to current solution + convergence_quantities_.increment_norm = 0.0; + // if the convergence check requires verifying the increment norm, we must ensure that the value + // set here is larger than the tolerance, to perform the check at least once, in the next + // iteration + if (params_.conv_check == LocalNewtonConvCheck::increment_ratio || + params_.conv_check == LocalNewtonConvCheck::residual_and_increment_ratio) + { + convergence_quantities_.increment_norm = 2.0 * params_.incr_tol; + } +} + +/*--------------------------------------------------------------------* + *--------------------------------------------------------------------*/ +void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager:: + increment_solution_vector(const Core::LinAlg::Matrix<10, 1>& delta_sol) +{ + sol_.update(1.0, delta_sol, 1.0); + + const double sol_norm = sol_.norm2(); + const double delta_sol_norm = delta_sol.norm2(); + FOUR_C_ASSERT_ALWAYS(sol_norm >= 1.0e-8, + "The solution vector in local iteration {} is nearly 0, with 2-norm: {}! Something went " + "wrong, since such mechanical states are not expected!", + iter_, sol_norm); + convergence_quantities_.increment_norm = delta_sol_norm / sol_norm; +} + +/*--------------------------------------------------------------------* + *--------------------------------------------------------------------*/ +bool Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager:: + is_local_newton_converged() const +{ + // check for convergence + switch (params_.conv_check) + { + case InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck::residual: + return (convergence_quantities_.residual_norm <= params_.res_tol); + break; + case InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck::increment_ratio: + return (convergence_quantities_.increment_norm <= params_.incr_tol); + break; + case InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck:: + residual_and_increment_ratio: + return (convergence_quantities_.residual_norm <= params_.res_tol && + convergence_quantities_.increment_norm <= params_.incr_tol); + break; + default: + FOUR_C_THROW("You should not be here (convergence checking of the Local Newton Loop)"); + } +} + +/*--------------------------------------------------------------------* + *--------------------------------------------------------------------*/ +bool Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager:: + is_local_newton_stuck() const +{ + // check for "stuck" Local Newton, i.e., the increment does not change much but there is not a + // converged state (check only feasible after the first iteration, since dx must be available) + if ((iter_ > 0) && (convergence_quantities_.increment_norm < 1.0e-15)) + { + // only in the case that the residual is verified, we set an + // error status + switch (params_.conv_check) + { + case LocalNewtonConvCheck::residual: + case LocalNewtonConvCheck::residual_and_increment_ratio: + { + return (convergence_quantities_.residual_norm > params_.res_tol); + } + case LocalNewtonConvCheck::increment_ratio: + { + return false; + } + default: + FOUR_C_THROW( + "You should not be here with convergence check type {} (check: is Local Newton " + "stuck?)", + EnumTools::enum_name(params_.conv_check)); + } + } + + return false; } @@ -464,6 +595,20 @@ void Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager: extract_from_pack(buffer, curr_num_iters_); } +/*--------------------------------------------------------------------* + *--------------------------------------------------------------------*/ +Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalIntegrationDeformationTensors:: + LocalIntegrationDeformationTensors( + const Core::LinAlg::Matrix<3, 3>& F, const Core::LinAlg::Matrix<3, 3>& last_iFp) +{ + defgrad = F; + inv_defgrad.invert(defgrad); + right_cg.multiply_tn(1.0, defgrad, defgrad, 0.0); + elastic_predictor_inverse_plastic_defgrad = last_iFp; + elastic_predictor_elastic_defgrad.multiply( + 1.0, defgrad, elastic_predictor_inverse_plastic_defgrad, 0.0); +} + FOUR_C_NAMESPACE_CLOSE diff --git a/src/mat/4C_mat_inelastic_defgrad_factors_service.hpp b/src/mat/4C_mat_inelastic_defgrad_factors_service.hpp index 5d510484d18..250e2c21b0a 100644 --- a/src/mat/4C_mat_inelastic_defgrad_factors_service.hpp +++ b/src/mat/4C_mat_inelastic_defgrad_factors_service.hpp @@ -160,6 +160,27 @@ namespace Mat }; + /// struct: settings for registering errors within the procedures used for the constitutive + /// update + struct ErrorRegistrationSettings + { + //! should overflow error be registered via ErrorType when the plastic strain increment + //! exceeds the specified tolerance? + bool register_plastic_strain_incr_overflow; + + //! maximum, numerically evaluable plastic strain increment before overflow error is + //! registered? + double max_plastic_strain_incr; + + //! should overflow error be registered via ErrorType when any of the plastic strain + //! derivative increments exceeds the specified tolerance? + bool register_plastic_strain_deriv_incr_overflow; + + //! maximum, numerically evaluable increment of plastic strain derivatives (time_step * + //! derivative) + double max_plastic_strain_deriv_incr; + }; + /// enum class for evaluation management actions in the iterations of the /// Local Newton loop enum class EvaluationAction @@ -295,8 +316,8 @@ namespace Mat */ void pre_evaluate(const unsigned int gp); - //! Update values between time steps: last <- current - void update(); + //! Update values between time steps: last <- current, at a given Gauss points + void update(const unsigned int gp); //! Pack values void pack(Core::Communication::PackBuffer& data) const; @@ -410,7 +431,7 @@ namespace Mat [[nodiscard]] std::string get_info() const { std::string out; - out += "Substepping info: \n"; + out += "\nSubstepping info: \n"; out += std::format( "t: {}, substep_counter: {}, curr_dt: {}, time_step_halving_counter: {}, " "total_num_of_substeps: {} \n", @@ -821,7 +842,7 @@ namespace Mat double residual_norm; //! ratio of solution increment to current solution: \f$ \frac{\left| \Delta - //! \boldsymbol{s}^{l+1} \right|}{\left| \boldsymbol{s}^{l} \right|} \f$ + //! \boldsymbol{s}^{l} \right|}{\left| \boldsymbol{s}^{l} \right|} \f$ double increment_norm; }; @@ -831,29 +852,29 @@ namespace Mat struct LocalNewtonParams { //! convergence tolerance: absolute residual value - const double res_tol; + double res_tol; //! convergence tolerance: ratio of solution increment to current solution - const double incr_tol; + double incr_tol; //! convergence check strategy - const LocalNewtonConvCheck conv_check; + LocalNewtonConvCheck conv_check; //! strategy for dealing with divergence - const LocalNewtonDiverCont diver_cont; + LocalNewtonDiverCont diver_cont; //! maximum number of local iterations - const unsigned int max_iter; + int max_iter; //! maximum exceedance factor for the residual tolerance (to be used when //! employing the divergence management strategy for continuation with //! safeguard) - const double max_exceedance_fact_res_tol; + double max_exceedance_fact_res_tol; //! maximum exceedance factor for the solution increment tolerance (to be used when //! employing the divergence management strategy for continuation with //! safeguard) - const double max_exceedance_fact_incr_tol; + double max_exceedance_fact_incr_tol; }; //! class for managing the Local Newton loop, containing the utilized parameters and iteration @@ -876,9 +897,6 @@ namespace Mat /// getter for local iteration count [[nodiscard]] unsigned int iter() const { return iter_; } - /// setter for local iteration count - void set_iteration_count(const unsigned int iter) { iter_ = iter; } - /// getter for total number of local iterations evaluated in this time step (vector over all /// Gauss points) [[nodiscard]] const std::vector& curr_num_iters() const @@ -886,9 +904,6 @@ namespace Mat return curr_num_iters_; } - /// increment iteration count by 1 - void increment_iteration_count() { iter_++; } - /*! * @brief Resizing based on a given number of Gauss points * @@ -896,6 +911,76 @@ namespace Mat */ void resize(const unsigned int numgp); + /*! + * @brief Initialize the solution vector and the convergence quantities, for the + * subsequent Local Newton at the currently considered Gauss point + * + * @param[in] init_estimate initial estimate \f$ \boldsymbol{s}^{(0)} \f$ + */ + void save_init_estimate_and_reset_convergence_quantities( + const Core::LinAlg::Matrix<10, 1>& init_estimate); + + /// reset iteration counter + void reset_iter() { iter_ = 0; } + + /// sets the residual norm based on the given residual vector + void set_residual_norm(const Core::LinAlg::Matrix<10, 1>& residual) + { + convergence_quantities_.residual_norm = residual.norm2(); + } + + /*! + * @brief Determine whether the Local Newton Loop has converged, based on the saved + * convergence quantities and the specified convergence checks. + * + * @return boolean: true = converged + */ + [[nodiscard]] bool is_local_newton_converged() const; + + + /*! + * @brief After an unsuccessful convergence check: determine whether the Local Newton is + * stuck / stagnates, i.e., the relative solution increment is nearly 0, but there is no + * convergence yet, based on the saved convergence quantities. + * + * @return boolean: true = stuck + */ + [[nodiscard]] bool is_local_newton_stuck() const; + + + /// is the maximum number of iterations reached? + [[nodiscard]] bool is_max_iter_reached() + { + return iter_ >= static_cast(params_.max_iter); + } + + + /// increment iteration counter + void increment_iter() { ++iter_; } + + /*! + * @brief Increments the solution vector \f$ \boldsymbol{s}^{(l+1)} = \boldsymbol{s}^{(l)} + * + + * \Delta \boldsymbol{s}^{(l+1)} \f$ after the current iteration \f$ l \f$ + * + * @note Also updates the increment norm (ratio of increment to solution) internally based on + * the provided increment + * + * @param[in] delta_sol increment vector for the next iteration \f$\Delta + * \boldsymbol{s}^{(l+1)}\f$ + */ + void increment_solution_vector(const Core::LinAlg::Matrix<10, 1>& delta_sol); + + /// getter for the solution vector + [[nodiscard]] Core::LinAlg::Matrix<10, 1> sol() const { return sol_; } + + + /// getter for the convergence quantities + [[nodiscard]] LocalNewtonConvQuantities convergence_quantities() const + { + return convergence_quantities_; + } + /*! * @brief Routine to be run after the Local Newton-Raphson at a given Gauss point * @@ -903,8 +988,8 @@ namespace Mat */ void update_after_local_newton(const unsigned int gp); - //! reset method - void reset(); + //! reset the saved number of iterations at a given Gauss point + void reset_curr_num_iters(const unsigned int gp); //! pack values void pack(Core::Communication::PackBuffer& data) const; @@ -922,12 +1007,50 @@ namespace Mat //! total number of local iterations for the current timestep; vector of Gauss point values std::vector curr_num_iters_; + //! solution vector in the current iteration \f$ \boldsymbol{s}^{(l)} \f$ (at the + //! currently considered Gauss point) + Core::LinAlg::Matrix<10, 1> sol_; + + //! quantities used for convergence checks + LocalNewtonConvQuantities convergence_quantities_; + //! tracks whether the resizing function has been called, to set the current number of //! Gauss points exactly once! bool resize_called_{false}; }; + //! helper struct containing deformation tensors passed as input + //! for the local time integration + struct LocalIntegrationDeformationTensors + { + /*! + * @brief constructor + * + * @param[in] F deformation gradient \f$ \mathbf{F}_{n+1} \f$ + * @param[in] last_iFp previous inverse inelastic/plastic deformation gradient \f$ + \mathbf{F}_{\text{p},n}^{-1} \f$ + * + */ + LocalIntegrationDeformationTensors( + const Core::LinAlg::Matrix<3, 3>& F, const Core::LinAlg::Matrix<3, 3>& last_iFp); + + //! deformation gradient \f$ \mathbf{F}_{n+1} \f$ + Core::LinAlg::Matrix<3, 3> defgrad; + + //! inverse deformation gradient \f$ \mathbf{F}_{n+1}^{-1} \f$ + Core::LinAlg::Matrix<3, 3> inv_defgrad; + //! right Cauchy-Green deformation tensor \f$ \mathbf{C}_{n+1} \f$ + Core::LinAlg::Matrix<3, 3> right_cg; + + //! inverse plastic deformation gradient within the elastic predictor \f$ + //! \left[ \mathbf{F}_{\mathrm{p},n+1}^{(\mathrm{E})} \right]^{-1} \f$ + Core::LinAlg::Matrix<3, 3> elastic_predictor_inverse_plastic_defgrad; + + //! elastic deformation gradient within the elastic predictor \f$ + //! \mathbf{F}_{\mathrm{e},n+1}^{(\mathrm{E})} \f$ + Core::LinAlg::Matrix<3, 3> elastic_predictor_elastic_defgrad; + }; } // namespace InelasticDefgradTransvIsotropElastViscoplastUtils diff --git a/src/mat/vplast/4C_mat_vplast_law.cpp b/src/mat/vplast/4C_mat_vplast_law.cpp index 46214201b60..40ba5e76b98 100644 --- a/src/mat/vplast/4C_mat_vplast_law.cpp +++ b/src/mat/vplast/4C_mat_vplast_law.cpp @@ -19,15 +19,22 @@ FOUR_C_NAMESPACE_OPEN /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ -Mat::Viscoplastic::Law::Law(Core::Mat::PAR::Parameter* params) : params_(params) {} +Mat::Viscoplastic::Law::Law(Core::Mat::PAR::Parameter* params, + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings) + : error_registration_settings_(error_registration_settings), params_(params) +{ +} /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ -Mat::Viscoplastic::Law::Law() : params_(nullptr) {} +Mat::Viscoplastic::Law::Law() : error_registration_settings_(), params_(nullptr) {} /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ -std::shared_ptr Mat::Viscoplastic::Law::factory(int matnum) +std::shared_ptr Mat::Viscoplastic::Law::factory(int matnum, + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings) { // for the sake of safety if (Global::Problem::instance()->materials() == nullptr) @@ -53,7 +60,8 @@ std::shared_ptr Mat::Viscoplastic::Law::factory(int matn auto* params = dynamic_cast(curmat); // return pointer to material - return std::make_shared(params); + return std::make_shared( + params, error_registration_settings); } default: diff --git a/src/mat/vplast/4C_mat_vplast_law.hpp b/src/mat/vplast/4C_mat_vplast_law.hpp index 2519c2058c4..22dda9ff668 100644 --- a/src/mat/vplast/4C_mat_vplast_law.hpp +++ b/src/mat/vplast/4C_mat_vplast_law.hpp @@ -61,8 +61,10 @@ namespace Mat class Law { public: - /// construct viscoplastic laws with specific material params - explicit Law(Core::Mat::PAR::Parameter* params); + /// construct viscoplastic laws with specific material params and error registration settings + explicit Law(Core::Mat::PAR::Parameter* params, + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings); /// construct empty viscoplastic law Law(); @@ -73,12 +75,20 @@ namespace Mat * @brief create object by input parameter ID * * @param[in] matnum material ID + * @param[in] error_registration_settings error registration settings for plastic strain + * increments and derivative increments * @return pointer to material that is defined by material ID */ - static std::shared_ptr factory(int matnum); + static std::shared_ptr factory(int matnum, + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings); /// provide material type - virtual Core::Materials::MaterialType material_type() const = 0; + [[nodiscard]] virtual Core::Materials::MaterialType material_type() const = 0; + + /// does the viscoplastic law use a yield surface formulation, or is it a no-yield-surface + /// law? + [[nodiscard]] virtual bool uses_yield_surface() const = 0; /*! * @brief Evaluate the ratio of the equivalent stress \f$ \overline{\sigma} \f$ to the yield @@ -117,7 +127,7 @@ namespace Mat * * @note To use the viscoplasticity components in the time * integration of history variables within InelasticDefgradTransvIsotropElastViscoplast, we - * have to check for eventual overflow errors within them. Specifically, we focus on the term + * may check for eventual overflow errors within them. Specifically, we focus on the term * \f$ \Delta t \dot{\varepsilon}^{\text{p}} \f$, which shall be * evaluable in the specific time integration used. Moreover, * for some viscoplasticity laws, we have to make sure that the given plastic strain is \f$ @@ -128,15 +138,11 @@ namespace Mat * @param[in] equiv_stress Equivalent stress \f$ \overline{\sigma} \f$ * @param[in] equiv_plastic_strain Equivalent plastic strain \f$ \varepsilon^{\text{p}}\f$ * @param[in] dt Time step size (used solely for overflow error checking, see @note) - * @param[in] max_plastic_strain_incr maximum, numerically evaluable plastic - * strain increment \f$ \Delta t \dot{\varepsilon}^{\text{p}}) \f$ (before throwing an - * overflow error) - * @param[out] err_status output variable: error of the terms considered in - * @note? + * @param[out] err_status Output variable: error due the term considered in @note? * @return Equivalent plastic strain rate \f$ \dot{\varepsilon}^{\text{p}} \f$ */ virtual double evaluate_plastic_strain_rate(const double equiv_stress, - const double equiv_plastic_strain, const double dt, const double max_plastic_strain_incr, + const double equiv_plastic_strain, const double dt, Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status, const bool update_hist_var = true) = 0; @@ -145,28 +151,27 @@ namespace Mat * \dot{\varepsilon}^{\text{p}} \f$ for a given equivalent stress \f$ \overline{\sigma} \f$ * and a given plastic strain \f$ \varepsilon^{\text{p}} \f$ * + * @note In addition to checking overflow based on the plastic strain increment (see + * documentation of evaluate_plastic_strain_rate), we may also verify overflow based on the + * derivatives of the plastic strain rate, scaled by the considered timestep. + * + * * @param[in] equiv_stress Equivalent stress \f$ \overline{\sigma} \f$ * @param[in] equiv_plastic_strain Equivalent plastic strain \f$ \varepsilon^{\text{p}}\f$ * @param[in] dt Time step size (used solely for overflow error checking, see @note of * evaluate_plastic_strain_rate) - * @param[in] max_plastic_strain_deriv_incr Maximum - * numerically evaluable increment of the - * plastic strain derivatives (before throwing an overflow error), - * i.e. \f$ \Delta t \frac{\partial \dot{\varepsilon}^{\text{p}}}{\partial s},~ s \in - * \{\varepsilon^{\text{p}}, \overline{\sigma}, T\} \f$ - * @param[out] err_status output variable: error of the terms considered in @note? + * @param[out] err_status Output variable: error of the terms considered in @note? * @return Derivatives of the equivalent plastic strain rate w.r.t. the equivalent stress, * plastic strain, and temperature. */ virtual InelasticDefgradTransvIsotropElastViscoplastUtils::PlasticStrainRateDerivs evaluate_derivatives_of_plastic_strain_rate(const double equiv_stress, const double equiv_plastic_strain, const double dt, - const double max_plastic_strain_deriv_incr, Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status, const bool update_hist_var = true) = 0; /// Return material parameters - virtual Core::Mat::PAR::Parameter* parameter() const { return params_; } + [[nodiscard]] virtual Core::Mat::PAR::Parameter* parameter() const { return params_; } /*! * @brief Setup viscoplasticity law for the specific element @@ -187,9 +192,12 @@ namespace Mat virtual void pre_evaluate(const Teuchos::ParameterList& params, int gp) { gp_ = gp; }; /*! - * @brief Update history variables of the viscoplasticity law for next time step + * @brief Update history variables of the viscoplasticity law for next time step at a given + * Gauss point + * + * @param[in] gp Current Gauss point */ - virtual void update() = 0; + virtual void update(const unsigned int gp) = 0; /*! * @brief Update the history variables for a specific GP after a converged substep @@ -197,7 +205,7 @@ namespace Mat * * @param[in] gp Gauss point */ - virtual void update_gp_state(int gp) = 0; + virtual void update_gp_state_after_substep(const unsigned int gp) = 0; virtual void pack_viscoplastic_law(Core::Communication::PackBuffer& data) const = 0; @@ -234,6 +242,11 @@ namespace Mat /// Gauss point index int gp_; + /// error registration settings for the plastic strain increments and the derivative + /// increments + const Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings_; + private: /// material parameters diff --git a/src/mat/vplast/4C_mat_vplast_reform_johnsoncook.cpp b/src/mat/vplast/4C_mat_vplast_reform_johnsoncook.cpp index d86f8b37f55..f49badcfc86 100644 --- a/src/mat/vplast/4C_mat_vplast_reform_johnsoncook.cpp +++ b/src/mat/vplast/4C_mat_vplast_reform_johnsoncook.cpp @@ -49,8 +49,10 @@ Mat::Viscoplastic::PAR::ReformulatedJohnsonCook::ReformulatedJohnsonCook( /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ Mat::Viscoplastic::ReformulatedJohnsonCook::ReformulatedJohnsonCook( - Core::Mat::PAR::Parameter* params) - : Mat::Viscoplastic::Law(params), + Core::Mat::PAR::Parameter* params, + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings) + : Mat::Viscoplastic::Law(params, error_registration_settings), const_pars_(parameter()->strain_rate_pre_fac(), 1.0 / parameter()->strain_rate_exp_fac(), parameter()->isotrop_harden_prefac(), parameter()->isotrop_harden_exp(), parameter()->init_yield_strength()) @@ -138,8 +140,7 @@ double Mat::Viscoplastic::ReformulatedJohnsonCook::compute_flow_resistance( *--------------------------------------------------------------------*/ double Mat::Viscoplastic::ReformulatedJohnsonCook::evaluate_plastic_strain_rate( const double equiv_stress, const double equiv_plastic_strain, const double dt, - const double max_plastic_strain_incr, ViscoplastErrorType& err_status, - const bool update_hist_var) + ViscoplastErrorType& err_status, const bool update_hist_var) { // first set error status to "no errors" err_status = ViscoplastErrorType::no_errors; @@ -176,10 +177,6 @@ double Mat::Viscoplastic::ReformulatedJohnsonCook::evaluate_plastic_strain_rate( EnumTools::enum_name(yield_strength_err_status)); } - // verify whether the maximum plastic strain increment is larger than 0, since we will take its - // logarithm - FOUR_C_ASSERT_ALWAYS(max_plastic_strain_incr > 0.0, - "Maximum plastic strain increment must be > 0: current value = {}", max_plastic_strain_incr); // stress ratio double stress_ratio = evaluate_stress_ratio(equiv_stress, equiv_plastic_strain); @@ -193,7 +190,9 @@ double Mat::Viscoplastic::ReformulatedJohnsonCook::evaluate_plastic_strain_rate( // check if characteristic term too large, throw error overflow // error if so - if (std::log(dt) + log_temp > std::log(max_plastic_strain_incr + const_pars_.p * dt)) + if (error_registration_settings_.register_plastic_strain_incr_overflow && + (std::log(dt) + log_temp > + std::log(error_registration_settings_.max_plastic_strain_incr + const_pars_.p * dt))) { err_status = ViscoplastErrorType::overflow_error; return -1; @@ -210,8 +209,7 @@ double Mat::Viscoplastic::ReformulatedJohnsonCook::evaluate_plastic_strain_rate( Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::PlasticStrainRateDerivs Mat::Viscoplastic::ReformulatedJohnsonCook::evaluate_derivatives_of_plastic_strain_rate( const double equiv_stress, const double equiv_plastic_strain, const double dt, - const double max_plastic_strain_deriv_incr, ViscoplastErrorType& err_status, - const bool update_hist_var) + ViscoplastErrorType& err_status, const bool update_hist_var) { // declare derivatives to be computed double deriv_equiv_stress{0.0}; @@ -279,19 +277,15 @@ Mat::Viscoplastic::ReformulatedJohnsonCook::evaluate_derivatives_of_plastic_stra const_pars_.log_p_e + const_pars_.e * (equiv_stress * inv_yield_strength - 1.0) + log_equiv_stress - 2.0 * log_yield_strength + log_neg_d_yield_strength_d_temperature; - // verify whether the maximum plastic strain derivative increment is larger than 0, since we - // will take its logarithm - FOUR_C_ASSERT_ALWAYS(max_plastic_strain_deriv_incr > 0.0, - "Maximum plastic strain derivative increment must be > 0: current value = {}", - max_plastic_strain_deriv_incr); - // perfect plasticity if (const_pars_.is_perfect_plasticity) { // check overflow error using these logarithms - double log_max_plastic_strain_deriv_value = std::log(max_plastic_strain_deriv_incr); - if ((log_dt + log_deriv_sigma > log_max_plastic_strain_deriv_value) or - (log_dt + log_deriv_temperature > log_max_plastic_strain_deriv_value)) + double log_max_plastic_strain_deriv_value = + std::log(error_registration_settings_.max_plastic_strain_deriv_incr); + if (error_registration_settings_.register_plastic_strain_deriv_incr_overflow && + ((log_dt + log_deriv_sigma > log_max_plastic_strain_deriv_value) or + (log_dt + log_deriv_temperature > log_max_plastic_strain_deriv_value))) { err_status = ViscoplastErrorType::failed_computation_flow_resistance_derivs; return InelasticDefgradTransvIsotropElastViscoplastUtils::PlasticStrainRateDerivs{ @@ -311,10 +305,12 @@ Mat::Viscoplastic::ReformulatedJohnsonCook::evaluate_derivatives_of_plastic_stra log_equiv_stress - 2.0 * log_yield_strength + const_pars_.log_B_N + (const_pars_.N - 1.0) * log_equiv_plastic_strain + log_temperature_ratio_; // check overflow error using these logarithms - double log_max_plastic_strain_deriv_value = std::log(max_plastic_strain_deriv_incr); - if ((log_dt + log_deriv_sigma > log_max_plastic_strain_deriv_value) or - (log_dt + log_neg_deriv_eps > log_max_plastic_strain_deriv_value) or - (log_dt + log_deriv_temperature > log_max_plastic_strain_deriv_value)) + double log_max_plastic_strain_deriv_value = + std::log(error_registration_settings_.max_plastic_strain_deriv_incr); + if (error_registration_settings_.register_plastic_strain_deriv_incr_overflow && + ((log_dt + log_deriv_sigma > log_max_plastic_strain_deriv_value) or + (log_dt + log_neg_deriv_eps > log_max_plastic_strain_deriv_value) or + (log_dt + log_deriv_temperature > log_max_plastic_strain_deriv_value))) { err_status = ViscoplastErrorType::failed_computation_flow_resistance_derivs; return InelasticDefgradTransvIsotropElastViscoplastUtils::PlasticStrainRateDerivs{ diff --git a/src/mat/vplast/4C_mat_vplast_reform_johnsoncook.hpp b/src/mat/vplast/4C_mat_vplast_reform_johnsoncook.hpp index 22dbf5fe59d..3c09c6fbdf7 100644 --- a/src/mat/vplast/4C_mat_vplast_reform_johnsoncook.hpp +++ b/src/mat/vplast/4C_mat_vplast_reform_johnsoncook.hpp @@ -12,6 +12,7 @@ #include "4C_comm_parobject.hpp" #include "4C_comm_parobjectfactory.hpp" #include "4C_linalg_fixedsizematrix.hpp" +#include "4C_mat_inelastic_defgrad_factors_service.hpp" #include "4C_mat_vplast_law.hpp" #include "4C_material_parameter_base.hpp" #include "4C_utils_exceptions.hpp" @@ -103,19 +104,23 @@ namespace Mat class ReformulatedJohnsonCook : public Law { public: - explicit ReformulatedJohnsonCook(Core::Mat::PAR::Parameter* params); + explicit ReformulatedJohnsonCook(Core::Mat::PAR::Parameter* params, + const InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings); - Mat::Viscoplastic::PAR::ReformulatedJohnsonCook* parameter() const override + [[nodiscard]] Mat::Viscoplastic::PAR::ReformulatedJohnsonCook* parameter() const override { return dynamic_cast( Mat::Viscoplastic::Law::parameter()); } - Core::Materials::MaterialType material_type() const override + [[nodiscard]] Core::Materials::MaterialType material_type() const override { return Core::Materials::mvl_reformulated_Johnson_Cook; }; + [[nodiscard]] bool uses_yield_surface() const override { return true; } + double evaluate_stress_ratio( const double equiv_stress, const double equiv_plastic_strain) override; @@ -123,14 +128,13 @@ namespace Mat Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status) override; double evaluate_plastic_strain_rate(const double equiv_stress, - const double equiv_plastic_strain, const double dt, const double max_plastic_strain_incr, + const double equiv_plastic_strain, const double dt, Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status, const bool update_hist_var) override; InelasticDefgradTransvIsotropElastViscoplastUtils::PlasticStrainRateDerivs evaluate_derivatives_of_plastic_strain_rate(const double equiv_stress, const double equiv_plastic_strain, const double dt, - const double max_plastic_strain_deriv_incr, Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType& err_status, const bool update_hist_var) override; @@ -140,9 +144,9 @@ namespace Mat void pre_evaluate(const Teuchos::ParameterList& params, int gp) override; - void update() override {}; + void update(const unsigned int gp) override {}; - void update_gp_state(int gp) override {}; + void update_gp_state_after_substep(const unsigned int gp) override {}; void pack_viscoplastic_law(Core::Communication::PackBuffer& data) const override; diff --git a/tests/input_files/mat_iso_viscoplast_refJC_log_timint.4C.yaml b/tests/input_files/mat_iso_viscoplast_refJC_log_timint.4C.yaml index cf03bdf6e75..b0171450079 100644 --- a/tests/input_files/mat_iso_viscoplast_refJC_log_timint.4C.yaml +++ b/tests/input_files/mat_iso_viscoplast_refJC_log_timint.4C.yaml @@ -59,6 +59,11 @@ MATERIALS: MAX_EXCEEDANCE_FACT_RES_TOL: 10 MAX_EXCEEDANCE_FACT_INCR_TOL: 10 DIVER_CONT: stop + ERROR_REGISTRATION_SETTINGS: + REGISTER_PLASTIC_STRAIN_INCR_OVERFLOW: true + MAX_PLASTIC_STRAIN_INCR: 10686474581524.463 + REGISTER_PLASTIC_STRAIN_DERIV_INCR_OVERFLOW: false + MAX_PLASTIC_STRAIN_DERIV_INCR: 10686474581524.463 - MAT: 4 MAT_ViscoplasticLawReformulatedJohnsonCook: STRAIN_RATE_PREFAC: 1 diff --git a/tests/input_files/mat_iso_viscoplast_refJC_log_timint_substepping.4C.yaml b/tests/input_files/mat_iso_viscoplast_refJC_log_timint_substepping.4C.yaml index 441ddc3055a..7a2a3b78b26 100644 --- a/tests/input_files/mat_iso_viscoplast_refJC_log_timint_substepping.4C.yaml +++ b/tests/input_files/mat_iso_viscoplast_refJC_log_timint_substepping.4C.yaml @@ -95,25 +95,25 @@ RESULT DESCRIPTION: DIS: "structure" NODE: 4 QUANTITY: "dispy" - VALUE: -4.01592180458057706e-03 + VALUE: -4.01558458395893415e-03 TOLERANCE: 4e-11 - STRUCTURE: DIS: "structure" NODE: 5 QUANTITY: "dispx" - VALUE: -4.01592180458140973e-03 + VALUE: -4.01558458395998453e-03 TOLERANCE: 4e-11 - STRUCTURE: DIS: "structure" NODE: 8 QUANTITY: "dispx" - VALUE: -4.01592180458110789e-03 + VALUE: -4.01558458395858894e-03 TOLERANCE: 4e-11 - STRUCTURE: DIS: "structure" NODE: 8 QUANTITY: "dispy" - VALUE: -4.01592180458025701e-03 + VALUE: -4.01558458395919263e-03 TOLERANCE: 4e-11 - STRUCTURE: DIS: "structure" @@ -125,19 +125,19 @@ RESULT DESCRIPTION: DIS: "structure" NODE: 6 QUANTITY: "dispx" - VALUE: -4.01592180458238204e-03 + VALUE: -4.01558458395947105e-03 TOLERANCE: 4e-11 - STRUCTURE: DIS: "structure" NODE: 4 QUANTITY: "stress_zz" - VALUE: 9.30776106020185466e+02 + VALUE: 9.31099439482890148e+02 TOLERANCE: 0.00098 - STRUCTURE: DIS: "structure" NODE: 8 QUANTITY: "stress_zz" - VALUE: 9.30776106016615358e+02 + VALUE: 9.31099439481397212e+02 TOLERANCE: 0.00098 DESIGN POINT DIRICH CONDITIONS: - E: 1 diff --git a/unittests/mat/4C_inelastic_defgrad_factors_service_test.cpp b/unittests/mat/4C_inelastic_defgrad_factors_service_test.cpp new file mode 100644 index 00000000000..a74454452bb --- /dev/null +++ b/unittests/mat/4C_inelastic_defgrad_factors_service_test.cpp @@ -0,0 +1,420 @@ +// This file is part of 4C multiphysics licensed under the +// GNU Lesser General Public License v3.0 or later. +// +// See the LICENSE.md file in the top-level for license information. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include + +#include "4C_linalg_fixedsizematrix.hpp" +#include "4C_mat_inelastic_defgrad_factors_service.hpp" +#include "4C_unittest_utils_assertions_test.hpp" +#include "4C_utils_singleton_owner.hpp" + + +namespace +{ + using namespace FourC; + + namespace ViscoplastUtils = Mat::InelasticDefgradTransvIsotropElastViscoplastUtils; + + class InelasticDefgradFactorsServiceTest : public ::testing::Test + { + protected: + void SetUp() override {} + + + Core::Utils::SingletonOwnerRegistry::ScopeGuard guard; + }; + + /// tests the LocalIntegrationDeformationTensors of + /// InelasticDefgradTransvIsotropElastViscoplast + TEST_F(InelasticDefgradFactorsServiceTest, TestLocalIntegrationDeformationTensors) + { + // setup input + Core::LinAlg::Matrix<3, 3> defgrad{Core::LinAlg::Initialization::zero}; + defgrad(0, 0) = 0.2513819028974873; + defgrad(0, 1) = 0.957511195526664; + defgrad(0, 2) = 0.8703229224151933; + defgrad(1, 0) = 0.675673714544612; + defgrad(1, 1) = 0.040444301498430923; + defgrad(1, 2) = 0.10298502801901921; + defgrad(2, 0) = 0.20079631315327318; + defgrad(2, 1) = 0.6901106554801166; + defgrad(2, 2) = 0.1769124998126297; + + + Core::LinAlg::Matrix<3, 3> last_iFin{Core::LinAlg::Initialization::zero}; + last_iFin(0, 0) = 0.35530729350748047; + last_iFin(0, 1) = 0.5829896953147952; + last_iFin(0, 2) = 0.9336918888091672; + last_iFin(1, 0) = 0.3099852313939162; + last_iFin(1, 1) = 0.7243285059889488; + last_iFin(1, 2) = 0.43375156919140767; + last_iFin(2, 0) = 0.41454463288433163; + last_iFin(2, 1) = 0.6433884759079006; + last_iFin(2, 2) = 0.23890433987101256; + + + // reference tensors based on input + Core::LinAlg::Matrix<3, 3> inv_defgrad_ref{Core::LinAlg::Initialization::zero}; + inv_defgrad_ref(0, 0) = -0.22190619146746082; + inv_defgrad_ref(0, 1) = 1.4971400487822994; + inv_defgrad_ref(0, 2) = 0.2201485775679747; + inv_defgrad_ref(1, 0) = -0.34321290611467375; + inv_defgrad_ref(1, 1) = -0.4523291882409134; + inv_defgrad_ref(1, 2) = 1.951751255286342; + inv_defgrad_ref(2, 0) = 1.590689346533634; + inv_defgrad_ref(2, 1) = 0.06521297552376205; + inv_defgrad_ref(2, 2) = -2.2108633434926004; + + + Core::LinAlg::Matrix<3, 3> right_cg_ref{Core::LinAlg::Initialization::zero}; + right_cg_ref(0, 0) = 0.5600469890068229; + right_cg_ref(0, 1) = 0.40659981309094395; + right_cg_ref(0, 2) = 0.3238910865092303; + right_cg_ref(1, 0) = 0.40659981309094395; + right_cg_ref(1, 1) = 1.3947161478897936; + right_cg_ref(1, 2) = 0.9595983006673772; + right_cg_ref(2, 0) = 0.3238910865092303; + right_cg_ref(2, 1) = 0.9595983006673772; + right_cg_ref(2, 2) = 0.7993659378673543; + + + Core::LinAlg::Matrix<3, 3> elastic_predictor_inverse_plastic_defgrad_ref{ + Core::LinAlg::Initialization::zero}; + elastic_predictor_inverse_plastic_defgrad_ref(0, 0) = 0.35530729350748047; + elastic_predictor_inverse_plastic_defgrad_ref(0, 1) = 0.5829896953147952; + elastic_predictor_inverse_plastic_defgrad_ref(0, 2) = 0.9336918888091672; + elastic_predictor_inverse_plastic_defgrad_ref(1, 0) = 0.3099852313939162; + elastic_predictor_inverse_plastic_defgrad_ref(1, 1) = 0.7243285059889488; + elastic_predictor_inverse_plastic_defgrad_ref(1, 2) = 0.43375156919140767; + elastic_predictor_inverse_plastic_defgrad_ref(2, 0) = 0.41454463288433163; + elastic_predictor_inverse_plastic_defgrad_ref(2, 1) = 0.6433884759079006; + elastic_predictor_inverse_plastic_defgrad_ref(2, 2) = 0.23890433987101256; + + + Core::LinAlg::Matrix<3, 3> elastic_predictor_elastic_defgrad_ref{ + Core::LinAlg::Initialization::zero}; + elastic_predictor_elastic_defgrad_ref(0, 0) = 0.7469198494262896; + elastic_predictor_elastic_defgrad_ref(0, 1) = 1.4000614513018017; + elastic_predictor_elastic_defgrad_ref(0, 2) = 0.8579591505610411; + elastic_predictor_elastic_defgrad_ref(1, 0) = 0.2953008256002754; + elastic_predictor_elastic_defgrad_ref(1, 1) = 0.48946515367319354; + elastic_predictor_elastic_defgrad_ref(1, 2) = 0.6730174161271413; + elastic_predictor_elastic_defgrad_ref(2, 0) = 0.3586066330866571; + elastic_predictor_elastic_defgrad_ref(2, 1) = 0.7307524651000326; + elastic_predictor_elastic_defgrad_ref(2, 2) = 0.5290836326068751; + + // initialize LocalIntegrationDeformationTensors and perform checks for the saved quantities + ViscoplastUtils::LocalIntegrationDeformationTensors deftensors(defgrad, last_iFin); + FOUR_C_EXPECT_NEAR(deftensors.defgrad, defgrad, 1.0e-15); + FOUR_C_EXPECT_NEAR(deftensors.inv_defgrad, inv_defgrad_ref, 1.0e-15); + FOUR_C_EXPECT_NEAR(deftensors.right_cg, right_cg_ref, 1.0e-15); + FOUR_C_EXPECT_NEAR(deftensors.elastic_predictor_elastic_defgrad, + elastic_predictor_elastic_defgrad_ref, 1.0e-15); + FOUR_C_EXPECT_NEAR(deftensors.elastic_predictor_inverse_plastic_defgrad, + elastic_predictor_inverse_plastic_defgrad_ref, 1.0e-15); + } + + + /// tests the bookkeeping of iterations within the LocalNewtonManager of + /// InelasticDefgradTransvIsotropElastViscoplast + TEST_F(InelasticDefgradFactorsServiceTest, TestLocalNewtonManagerIterBookkeeping) + { + auto local_newton_params = + Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonParams{ + .res_tol = 1.0e-8, + .incr_tol = 1.0e-8, + .conv_check = ViscoplastUtils::LocalNewtonConvCheck::residual_and_increment_ratio, + .diver_cont = ViscoplastUtils::LocalNewtonDiverCont::stop, + .max_iter = 5, + .max_exceedance_fact_res_tol = 1.0e1, + .max_exceedance_fact_incr_tol = 1.0e1, + + }; + Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager local_newton_manager( + local_newton_params); + + EXPECT_EQ(local_newton_manager.iter(), 0); + EXPECT_EQ(local_newton_manager.curr_num_iters().size(), 1); + EXPECT_EQ(local_newton_manager.curr_num_iters()[0], 0); + + local_newton_manager.resize(3); + EXPECT_EQ(local_newton_manager.curr_num_iters().size(), 3); + EXPECT_EQ(local_newton_manager.curr_num_iters()[0], 0); + EXPECT_EQ(local_newton_manager.curr_num_iters()[1], 0); + EXPECT_EQ(local_newton_manager.curr_num_iters()[2], 0); + + Core::LinAlg::Matrix<10, 1> one_10x1{Core::LinAlg::Initialization::zero}; + for (unsigned int i = 0; i < 10; ++i) one_10x1(i) = 1.0; + + local_newton_manager.reset_iter(); + local_newton_manager.save_init_estimate_and_reset_convergence_quantities(one_10x1); + local_newton_manager.increment_solution_vector(one_10x1); + local_newton_manager.increment_iter(); + local_newton_manager.increment_solution_vector(one_10x1); + local_newton_manager.increment_iter(); + local_newton_manager.increment_solution_vector(one_10x1); + local_newton_manager.increment_iter(); + EXPECT_EQ(local_newton_manager.iter(), 3); + local_newton_manager.update_after_local_newton(1); + EXPECT_EQ(local_newton_manager.curr_num_iters()[1], 3); + + local_newton_manager.save_init_estimate_and_reset_convergence_quantities(one_10x1); + local_newton_manager.increment_solution_vector(one_10x1); + local_newton_manager.increment_iter(); + EXPECT_EQ(local_newton_manager.iter(), 4); + local_newton_manager.update_after_local_newton(1); + EXPECT_EQ(local_newton_manager.curr_num_iters()[1], 7); + + local_newton_manager.reset_curr_num_iters(0); + EXPECT_EQ(local_newton_manager.curr_num_iters()[0], 0); + local_newton_manager.reset_curr_num_iters(1); + EXPECT_EQ(local_newton_manager.curr_num_iters()[1], 0); + local_newton_manager.reset_curr_num_iters(2); + EXPECT_EQ(local_newton_manager.curr_num_iters()[2], 0); + + + // test whether the maximum number of iterations was exceeded + EXPECT_FALSE(local_newton_manager.is_max_iter_reached()); + local_newton_manager.increment_solution_vector(one_10x1); + local_newton_manager.increment_iter(); + local_newton_manager.increment_solution_vector(one_10x1); + local_newton_manager.increment_iter(); + EXPECT_TRUE(local_newton_manager.is_max_iter_reached()); + } + + + /// tests the basic functionality of the LocalNewtonManager (initialization, incrementation, + /// convergence and "stuckness" verification) used within + /// InelasticDefgradTransvIsotropElastViscoplast + TEST_F(InelasticDefgradFactorsServiceTest, TestLocalNewtonManagerBasicFunctionality) + { + auto local_newton_params = + Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonParams{ + .res_tol = 1.0e-8, + .incr_tol = 1.0e-8, + .conv_check = ViscoplastUtils::LocalNewtonConvCheck::residual_and_increment_ratio, + .diver_cont = ViscoplastUtils::LocalNewtonDiverCont::stop, + .max_iter = 100, + .max_exceedance_fact_res_tol = 0.0, + .max_exceedance_fact_incr_tol = 0.0, + }; + Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager local_newton_manager( + local_newton_params); + + // auxiliaries + Core::LinAlg::Matrix<10, 1> one_10x1{Core::LinAlg::Initialization::zero}; + for (unsigned int i = 0; i < 10; ++i) one_10x1(i) = 1.0; + + + // --> test initialization with and without iteration counter reset + + // with iteration counter reset + local_newton_manager.reset_iter(); + local_newton_manager.save_init_estimate_and_reset_convergence_quantities(one_10x1); + FOUR_C_EXPECT_NEAR(local_newton_manager.sol(), one_10x1, 1.0e-15); + EXPECT_EQ(local_newton_manager.iter(), 0); + + // without iteration counter reset + local_newton_manager.increment_solution_vector(one_10x1); + local_newton_manager.increment_iter(); // increment the iteration counter + local_newton_manager.save_init_estimate_and_reset_convergence_quantities(one_10x1); + FOUR_C_EXPECT_NEAR(local_newton_manager.sol(), one_10x1, 1.0e-15); + EXPECT_EQ(local_newton_manager.iter(), 1); + + + // --> test workflow within the Local Newton: increment the solution vector (save the + // increment), then set the residual norm, and perform the convergence check + Core::LinAlg::Matrix<10, 1> vector_under_tol{ + Core::LinAlg::Initialization::zero}; // the 2-norm of this vector is smaller than the set + // value for residual and increment tolerance + vector_under_tol(0) = 1.0e-9; + Core::LinAlg::Matrix<10, 1> vector_over_tol{Core::LinAlg::Initialization::zero}; + vector_over_tol(0) = 1.0e-7; // the 2-norm of this vector is smaller than the set value for + // residual and increment tolerance + + Core::LinAlg::Matrix<10, 1> updated_sol_ref( + Core::LinAlg::Initialization::zero); // reference: updated solution vector, used for the + // solution vector checks + + // try out increment and residual vector exceeding the tolerance: no convergence! + local_newton_manager.reset_iter(); + local_newton_manager.save_init_estimate_and_reset_convergence_quantities(one_10x1); + local_newton_manager.increment_solution_vector(vector_over_tol); + local_newton_manager.increment_iter(); + updated_sol_ref.update(1.0, one_10x1, 1.0, vector_over_tol, 0.0); + FOUR_C_EXPECT_NEAR(local_newton_manager.sol(), updated_sol_ref, 1.0e-15); + EXPECT_EQ(local_newton_manager.convergence_quantities().increment_norm, + vector_over_tol(0) / updated_sol_ref.norm2()); + EXPECT_EQ(local_newton_manager.iter(), 1); + local_newton_manager.set_residual_norm(vector_over_tol); + EXPECT_EQ(local_newton_manager.convergence_quantities().residual_norm, vector_over_tol(0)); + EXPECT_FALSE(local_newton_manager.is_local_newton_converged()); + + // try out increment exceeding the tolerance, and residual vector under the tolerance: no + // convergence! + local_newton_manager.increment_solution_vector(vector_over_tol); + local_newton_manager.increment_iter(); + updated_sol_ref.update(1.0, vector_over_tol, 1.0); + FOUR_C_EXPECT_NEAR(local_newton_manager.sol(), updated_sol_ref, 1.0e-15); + EXPECT_EQ(local_newton_manager.convergence_quantities().increment_norm, + vector_over_tol(0) / updated_sol_ref.norm2()); + EXPECT_EQ(local_newton_manager.iter(), 2); + local_newton_manager.set_residual_norm(vector_under_tol); + EXPECT_EQ(local_newton_manager.convergence_quantities().residual_norm, vector_under_tol(0)); + EXPECT_FALSE(local_newton_manager.is_local_newton_converged()); + + // now the other way around: no convergence! + local_newton_manager.increment_solution_vector(vector_under_tol); + local_newton_manager.increment_iter(); + updated_sol_ref.update(1.0, vector_under_tol, 1.0); + FOUR_C_EXPECT_NEAR(local_newton_manager.sol(), updated_sol_ref, 1.0e-15); + EXPECT_EQ(local_newton_manager.convergence_quantities().increment_norm, + vector_under_tol(0) / updated_sol_ref.norm2()); + EXPECT_EQ(local_newton_manager.iter(), 3); + local_newton_manager.set_residual_norm(vector_over_tol); + EXPECT_EQ(local_newton_manager.convergence_quantities().residual_norm, vector_over_tol(0)); + EXPECT_FALSE(local_newton_manager.is_local_newton_converged()); + + // now, both increment and residual are under the tolerance: convergence! + local_newton_manager.increment_solution_vector(vector_under_tol); + local_newton_manager.increment_iter(); + updated_sol_ref.update(1.0, vector_under_tol, 1.0); + FOUR_C_EXPECT_NEAR(local_newton_manager.sol(), updated_sol_ref, 1.0e-15); + EXPECT_EQ(local_newton_manager.convergence_quantities().increment_norm, + vector_under_tol(0) / updated_sol_ref.norm2()); + EXPECT_EQ(local_newton_manager.iter(), 4); + local_newton_manager.set_residual_norm(vector_under_tol); + EXPECT_EQ(local_newton_manager.convergence_quantities().residual_norm, vector_under_tol(0)); + EXPECT_TRUE(local_newton_manager.is_local_newton_converged()); + + // --> test whether the Local Newton becomes stuck: increment is exactly 0.0, but the residual + // is still over the set tolerance + EXPECT_FALSE(local_newton_manager.is_local_newton_stuck()); // for the previous settings, the + // Local Newton should not be stuck + Core::LinAlg::Matrix<10, 1> zero_10x1{Core::LinAlg::Initialization::zero}; + local_newton_manager.increment_solution_vector(zero_10x1); + local_newton_manager.increment_iter(); + FOUR_C_EXPECT_NEAR(local_newton_manager.sol(), updated_sol_ref, 1.0e-15); + EXPECT_EQ(local_newton_manager.convergence_quantities().increment_norm, 0.0); + EXPECT_EQ(local_newton_manager.iter(), 5); + local_newton_manager.set_residual_norm(vector_over_tol); + EXPECT_EQ(local_newton_manager.convergence_quantities().residual_norm, vector_over_tol(0)); + EXPECT_TRUE(local_newton_manager.is_local_newton_stuck()); + } + + + /// tests the convergence of the LocalNewtonManager (for various settings) used within + /// InelasticDefgradTransvIsotropElastViscoplast + TEST_F(InelasticDefgradFactorsServiceTest, TestLocalNewtonManagerConvergenceVerification) + { + // framework for setting up multiple LocalNewtonManager objects with varied parameters + auto local_newton_base_params = + Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonParams{ + .res_tol = 1.0e-8, + .incr_tol = 1.0e-10, + .conv_check = ViscoplastUtils::LocalNewtonConvCheck::residual_and_increment_ratio, + .diver_cont = ViscoplastUtils::LocalNewtonDiverCont::stop, + .max_iter = 100, + .max_exceedance_fact_res_tol = 0.0, + .max_exceedance_fact_incr_tol = 0.0, + }; + auto set_up_local_newton_manager = [local_newton_base_params]( + const ViscoplastUtils::LocalNewtonConvCheck conv_check) + { + Core::LinAlg::Matrix<10, 1> one_10x1{Core::LinAlg::Initialization::zero}; + for (unsigned int i = 0; i < 10; ++i) one_10x1(i) = 1.0; + + auto manager = ViscoplastUtils::LocalNewtonManager({ + .res_tol = local_newton_base_params.res_tol, + .incr_tol = local_newton_base_params.incr_tol, + .conv_check = conv_check, // override + .diver_cont = local_newton_base_params.diver_cont, + .max_iter = local_newton_base_params.max_iter, + .max_exceedance_fact_res_tol = local_newton_base_params.max_exceedance_fact_res_tol, + .max_exceedance_fact_incr_tol = local_newton_base_params.max_exceedance_fact_incr_tol, + }); + manager.reset_iter(); + manager.save_init_estimate_and_reset_convergence_quantities(one_10x1); + + return manager; + }; + + // setup several Local Newton managers + ViscoplastUtils::LocalNewtonManager manager_res_and_incr = set_up_local_newton_manager( + ViscoplastUtils::LocalNewtonConvCheck::residual_and_increment_ratio); + ViscoplastUtils::LocalNewtonManager manager_res = + set_up_local_newton_manager(ViscoplastUtils::LocalNewtonConvCheck::residual); + ViscoplastUtils::LocalNewtonManager manager_incr = + set_up_local_newton_manager(ViscoplastUtils::LocalNewtonConvCheck::increment_ratio); + + // setup vectors (residual / increment) to be used for convergence checks + auto vector_from_tol = [](const double first_value) + { + Core::LinAlg::Matrix<10, 1> out{ + Core::LinAlg::Initialization::zero}; // the 2-norm of this vector is smaller than the set + // value for residual and increment tolerance + out(0) = first_value; + + return out; + }; + + // setup numerical values smaller than, or exceeding the set tolerances + const double exceeds_incr_tol{1.0e-9}; + const double exceeds_res_tol{1.0e-7}; + const double smaller_than_incr_tol{1.0e-10}; + const double smaller_than_res_tol{1.0e-9}; + + + // try out residual and increment exceeding the set tolerances + manager_res_and_incr.increment_solution_vector(vector_from_tol(exceeds_incr_tol)); + manager_res_and_incr.increment_iter(); + manager_res.increment_solution_vector(vector_from_tol(exceeds_incr_tol)); + manager_res.increment_iter(); + manager_incr.increment_solution_vector(vector_from_tol(exceeds_incr_tol)); + manager_incr.increment_iter(); + + manager_res_and_incr.set_residual_norm(vector_from_tol(exceeds_res_tol)); + manager_res.set_residual_norm(vector_from_tol(exceeds_res_tol)); + manager_incr.set_residual_norm(vector_from_tol(exceeds_res_tol)); + + EXPECT_FALSE(manager_res_and_incr.is_local_newton_converged()); + EXPECT_FALSE(manager_res.is_local_newton_converged()); + EXPECT_FALSE(manager_incr.is_local_newton_converged()); + + // try out residual smaller than the set tolerance, with increment exceeding its set tolerance + manager_res_and_incr.increment_solution_vector(vector_from_tol(exceeds_incr_tol)); + manager_res_and_incr.increment_iter(); + manager_res.increment_solution_vector(vector_from_tol(exceeds_incr_tol)); + manager_res.increment_iter(); + manager_incr.increment_solution_vector(vector_from_tol(exceeds_incr_tol)); + manager_incr.increment_iter(); + + manager_res_and_incr.set_residual_norm(vector_from_tol(smaller_than_res_tol)); + manager_res.set_residual_norm(vector_from_tol(smaller_than_res_tol)); + manager_incr.set_residual_norm(vector_from_tol(smaller_than_res_tol)); + + EXPECT_FALSE(manager_res_and_incr.is_local_newton_converged()); + EXPECT_TRUE(manager_res.is_local_newton_converged()); + EXPECT_FALSE(manager_incr.is_local_newton_converged()); + + // try out residual exceeding its set tolerance, with increment smaller than its set tolerance + manager_res_and_incr.increment_solution_vector(vector_from_tol(smaller_than_incr_tol)); + manager_res_and_incr.increment_iter(); + manager_res.increment_solution_vector(vector_from_tol(smaller_than_incr_tol)); + manager_res.increment_iter(); + manager_incr.increment_solution_vector(vector_from_tol(smaller_than_incr_tol)); + manager_incr.increment_iter(); + + manager_res_and_incr.set_residual_norm(vector_from_tol(exceeds_res_tol)); + manager_res.set_residual_norm(vector_from_tol(exceeds_res_tol)); + manager_incr.set_residual_norm(vector_from_tol(exceeds_res_tol)); + + EXPECT_FALSE(manager_res_and_incr.is_local_newton_converged()); + EXPECT_FALSE(manager_res.is_local_newton_converged()); + EXPECT_TRUE(manager_incr.is_local_newton_converged()); + } +} // namespace diff --git a/unittests/mat/4C_inelastic_defgrad_factors_test.cpp b/unittests/mat/4C_inelastic_defgrad_factors_test.cpp index b06cf1fc20d..6b4fa61b4aa 100644 --- a/unittests/mat/4C_inelastic_defgrad_factors_test.cpp +++ b/unittests/mat/4C_inelastic_defgrad_factors_test.cpp @@ -168,17 +168,26 @@ namespace material_data.group("LOCAL_SUBSTEPPING").add("USE_SUBSTEPPING", setup.use_substepping); material_data.group("LOCAL_SUBSTEPPING") .add("MAX_SUBSTEPPING_HALVE_NUM", static_cast(setup.max_substepping_halve_num)); - material_data.group("LOCAL_NEWTON").add("CONV_CHECK", setup.local_newton_params.conv_check); - material_data.group("LOCAL_NEWTON").add("DIVER_CONT", setup.local_newton_params.diver_cont); - material_data.group("LOCAL_NEWTON").add("INCR_TOL", setup.local_newton_params.incr_tol); - material_data.group("LOCAL_NEWTON").add("RES_TOL", setup.local_newton_params.res_tol); - material_data.group("LOCAL_NEWTON") - .add("MAX_ITER", static_cast(setup.local_newton_params.max_iter)); - material_data.group("LOCAL_NEWTON") - .add("MAX_EXCEEDANCE_FACT_RES_TOL", setup.local_newton_params.max_exceedance_fact_res_tol); - material_data.group("LOCAL_NEWTON") - .add( - "MAX_EXCEEDANCE_FACT_INCR_TOL", setup.local_newton_params.max_exceedance_fact_incr_tol); + const auto local_newton_params = + Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonParams{ + .res_tol = setup.local_newton_params.res_tol, + .incr_tol = setup.local_newton_params.incr_tol, + .conv_check = setup.local_newton_params.conv_check, + .diver_cont = setup.local_newton_params.diver_cont, + .max_iter = setup.local_newton_params.max_iter, + .max_exceedance_fact_res_tol = setup.local_newton_params.max_exceedance_fact_res_tol, + .max_exceedance_fact_incr_tol = setup.local_newton_params.max_exceedance_fact_incr_tol, + }; + material_data.add("LOCAL_NEWTON", local_newton_params); + const auto error_registration_settings = + Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings{ + .register_plastic_strain_incr_overflow = true, + .max_plastic_strain_incr = std::exp(30.0), + .register_plastic_strain_deriv_incr_overflow = false, + .max_plastic_strain_deriv_incr = std::exp(30.0)}; + material_data.add("ERROR_REGISTRATION_SETTINGS", error_registration_settings); + + auto material_params = std::dynamic_pointer_cast( @@ -229,7 +238,7 @@ namespace Core::Materials::MaterialType::mvl_reformulated_Johnson_Cook, viscoplastic_law_data)); auto viscoplastic_law = std::make_shared( - problem.materials()->parameter_by_id(viscoplastic_law_id)); + problem.materials()->parameter_by_id(viscoplastic_law_id), error_registration_settings); std::vector> pot_sum_el; pot_sum_el.emplace_back(Mat::Elastic::Summand::factory(200)); @@ -1797,52 +1806,6 @@ namespace computed_state_quantities_isotrop.curr_lpM, 1.0e-10); } - TEST_F(InelasticDefgradFactorsTest, TestLocalNewtonParametersParsing) - { - const auto local_newton_params = set_up_viscoplastic_material().params->local_newton_params(); - - EXPECT_EQ(local_newton_params.conv_check, - Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonConvCheck:: - residual_and_increment_ratio); - EXPECT_EQ(local_newton_params.diver_cont, - Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonDiverCont::stop); - EXPECT_EQ(local_newton_params.max_iter, 100); - EXPECT_DOUBLE_EQ(local_newton_params.res_tol, 1.0e-8); - EXPECT_DOUBLE_EQ(local_newton_params.incr_tol, 1.0e-8); - EXPECT_DOUBLE_EQ(local_newton_params.max_exceedance_fact_res_tol, 1.0e1); - EXPECT_DOUBLE_EQ(local_newton_params.max_exceedance_fact_incr_tol, 1.0e1); - } - - TEST_F(InelasticDefgradFactorsTest, TestLocalNewtonManagerBookkeeping) - { - const auto material = set_up_viscoplastic_material(); - Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonManager local_newton_manager( - material.params->local_newton_params()); - - EXPECT_EQ(local_newton_manager.iter(), 0); - EXPECT_EQ(local_newton_manager.curr_num_iters().size(), 1); - EXPECT_EQ(local_newton_manager.curr_num_iters()[0], 0); - - local_newton_manager.resize(3); - EXPECT_EQ(local_newton_manager.curr_num_iters().size(), 3); - EXPECT_EQ(local_newton_manager.curr_num_iters()[0], 0); - EXPECT_EQ(local_newton_manager.curr_num_iters()[1], 0); - EXPECT_EQ(local_newton_manager.curr_num_iters()[2], 0); - - local_newton_manager.set_iteration_count(4); - local_newton_manager.update_after_local_newton(1); - EXPECT_EQ(local_newton_manager.curr_num_iters()[1], 4); - - local_newton_manager.set_iteration_count(2); - local_newton_manager.update_after_local_newton(1); - EXPECT_EQ(local_newton_manager.curr_num_iters()[1], 6); - - local_newton_manager.reset(); - EXPECT_EQ(local_newton_manager.curr_num_iters()[0], 0); - EXPECT_EQ(local_newton_manager.curr_num_iters()[1], 0); - EXPECT_EQ(local_newton_manager.curr_num_iters()[2], 0); - } - TEST_F(InelasticDefgradFactorsTest, TestLocalNewtonDivergenceHandlingStop) { Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::LocalNewtonParams local_newton_params{ @@ -1880,7 +1843,9 @@ namespace Core::LinAlg::Matrix<3, 3> iFin_result(Core::LinAlg::Initialization::zero); FOUR_C_EXPECT_THROW_WITH_MESSAGE( material->evaluate_inverse_inelastic_def_grad(&FM_, iFin_other, iFin_result), - Core::Exception, "Local Newton Loop did not converge"); + Core::Exception, + "Error in InelasticDefgradTransvIsotropElastViscoplast: Local Newton Loop did not converge " + "for the given loop settings!"); } TEST_F(InelasticDefgradFactorsTest, TestLocalNewtonDivergenceHandlingContinue) @@ -2050,7 +2015,9 @@ namespace Core::LinAlg::Matrix<3, 3> iFin_result(Core::LinAlg::Initialization::zero); FOUR_C_EXPECT_THROW_WITH_MESSAGE( material->evaluate_inverse_inelastic_def_grad(&FM_, iFin_other, iFin_result), - Core::Exception, "Local Newton Loop did not converge"); + Core::Exception, + "Error in InelasticDefgradTransvIsotropElastViscoplast: Local Newton Loop did not converge " + "for the given loop settings!"); } TEST_F(InelasticDefgradFactorsTest, TestLocalNewtonResidualConvergence) @@ -2127,7 +2094,9 @@ namespace Core::LinAlg::Matrix<3, 3> iFin_result(Core::LinAlg::Initialization::zero); FOUR_C_EXPECT_THROW_WITH_MESSAGE( material->evaluate_inverse_inelastic_def_grad(&FM_, iFin_other, iFin_result), - Core::Exception, "Local Newton Loop did not converge"); + Core::Exception, + "Error in InelasticDefgradTransvIsotropElastViscoplast: Local Newton Loop did not converge " + "for the given loop settings!"); } TEST_F(InelasticDefgradFactorsTest, TestLocalNewtonIncrementRatioConvergence) @@ -2215,7 +2184,9 @@ namespace Core::LinAlg::Matrix<3, 3> iFin_result(Core::LinAlg::Initialization::zero); FOUR_C_EXPECT_THROW_WITH_MESSAGE( material->evaluate_inverse_inelastic_def_grad(&FM_, iFin_other, iFin_result), - Core::Exception, "Local Newton Loop did not converge"); + Core::Exception, + "Error in InelasticDefgradTransvIsotropElastViscoplast: Local Newton Loop did not converge " + "for the given loop settings!"); } TEST_F(InelasticDefgradFactorsTest, TestLocalNewtonResidualAndIncrementRatioConvergence) @@ -2322,15 +2293,16 @@ namespace // the one-step formulation fails to converge FOUR_C_EXPECT_THROW_WITH_MESSAGE( material_one_step->evaluate_inverse_inelastic_def_grad(&FM, iFin_other, iFin_result), - Core::Exception, "Local Newton evaluation has failed with err status overflow_error"); + Core::Exception, + "Local Newton evaluation has failed and there is no evaluation management strategy"); // the local substepping formulation converges material_substepping->evaluate_inverse_inelastic_def_grad(&FM, iFin_other, iFin_result); Core::LinAlg::Matrix<3, 3> iFin_result_ref{Core::LinAlg::Initialization::zero}; - iFin_result_ref(0, 0) = 0.71055164642; - iFin_result_ref(1, 1) = 1.18632088172; - iFin_result_ref(2, 2) = 1.18632088172; + iFin_result_ref(0, 0) = 0.71055158583; + iFin_result_ref(1, 1) = 1.18632093229; + iFin_result_ref(2, 2) = 1.18632093229; FOUR_C_EXPECT_NEAR(iFin_result, iFin_result_ref, 1.0e-10); } diff --git a/unittests/mat/vplast/4C_vplast_reform_johnsoncook_test.cpp b/unittests/mat/vplast/4C_vplast_reform_johnsoncook_test.cpp index bd59145407f..1c43791bc1c 100644 --- a/unittests/mat/vplast/4C_vplast_reform_johnsoncook_test.cpp +++ b/unittests/mat/vplast/4C_vplast_reform_johnsoncook_test.cpp @@ -23,6 +23,58 @@ namespace { using namespace FourC; + struct ReformulatedJohnsonCookLaw + { + //! parameters + std::shared_ptr params; + + //! material + std::shared_ptr material; + }; + + int make_unique_viscoplastic_law_id() + { + static int viscoplastic_law_id = 1; + return viscoplastic_law_id; + } + + + ReformulatedJohnsonCookLaw set_up_reformulated_johnson_cook_law( + const Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorRegistrationSettings + error_registration_settings) + { + const int viscoplastic_law_id = make_unique_viscoplastic_law_id(); + + Core::IO::InputParameterContainer vplast_law_reformulated_JC_data; + vplast_law_reformulated_JC_data.add("STRAIN_RATE_PREFAC", 1.0); + vplast_law_reformulated_JC_data.add("STRAIN_RATE_EXP_FAC", 0.014); + vplast_law_reformulated_JC_data.add("INIT_YIELD_STRENGTH", 792.0); + vplast_law_reformulated_JC_data.add("ISOTROP_HARDEN_PREFAC", 510.0); + vplast_law_reformulated_JC_data.add("ISOTROP_HARDEN_EXP", 0.26); + vplast_law_reformulated_JC_data.add("REF_TEMPERATURE", 293.0); + vplast_law_reformulated_JC_data.add("MELT_TEMPERATURE", 1793.0); + vplast_law_reformulated_JC_data.add("TEMPERATURE_SENS", 1.03); + auto params = std::dynamic_pointer_cast( + std::shared_ptr(Mat::make_parameter(viscoplastic_law_id, + Core::Materials::MaterialType::mvl_reformulated_Johnson_Cook, + vplast_law_reformulated_JC_data))); + + auto material = std::make_shared( + params.get(), error_registration_settings); + + // call setup method for ReformulatedJohnsonCook + int numgp = 1; + material->setup(numgp, {}, {}); + // pre_evaluate + Teuchos::ParameterList param_list{}; + param_list.set("temperature", 313.0); + material->pre_evaluate(param_list, 0); + + return {.params = params, .material = material}; + } + + + class ReformJohnsonCookTest : public ::testing::Test { protected: @@ -33,34 +85,14 @@ namespace equiv_plastic_strain_ = 0.001; // manually create viscoplastic law (ReformulatedJohnsonCook) - Core::IO::InputParameterContainer vplast_law_reformulated_JC_data; - vplast_law_reformulated_JC_data.add("STRAIN_RATE_PREFAC", 1.0); - vplast_law_reformulated_JC_data.add("STRAIN_RATE_EXP_FAC", 0.014); - vplast_law_reformulated_JC_data.add("INIT_YIELD_STRENGTH", 792.0); - vplast_law_reformulated_JC_data.add("ISOTROP_HARDEN_PREFAC", 510.0); - vplast_law_reformulated_JC_data.add("ISOTROP_HARDEN_EXP", 0.26); - vplast_law_reformulated_JC_data.add("REF_TEMPERATURE", 293.0); - vplast_law_reformulated_JC_data.add("MELT_TEMPERATURE", 1793.0); - vplast_law_reformulated_JC_data.add("TEMPERATURE_SENS", 1.03); - params_vplast_law_reformulated_JC_ = - std::dynamic_pointer_cast( - std::shared_ptr(Mat::make_parameter(1, - Core::Materials::MaterialType::mvl_reformulated_Johnson_Cook, - vplast_law_reformulated_JC_data))); - vplast_law_reformulated_JC_ = std::make_shared( - params_vplast_law_reformulated_JC_.get()); - - // call setup method for ReformulatedJohnsonCook - int numgp = 8; // HEX8 element, although not really relevant for the tested methods - vplast_law_reformulated_JC_->setup(numgp, {}, {}); - - // parameter list - Teuchos::ParameterList param_list{}; - param_list.set("temperature", 313.0); - - - // call pre_evaluate - vplast_law_reformulated_JC_->pre_evaluate(param_list, 0); + const double max_plastic_strain_incr_and_deriv_incr = std::exp(30.0); + const auto reformulated_johnson_cook_law = + set_up_reformulated_johnson_cook_law({.register_plastic_strain_incr_overflow = true, + .max_plastic_strain_incr = max_plastic_strain_incr_and_deriv_incr, + .register_plastic_strain_deriv_incr_overflow = true, + .max_plastic_strain_deriv_incr = max_plastic_strain_incr_and_deriv_incr}); + params_vplast_law_reformulated_JC_ = reformulated_johnson_cook_law.params; + vplast_law_reformulated_JC_ = reformulated_johnson_cook_law.material; } // equivalent stress @@ -110,15 +142,39 @@ namespace // compute solution from the viscoplasticity law double plastic_strain_rate_reformulated_JC = vplast_law_reformulated_JC_->evaluate_plastic_strain_rate( - equiv_stress_, equiv_plastic_strain_, 1.0, std::exp(30.0), err_status, false); + equiv_stress_, equiv_plastic_strain_, 1.0, err_status, false); if (err_status != Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType::no_errors) FOUR_C_THROW("Error encountered during testing of TestEvaluatePlasticStrainRate"); - - - // compare solutions EXPECT_NEAR( plastic_strain_rate_reformulated_JC_solution_, plastic_strain_rate_reformulated_JC, 1.0e-8); + + // test registering of the overflow error + const auto ref_jc_register_both_with_zero_incr = + set_up_reformulated_johnson_cook_law({.register_plastic_strain_incr_overflow = true, + .max_plastic_strain_incr = + 1.0e-16, // effectively 0-tolerance for plastic strain increments -> results in + // overflow error regardless of the computed plastic strain increment + // value + .register_plastic_strain_deriv_incr_overflow = true, + .max_plastic_strain_deriv_incr = 1.0e-16}); + plastic_strain_rate_reformulated_JC = + ref_jc_register_both_with_zero_incr.material->evaluate_plastic_strain_rate( + equiv_stress_, equiv_plastic_strain_, 1.0, err_status, false); + EXPECT_EQ(err_status, + Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType::overflow_error); + + const auto ref_jc_register_none_with_zero_incr = + set_up_reformulated_johnson_cook_law({.register_plastic_strain_incr_overflow = false, + .max_plastic_strain_incr = + 1.0e-16, // same test as above, but now without registering the error + .register_plastic_strain_deriv_incr_overflow = false, + .max_plastic_strain_deriv_incr = 1.0e-16}); + plastic_strain_rate_reformulated_JC = + ref_jc_register_none_with_zero_incr.material->evaluate_plastic_strain_rate( + equiv_stress_, equiv_plastic_strain_, 1.0, err_status, false); + EXPECT_EQ( + err_status, Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType::no_errors); } TEST_F(ReformJohnsonCookTest, TestEvaluatePlasticStrainRateDerivatives) @@ -135,10 +191,17 @@ namespace Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType::no_errors; // compute solution from the viscoplasticity law + const double max_plastic_strain_incr_and_deriv_incr = std::exp(30.0); + const auto ref_jc_register_both_with_set_incr = + set_up_reformulated_johnson_cook_law({.register_plastic_strain_incr_overflow = true, + .max_plastic_strain_incr = max_plastic_strain_incr_and_deriv_incr, + .register_plastic_strain_deriv_incr_overflow = true, + .max_plastic_strain_deriv_incr = max_plastic_strain_incr_and_deriv_incr}); Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::PlasticStrainRateDerivs deriv_plastic_strain_rate_reformulated_JC = - vplast_law_reformulated_JC_->evaluate_derivatives_of_plastic_strain_rate( - equiv_stress_, equiv_plastic_strain_, 1.0, std::exp(30.0), err_status, false); + ref_jc_register_both_with_set_incr.material + ->evaluate_derivatives_of_plastic_strain_rate( + equiv_stress_, equiv_plastic_strain_, 1.0, err_status, false); if (err_status != Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType::no_errors) FOUR_C_THROW("Error encountered during testing of TestEvaluatePlasticStrainRateDerivatives"); @@ -150,6 +213,36 @@ namespace deriv_plastic_strain_rate_reformulated_JC.deriv_plastic_strain, 1.0e-6); EXPECT_NEAR(deriv_plastic_strain_rate_reformulated_JC_solution_.deriv_temperature, deriv_plastic_strain_rate_reformulated_JC.deriv_temperature, 1.0e-6); + + + + const auto ref_jc_register_both_with_zero_incr = + set_up_reformulated_johnson_cook_law({.register_plastic_strain_incr_overflow = true, + .max_plastic_strain_incr = + 1.0e-16, // effectively 0-tolerance for plastic strain increments -> results + // in overflow error regardless of the computed plastic strain + // increment value + .register_plastic_strain_deriv_incr_overflow = true, + .max_plastic_strain_deriv_incr = 1.0e-16}); + deriv_plastic_strain_rate_reformulated_JC = + ref_jc_register_both_with_zero_incr.material->evaluate_derivatives_of_plastic_strain_rate( + equiv_stress_, equiv_plastic_strain_, 1.0, err_status, false); + + EXPECT_EQ(err_status, Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType:: + failed_computation_flow_resistance_derivs); + + + const auto ref_jc_register_none_with_zero_incr = + set_up_reformulated_johnson_cook_law({.register_plastic_strain_incr_overflow = false, + .max_plastic_strain_incr = + 1.0e-16, // same test as above, but now without registering the error + .register_plastic_strain_deriv_incr_overflow = false, + .max_plastic_strain_deriv_incr = 1.0e-16}); + deriv_plastic_strain_rate_reformulated_JC = + ref_jc_register_none_with_zero_incr.material->evaluate_derivatives_of_plastic_strain_rate( + equiv_stress_, equiv_plastic_strain_, 1.0, err_status, false); + EXPECT_EQ( + err_status, Mat::InelasticDefgradTransvIsotropElastViscoplastUtils::ErrorType::no_errors); } } // namespace From ba080b0f50bb03176eac246841f107723def8c82 Mon Sep 17 00:00:00 2001 From: Rasmus Joussen Date: Fri, 5 Jun 2026 17:08:34 +0200 Subject: [PATCH 19/28] Add thermal effects to the multsplit material - Heat source due to plastic dissipation is wired from the viscoplastic factor to the thermo element implementation. - Stress contribution from thermal expansion is added - Two new regression tests are added, for partitioned and monolithic TSI Limitations: - Supported only for a single viscoplastic factor. - The thermo-elastic contribution in the via `stress_temperature_modulus_and_deriv` is neglected so far. --- src/mat/4C_mat_inelastic_defgrad_factors.cpp | 48 +-- ..._mat_inelastic_defgrad_factors_service.hpp | 4 + ...ultiplicative_split_defgrad_elasthyper.cpp | 137 +++++++- ...ultiplicative_split_defgrad_elasthyper.hpp | 151 +++++++- ...ative_split_defgrad_elasthyper_service.hpp | 283 +++++---------- src/mat/4C_mat_trait_thermo_solid.hpp | 2 +- src/thermo/src/element/4C_thermo_ele_impl.cpp | 199 ++++++++--- src/tsi/4C_tsi_monolithic.cpp | 1 + ...st_refJC_log_timint_tsi_monolithic.4C.yaml | 326 +++++++++++++++++ ...t_refJC_log_timint_tsi_partitioned.4C.yaml | 329 ++++++++++++++++++ tests/list_of_tests.cmake | 4 + ..._split_defgrad_elasthyper_service_test.cpp | 110 ++---- ...licative_split_defgrad_elasthyper_test.cpp | 12 +- 13 files changed, 1223 insertions(+), 383 deletions(-) create mode 100644 tests/input_files/mat_iso_thermoviscoplast_refJC_log_timint_tsi_monolithic.4C.yaml create mode 100644 tests/input_files/mat_iso_thermoviscoplast_refJC_log_timint_tsi_partitioned.4C.yaml diff --git a/src/mat/4C_mat_inelastic_defgrad_factors.cpp b/src/mat/4C_mat_inelastic_defgrad_factors.cpp index b7904dd8445..d59ee058fd1 100644 --- a/src/mat/4C_mat_inelastic_defgrad_factors.cpp +++ b/src/mat/4C_mat_inelastic_defgrad_factors.cpp @@ -1974,25 +1974,8 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantities( Core::LinAlg::Matrix<3, 3> CeCeM(Core::LinAlg::Initialization::zero); CeCeM.multiply_nn(1.0, state_quantities.curr_CeM, state_quantities.curr_CeM, 0.0); - // thermal quantities and stress factors - Mat::ThermalQuantities thermal_quantities = - Mat::evaluate_thermal_quantities(temperature - ref_temperature_, - thermal_expansion_coefficient_, iFinM, gp_, ele_gid_, potsumel_); - Mat::StressFactors thermal_stress_factors; - Mat::calculate_gamma_delta(thermal_stress_factors.gamma, thermal_stress_factors.delta, - thermal_quantities.prinv, thermal_quantities.dPI, thermal_quantities.ddPII); - - // compute mixed thermo-elastic tensors required for reducing the Mandel stress based on - // temperature - Core::LinAlg::Matrix<3, 3> CT{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Stresses::vector_to_matrix(thermal_quantities.CTV, CT); - Core::LinAlg::Matrix<3, 3> iCT{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Stresses::vector_to_matrix(thermal_quantities.iCTV, iCT); - Core::LinAlg::Matrix<3, 3> CeCT{Core::LinAlg::Initialization::zero}; - CeCT.multiply_nn(1.0, state_quantities.curr_CeM, CT, 0.0); - Core::LinAlg::Matrix<3, 3> CeiCT{Core::LinAlg::Initialization::zero}; - CeiCT.multiply_nn(1.0, state_quantities.curr_CeM, iCT, 0.0); - + state_quantities.curr_ST = Mat::ThermalExpansion::compute_thermoelastic_stress_contribution( + temperature - ref_temperature_, thermal_expansion_coefficient_, potsumel_, gp_, ele_gid_); /** compute symmetric part of thermo-elastic Mandel stress tensor @@ -2003,9 +1986,9 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantities( Mtheta_sym_M.update(state_quantities.curr_gamma(0), state_quantities.curr_CeM, state_quantities.curr_gamma(1), CeCeM, 0.0); Mtheta_sym_M.update(state_quantities.curr_gamma(2), const_non_mat_tensors.id3x3, 1.0); - Mtheta_sym_M.update(-1.0 * thermal_stress_factors.gamma(0), state_quantities.curr_CeM, 1.0); - Mtheta_sym_M.update(-1.0 * thermal_stress_factors.gamma(1), CeCT, 1.0); - Mtheta_sym_M.update(-1.0 * thermal_stress_factors.gamma(2), CeiCT, 1.0); + const auto& CeS_T = + dot(make_tensor_view(state_quantities.curr_CeM), state_quantities.curr_ST.value); + Mtheta_sym_M.update(-1.0, make_matrix_view(CeS_T), 1.0); if (parameter()->mat_behavior() == ViscoplastUtils::MatBehavior::transv_isotropic) { Core::LinAlg::Matrix<3, 3> addMeM(Core::LinAlg::Initialization::zero); @@ -2233,6 +2216,7 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantity_deriv const Core::LinAlg::Matrix<3, 3> dpM = relevant_state_quantities.curr_dpM; const Core::LinAlg::Matrix<3, 3> lpM = relevant_state_quantities.curr_lpM; const Core::LinAlg::Matrix<3, 3> EpM = relevant_state_quantities.curr_EpM; + const TensorAndTemperatureDerivative ST = relevant_state_quantities.curr_ST; // compute the relevant derivatives of the elastic right Cauchy-Green deformation tensor @@ -2309,19 +2293,7 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantity_deriv Core::LinAlg::Matrix<6, 1> iCV(Core::LinAlg::Initialization::zero); Core::LinAlg::Voigt::Stresses::matrix_to_vector(iCM, iCV); - // thermal quantities and stress factors - Mat::ThermalQuantities thermal_quantities = - Mat::evaluate_thermal_quantities(temperature - ref_temperature_, - thermal_expansion_coefficient_, iFinM, gp_, ele_gid_, potsumel_); - Core::LinAlg::SymmetricTensor hyperelast_stress_CT{}; - Core::LinAlg::SymmetricTensor hyperelast_stiffness_CT{}; - Mat::elast_hyper_add_isotropic_stress_cmat(hyperelast_stress_CT, hyperelast_stiffness_CT, - Core::LinAlg::make_symmetric_tensor_from_stress_like_voigt_matrix(thermal_quantities.CTV), - Core::LinAlg::make_symmetric_tensor_from_stress_like_voigt_matrix(thermal_quantities.iCTV), - thermal_quantities.prinv, thermal_quantities.dPI, thermal_quantities.ddPII); - const Core::LinAlg::Matrix<3, 3> S_T = - Core::LinAlg::make_matrix(Core::LinAlg::get_full(hyperelast_stress_CT)); - + const auto S_T = make_matrix(get_full(ST.value)); // compute the relevant derivatives of the symmetric part of the Mandel stress /** @@ -2391,11 +2363,7 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantity_deriv \f$ \frac{\partial \boldsymbol{M}_{\theta, \text{sym}} }{\partial T} = - \boldsymbol{C}_e \cdot \frac{\partial\boldsymbol{S}_{T}}{\partial T}\f$ (Voigt stress-form) */ - Core::LinAlg::Matrix<6, 1> dST_dT_V{Core::LinAlg::Initialization::zero}; - dST_dT_V.multiply_nn(0.5, Core::LinAlg::make_stress_like_voigt_view(hyperelast_stiffness_CT), - thermal_quantities.dCTdTV, 0.0); - Core::LinAlg::Matrix<3, 3> dST_dT_M{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Stresses::vector_to_matrix(dST_dT_V, dST_dT_M); + const auto dST_dT_M = make_matrix(get_full(ST.temperature_derivative)); Core::LinAlg::Matrix<3, 3> dMtheta_sym_dT_M(Core::LinAlg::Initialization::zero); dMtheta_sym_dT_M.multiply_nn(-1.0, CeM, dST_dT_M, 0.0); Core::LinAlg::Matrix<6, 1> dMtheta_sym_dT_V(Core::LinAlg::Initialization::zero); diff --git a/src/mat/4C_mat_inelastic_defgrad_factors_service.hpp b/src/mat/4C_mat_inelastic_defgrad_factors_service.hpp index 5d510484d18..95f6e37baf9 100644 --- a/src/mat/4C_mat_inelastic_defgrad_factors_service.hpp +++ b/src/mat/4C_mat_inelastic_defgrad_factors_service.hpp @@ -12,6 +12,7 @@ #include "4C_comm_utils.hpp" #include "4C_linalg_fixedsizematrix.hpp" +#include "4C_mat_multiplicative_split_defgrad_elasthyper_service.hpp" #include "4C_utils_exceptions.hpp" #include @@ -467,6 +468,9 @@ namespace Mat //! isotropic constitutive tensor factors Core::LinAlg::Matrix<8, 1> curr_delta{Core::LinAlg::Initialization::zero}; + //! thermal contribution due to thermal expansion to the thermo-elastic 2PK stress + TensorAndTemperatureDerivative curr_ST{}; + //! elastic 2nd PK stress tensors (specifically only transversely-isotropic components) Core::LinAlg::Matrix<3, 3> curr_SeM{Core::LinAlg::Initialization::zero}; diff --git a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp index 357ff679f64..880fc4c173e 100644 --- a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp +++ b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp @@ -15,6 +15,7 @@ #include "4C_linalg_fixedsizematrix_tensor_products.hpp" #include "4C_linalg_fixedsizematrix_voigt_notation.hpp" #include "4C_linalg_symmetric_tensor.hpp" +#include "4C_linalg_tensor.hpp" #include "4C_linalg_tensor_conversion.hpp" #include "4C_linalg_tensor_generators.hpp" #include "4C_mat_anisotropy.hpp" @@ -28,6 +29,7 @@ #include "4C_ssi_input.hpp" #include "4C_structure_new_enum_lists.hpp" #include "4C_utils_enum.hpp" +#include "4C_utils_exceptions.hpp" #include @@ -45,7 +47,10 @@ Mat::PAR::MultiplicativeSplitDefgradElastHyper::MultiplicativeSplitDefgradElastH matids_elast_(matdata.parameters.get>("MATIDSEL")), numfac_inel_(matdata.parameters.get("NUMFACINEL")), inel_defgradfacids_(matdata.parameters.get>("INELDEFGRADFACIDS")), - density_(matdata.parameters.get("DENS")) + density_(matdata.parameters.get("DENS")), + ref_temperature_(matdata.parameters.get("REF_TEMPERATURE")), + thermal_expansion_coefficient_( + matdata.parameters.get("THERMAL_EXPANSION_COEFFICIENT")) { // check if sizes fit if (nummat_elast_ != static_cast(matids_elast_.size())) @@ -241,9 +246,20 @@ void Mat::MultiplicativeSplitDefgradElastHyper::evaluate( Mat::calculate_gamma_delta(stress_factors.gamma, stress_factors.delta, kinematic_quantities.prinv, kinematic_quantities.dPIe, kinematic_quantities.ddPIIe); + // compute thermal quantities from the absolute temperature stored in the parameter list + double delta_temperature = 0.0; + if (params.isParameter("temperature")) + { + delta_temperature = params.get("temperature") - params_->ref_temperature_; + } + auto thermoelastic_stress_contribution = + Mat::ThermalExpansion::compute_thermoelastic_stress_contribution( + delta_temperature, params_->thermal_expansion_coefficient_, potsumel_, gp, eleGID); + // derivative of 2nd Piola Kirchhoff stresses w.r.t. the inverse inelastic deformation // gradient - Core::LinAlg::Matrix<6, 9> dSdiFin = evaluated_sdi_fin(kinematic_quantities, stress_factors); + Core::LinAlg::Matrix<6, 9> dSdiFin = evaluate_d_stress_d_ifin( + kinematic_quantities, stress_factors, thermoelastic_stress_contribution.value); // right Cauchy-Green deformation tensor Core::LinAlg::Matrix<3, 3> CM(Core::LinAlg::Initialization::zero); @@ -255,9 +271,18 @@ void Mat::MultiplicativeSplitDefgradElastHyper::evaluate( // cmat = 2 dS/dC = 2 \frac{\partial S}{\partial C} + 2 \frac{\partial S}{\partial F_{in}^{-1}} // : \frac{\partial F_{in}^{-1}}{\partial C} = cmatiso + cmatadd evaluate_stress_cmat_iso(kinematic_quantities, stress_factors, stress_view, cmatiso); + + // subtract stress contribution due to thermal expansion + stress -= Mat::ThermalExpansion::compute_pk2_stress_contribution( + thermoelastic_stress_contribution, kinematic_quantities.iFinM) + .value; + // separate update coming from the transversely isotropic components if (!(potsumel_transviso_.empty())) { + FOUR_C_ASSERT_ALWAYS(delta_temperature == 0.0, + "Thermoelastic coupling with transversely isotropic elastic summands is not supported yet. " + "Use isotropic elastic summands only."); evaluate_transv_iso_quantities( kinematic_quantities, CM, params, gp, eleGID, stress_view, cmatiso, dSdiFin); } @@ -300,13 +325,36 @@ Mat::MultiplicativeSplitDefgradElastHyper::evaluate_d_stress_d_scalar( Mat::calculate_gamma_delta(stress_factors.gamma, stress_factors.delta, kinematic_quantities.prinv, kinematic_quantities.dPIe, kinematic_quantities.ddPIIe); - Core::LinAlg::SymmetricTensor d_stress_d_scalar{}; - Core::LinAlg::Matrix<6, 1> d_stress_d_scalar_view = - Core::LinAlg::make_stress_like_voigt_view(d_stress_d_scalar); + double delta_temperature = 0.0; + + // compute thermal quantities from the absolute temperature stored in the parameter list + if (params.isParameter("temperature")) + { + delta_temperature = params.get("temperature") - params_->ref_temperature_; + } + + const auto thermoelastic_stress_contribution = + Mat::ThermalExpansion::compute_thermoelastic_stress_contribution( + delta_temperature, params_->thermal_expansion_coefficient_, potsumel_, gp, eleGID); + + Core::LinAlg::Matrix<6, 9> dSdiFin = evaluate_d_stress_d_ifin( + kinematic_quantities, stress_factors, thermoelastic_stress_contribution.value); + + Core::LinAlg::SymmetricTensor d_stress_d_scalar = + make_symmetric_tensor_from_stress_like_voigt_matrix( + evaluate_od_stiff_mat(source, &defgrad_mat, dSdiFin)); + + + if (source == PAR::InelasticSource::temperature) + { + // stress depends on temperature not only through the inelastic deformation gradient but also + // through thermal expansion + d_stress_d_scalar -= Mat::ThermalExpansion::compute_pk2_stress_contribution( + thermoelastic_stress_contribution, kinematic_quantities.iFinM) + .temperature_derivative; + } - Core::LinAlg::Matrix<6, 9> dSdiFin = evaluated_sdi_fin(kinematic_quantities, stress_factors); - evaluate_od_stiff_mat(source, &defgrad_mat, dSdiFin, d_stress_d_scalar_view); return d_stress_d_scalar; } @@ -668,9 +716,10 @@ void Mat::MultiplicativeSplitDefgradElastHyper::evaluate_invariant_derivatives( /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ -Core::LinAlg::Matrix<6, 9> Mat::MultiplicativeSplitDefgradElastHyper::evaluated_sdi_fin( +Core::LinAlg::Matrix<6, 9> Mat::MultiplicativeSplitDefgradElastHyper::evaluate_d_stress_d_ifin( const Mat::MultiplicativeSplitDefgradElastHyper::KinematicQuantities& kinemat_quant, - const Mat::StressFactors& stress_fact) const + const Mat::StressFactors& stress_fact, + const Core::LinAlg::SymmetricTensor& SthetaT) const { // declare output variables Core::LinAlg::Matrix<6, 9> dSdiFin{Core::LinAlg::Initialization::zero}; @@ -735,6 +784,22 @@ Core::LinAlg::Matrix<6, 9> Mat::MultiplicativeSplitDefgradElastHyper::evaluated_ // chain rule to get dS/d(det(Fin)) * d(det(Fin))/diFin dSdiFin.multiply_nt(1.0, dSddetFin, ddetFindiFinV, 1.0); + { + const Core::LinAlg::Tensor iFinSthetaT = dot(make_tensor_view(iFinM), SthetaT); + + /// \f$\texttt{dSdiFin}\; \mathrel{-}= \frac{\partial}{\partial + /// \mathbf{F}_{\text{in}}^{-1}}\left(\det(\mathbf{F}_{\text{in}}) \mathbf{F}_{\text{in}}^{-1} + /// \cdot \mathbf{S}_{\theta,T} \cdot \mathbf{F}_{\text{in}}^{-T}\right)\f$ + Core::LinAlg::FourTensorOperations::add_right_non_symmetric_holzapfel_product( + dSdiFin, id, make_matrix_view(iFinSthetaT), -detFin); + + Core::LinAlg::Matrix<3, 3> iFinSthetaTiFinT(Core::LinAlg::Initialization::zero); + iFinSthetaTiFinT.multiply_nt(1.0, make_matrix_view(iFinSthetaT), iFinM, 0.0); + Core::LinAlg::Matrix<6, 1> iFinSthetaTiFinTV(Core::LinAlg::Initialization::zero); + Core::LinAlg::Voigt::Stresses::matrix_to_vector(iFinSthetaTiFinT, iFinSthetaTiFinTV); + dSdiFin.multiply_nt(-1.0, iFinSthetaTiFinTV, ddetFindiFinV, 1.0); + } + return dSdiFin; } @@ -979,12 +1044,11 @@ void Mat::MultiplicativeSplitDefgradElastHyper::update() /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ -void Mat::MultiplicativeSplitDefgradElastHyper::evaluate_od_stiff_mat(PAR::InelasticSource source, - const Core::LinAlg::Matrix<3, 3>* const defgrad, const Core::LinAlg::Matrix<6, 9>& dSdiFin, - Core::LinAlg::Matrix<6, 1>& dstressdx) +Core::LinAlg::Matrix<6, 1> Mat::MultiplicativeSplitDefgradElastHyper::evaluate_od_stiff_mat( + const PAR::InelasticSource source, const Core::LinAlg::Matrix<3, 3>* const defgrad, + const Core::LinAlg::Matrix<6, 9>& dSdiFin) { - // clear variable - dstressdx.clear(); + Core::LinAlg::Matrix<6, 1> dstressdx{Core::LinAlg::Initialization::zero}; // References to vector of inelastic contributions and inelastic deformation gradients const auto& facdefgradin = inelastic_->fac_def_grad_in(); @@ -1064,8 +1128,53 @@ void Mat::MultiplicativeSplitDefgradElastHyper::evaluate_od_stiff_mat(PAR::Inela } else FOUR_C_THROW("You should not be here"); + + return dstressdx; +} + +void Mat::MultiplicativeSplitDefgradElastHyper::stress_temperature_modulus_and_deriv( + Core::LinAlg::SymmetricTensor& stm, + Core::LinAlg::SymmetricTensor& stm_dT, const int gp) +{ + // this contribution is intentionally neglected so far. + stm.fill(0.0); + stm_dT.fill(0.0); } +Mat::HeatSource Mat::MultiplicativeSplitDefgradElastHyper::evaluate_additional_heat_source( + const EvaluationContext<3>& context, const int gp, const int eleGID, + const Core::LinAlg::Matrix<3, 3>* current_defgrad, const double current_temperature) +{ + HeatSource heat_source; + + // References to vector of inelastic contributions and inelastic deformation gradients + const auto& facdefgradin = inelastic_->fac_def_grad_in(); + + // number of contributions + const int num_contributions = inelastic_->num_inelastic_def_grad(); + + // check number of factors the inelastic deformation gradient consists of and choose + // implementation accordingly + if (num_contributions == 1) + { + if (const auto viscoplastic_factor = + std::dynamic_pointer_cast( + facdefgradin[0].second)) + { + heat_source = viscoplastic_factor->evaluate_taylor_quinney_heat_source(context, gp, eleGID, + current_defgrad, Core::LinAlg::identity_matrix<3>(), current_temperature); + } + } + else if (num_contributions > 1) + { + FOUR_C_THROW( + "Evaluation of additional heat source is only implemented for a single factor so far."); + } + else + FOUR_C_THROW("You should not be here"); + + return heat_source; +} /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ void Mat::MultiplicativeSplitDefgradElastHyper::pre_evaluate(const Teuchos::ParameterList& params, diff --git a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp index 0eda8de8c97..19f9a5821dc 100644 --- a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp +++ b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp @@ -11,12 +11,18 @@ #include "4C_config.hpp" #include "4C_comm_parobjectfactory.hpp" +#include "4C_linalg_fixedsizematrix.hpp" +#include "4C_linalg_symmetric_tensor.hpp" +#include "4C_linalg_tensor.hpp" #include "4C_mat_anisotropy.hpp" #include "4C_mat_elast_couptransverselyisotropic.hpp" -#include "4C_mat_monolithic_solid_scalar_material.hpp" #include "4C_mat_multiplicative_split_defgrad_elasthyper_service.hpp" #include "4C_mat_so3_material.hpp" +#include "4C_mat_thermomechanical.hpp" #include "4C_material_parameter_base.hpp" +#include "4C_utils_exceptions.hpp" + +#include FOUR_C_NAMESPACE_OPEN @@ -65,6 +71,12 @@ namespace Mat /// material mass density const double density_; + /// reference temperature for thermal expansion + const double ref_temperature_; + + /// thermal expansion coefficient + const double thermal_expansion_coefficient_; + }; // class MultiplicativeSplitDefgrad_ElastHyper } // namespace PAR @@ -176,8 +188,7 @@ namespace Mat that are needed to set up the system to be solved are evaluated in the derived classes of the interface class 'InelasticDefgradFactors'. */ - class MultiplicativeSplitDefgradElastHyper : public So3Material, - public MonolithicSolidScalarMaterial + class MultiplicativeSplitDefgradElastHyper : public So3Material, public Trait::ThermoSolid { public: /// construct empty material object @@ -276,6 +287,112 @@ namespace Mat const Teuchos::ParameterList& params, const EvaluationContext<3>& context, int gp, int eleGID) override; + void reinit(const Core::LinAlg::Tensor* defgrd, + const Core::LinAlg::SymmetricTensor& glstrain, double temperature, + unsigned gp) override { /* do nothing */ }; + + void stress_temperature_modulus_and_deriv(Core::LinAlg::SymmetricTensor& stm, + Core::LinAlg::SymmetricTensor& stm_dT, const int gp) override; + + /*! + * @brief Evaluate the heat source produced by this material. Currently, this is only + * enabled for the viscoplastic factor. + * + * @param[in] context Evaluation context, providing access to the current timestep and total + * time + * @param[in] gp Gauss point + * @param[in] eleGID global element ID + * @param[in] defgrad Deformation gradient + * @param[in] current_temperature Absolute current temperature + * @return mechanical dissipation heat source and derivatives w.r.t. temperature and the right + * Cauchy-Green tensor + */ + [[nodiscard]] HeatSource evaluate_additional_heat_source(const EvaluationContext<3>& context, + const int gp, const int eleGID, const Core::LinAlg::Matrix<3, 3>* current_defgrad, + const double current_temperature); + + + // ******************************************************************************* + // All of the following functions in this block are only required since the ThermoSolid + // Trait inherits from the ThermoTrait. + // https://github.com/4C-multiphysics/4C/pull/2075 aims to remove this dependency. After this, + // these functions can be removed. This material hence does not wrap an internal thermo + // material, all corresponding functions throw an error if called. + + void evaluate( + const Core::LinAlg::Matrix<3, 1>& gradtemp, ///< temperature gradient (strain tensor) + Core::LinAlg::Matrix<3, 3>& cmat, ///< constitutive matrix + Core::LinAlg::Matrix<3, 1>& heatflux, ///< heatflux + const int eleGID) const override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + void evaluate( + const Core::LinAlg::Matrix<2, 1>& gradtemp, ///< temperature gradient (strain tensor) + Core::LinAlg::Matrix<2, 2>& cmat, ///< constitutive matrix + Core::LinAlg::Matrix<2, 1>& heatflux, ///< heatflux + const int eleGID) const override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + void evaluate( + const Core::LinAlg::Matrix<1, 1>& gradtemp, ///< temperature gradient (strain tensor) + Core::LinAlg::Matrix<1, 1>& cmat, ///< constitutive matrix + Core::LinAlg::Matrix<1, 1>& heatflux, ///< heatflux + const int eleGID) const override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + std::vector conductivity(int eleGID = 0) const override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + void conductivity_deriv_t(Core::LinAlg::Matrix<3, 3>& dCondDT) const override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + void conductivity_deriv_t(Core::LinAlg::Matrix<2, 2>& dCondDT) const override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + void conductivity_deriv_t(Core::LinAlg::Matrix<1, 1>& dCondDT) const override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + double capacity() const override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + double capacity_deriv_t() const override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + void reinit(double temperature, unsigned gp) override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + void reset_current_state() override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + void commit_current_state() override + { + FOUR_C_THROW("This material does not wrap an internal thermo material"); + }; + + // ******************************************************************************* + double evaluate_cauchy_n_dir_and_derivatives(const Core::LinAlg::Tensor& defgrd, const Core::LinAlg::Tensor& n, const Core::LinAlg::Tensor& dir, Core::LinAlg::Matrix<3, 1>* d_cauchyndir_dn, Core::LinAlg::Matrix<3, 1>* d_cauchyndir_ddir, @@ -300,18 +417,23 @@ namespace Mat const std::string& name, Core::LinAlg::SerialDenseMatrix& data) const override; /*! - * @brief Evaluate off-diagonal stiffness matrix (required for monolithic algorithms) + * @brief Evaluate off-diagonal stiffness matrix contributions due to the inelastic deformation, + * i.e.: + * \f[ + * \frac{\partial \mathbf{S}}{\partial \mathbf{F}_\text{in}^{-1}} + * :\frac{\mathrm{d}\mathbf{F}_\text{in}^{-1}}{\mathrm{d}x} + * \f] + * where \f[x\f] is the scalar of the secondary field corresponding to \param source * * @param[in] source Source of inelastic deformation * @param[in] defgrad Deformation gradient - * @param[in] dSdiFin Derivative of 2nd Piola Kirchhoff stresses w.r.t. the inverse inelastic - * deformation gradient - * @param[out] dstressdx Derivative of 2nd Piola Kirchhoff stresses w.r.t. primary variable of - * different field + * @param[in] dSdiFin Already computed derivative of 2nd Piola Kirchhoff stresses w.r.t. the + * inverse inelastic deformation gradient \f[ \frac{\partial \mathbf{S}}{\partial + * \mathbf{F}_\text{in}^{-1}} \f] + * @return off-diagonal stiffness matrix contribution in stress-like Voigt notation */ - void evaluate_od_stiff_mat(PAR::InelasticSource source, - const Core::LinAlg::Matrix<3, 3>* defgrad, const Core::LinAlg::Matrix<6, 9>& dSdiFin, - Core::LinAlg::Matrix<6, 1>& dstressdx); + Core::LinAlg::Matrix<6, 1> evaluate_od_stiff_mat(PAR::InelasticSource source, + const Core::LinAlg::Matrix<3, 3>* defgrad, const Core::LinAlg::Matrix<6, 9>& dSdiFin); /*! * @brief Evaluate additional terms of the elasticity tensor @@ -337,11 +459,13 @@ namespace Mat * @param[in] kinemat_quant struct containing kinematic quantities * @param[in] stress_fact struct containing \f$ \gamma_i \f$ and \f$ \delta_i \f$ stress * factors, as presented in Holzapfel - Nonlinear Solid Mechanics + * @param[in] SthetaT thermal part of the thermo-elastic stress (due to thermal expansion) * @return derivative \f$ \frac{\partial \mathsymbol{S}}{\partial * \mathsymbol{F}^{-1}_{\text{in}}} \f$ */ - Core::LinAlg::Matrix<6, 9> evaluated_sdi_fin( - const KinematicQuantities& kinemat_quant, const Mat::StressFactors& stress_factors) const; + [[nodiscard]] Core::LinAlg::Matrix<6, 9> evaluate_d_stress_d_ifin( + const KinematicQuantities& kinemat_quant, const Mat::StressFactors& stress_factors, + const Core::LinAlg::SymmetricTensor& SthetaT) const; /*! * @brief Evaluate the stress and stiffness components of the transversely isotropic components @@ -379,7 +503,6 @@ namespace Mat * \f] * \f[ * \mathbf{S} = \det(\mathbf{F}_\text{in}) \left(\gamma_1 \ \mathbf{C}_\text{in}^{-1} + \gamma_2 - * \ * \mathbf{C}_\text{in}^{-1} \cdot \mathbf{C} \cdot \mathbf{C}_\text{in}^{-1} + \gamma_3 \ * \mathbf{C}^{-1} \right) * \f] with \f$\gamma_i\f$ as defined in Mat::CalculateGammaDelta() diff --git a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper_service.hpp b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper_service.hpp index b4cf497f4d5..61b09d368e0 100644 --- a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper_service.hpp +++ b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper_service.hpp @@ -14,8 +14,10 @@ #include "4C_linalg_fixedsizematrix_tensor_products.hpp" #include "4C_linalg_fixedsizematrix_voigt_notation.hpp" #include "4C_linalg_symmetric_tensor.hpp" +#include "4C_linalg_tensor.hpp" #include "4C_linalg_tensor_conversion.hpp" #include "4C_linalg_tensor_generators.hpp" +#include "4C_linalg_utils_densematrix_determinant.hpp" #include "4C_mat_elasthyper_service.hpp" #include "4C_mat_service.hpp" @@ -63,37 +65,102 @@ namespace Mat Core::LinAlg::Matrix<8, 1> delta{Core::LinAlg::Initialization::zero}; }; - /// Thermal stretch quantities used by multiplicative-split thermoelastic stress evaluation. - struct ThermalQuantities + /// helper to store a second order tensor and its derivative w.r.t. temperature + struct TensorAndTemperatureDerivative { - // ----- variables of thermal quantities ----- // - /// thermal right Cauchy-Green deformation tensor \f$ \mathbf{C}_T \f$ stored as 6x1 - /// vector (stress-form!) - Core::LinAlg::Matrix<6, 1> CTV{Core::LinAlg::Initialization::zero}; - /// inverse thermal right Cauchy-Green deformation tensor \f$ \mathbf{C}_T^{-1} \f$ stored as - /// 6x1 vector (stress-form) - Core::LinAlg::Matrix<6, 1> iCTV{Core::LinAlg::Initialization::zero}; - /// \f$ \mathbf{F}_{\text{in}}^{-1} \mathbf{C}_T \mathbf{F}_{\text{in}}^{-T} \f$ stored as 6x1 - /// vector (stress-form!) - Core::LinAlg::Matrix<6, 1> iFinCTiFinTV{Core::LinAlg::Initialization::zero}; - /// \f$ \mathbf{F}_{\text{in}}^{-1} \mathbf{C}_T^{-1} \mathbf{F}_{\text{in}}^{-T} \f$ stored - /// as 6x1 vector (stress-form!) - Core::LinAlg::Matrix<6, 1> iFiniCTiFinTV{Core::LinAlg::Initialization::zero}; - /// derivative of thermal right Cauchy-Green deformation tensor wrt temperature \f$ \mathrm{d} - /// \mathbf{C}_T / \mathrm{d} T \f$ stored as 6x1 vector (strain-form!) - Core::LinAlg::Matrix<6, 1> dCTdTV{Core::LinAlg::Initialization::zero}; - - /// principal invariants of the thermal right Cauchy-Green tensor - Core::LinAlg::Matrix<3, 1> prinv{Core::LinAlg::Initialization::zero}; - - // ----- derivatives of principal invariants ----- // - - /// first derivatives of principal invariants - Core::LinAlg::Matrix<3, 1> dPI{Core::LinAlg::Initialization::zero}; - /// second derivatives of principal invariants - Core::LinAlg::Matrix<6, 1> ddPII{Core::LinAlg::Initialization::zero}; + /// value of the second order tensor + Core::LinAlg::SymmetricTensor value{}; + /// derivative of the second order tensor w.r.t. temperature + Core::LinAlg::SymmetricTensor temperature_derivative{}; }; + /// Thermal stretch quantities used by multiplicative-split thermoelastic stress evaluation. + namespace ThermalExpansion + { + + /*! + * @brief compute contribution to the thermo-elastic stress due to thermal expansion, + * \f$\boldsymbol{S}_T = S_\mathrm{he}(\boldsymbol{C}_T)\f$, and its partial derivative w.r.t. + * temperature: + * \f$\frac{\partial \mathbf{S}_T}{\partial T} = + * \frac{1}{2}\left.\mathbb{C}_\text{he}\right|_{\boldsymbol{C}_T} : \frac{\partial + * \boldsymbol{C}_T}{\partial T}\f$ + * + * @param[in] delta_temperature current absolute temperature minus reference temperature + * @param[in] expansion_coefficient isotropic thermal expansion coefficient + * @param[in] gp Gauss point + * @param[in] eleGID element global ID + * @param[in] potsumel isotropic elastic summands used to evaluate invariant derivatives + */ + inline TensorAndTemperatureDerivative compute_thermoelastic_stress_contribution( + const double delta_temperature, const double expansion_coefficient, + const std::vector>& potsumel, const int gp, + const int eleGID) + { + auto thermoelastic_stress_contribution = TensorAndTemperatureDerivative{}; + if (expansion_coefficient == 0.0) + { + // no thermal expansion, default initialized zero values are correct + return thermoelastic_stress_contribution; + } + + /// thermal right Cauchy-Green deformation tensor due to thermal expansion, + /// \f$\mathbf{C}_T = (1 + 2 \alpha_T \Delta T)\mathbf{I}\f$, and its derivative w.r.t. + /// temperature, \f$\frac{\partial \mathbf{C}_T}{\partial T} = 2 \alpha_T \mathbf{I}\f$ + const TensorAndTemperatureDerivative thermal_cauchy_green{ + .value = (1 + 2 * expansion_coefficient * delta_temperature) * + Core::LinAlg::TensorGenerators::identity, + .temperature_derivative = + 2 * expansion_coefficient * Core::LinAlg::TensorGenerators::identity}; + + // compute principal invariants of the thermal stretch + Core::LinAlg::Matrix<3, 1> prinv_of_thermal_cauchy_green{Core::LinAlg::Initialization::zero}; + Core::LinAlg::Voigt::Stresses::invariants_principal( + prinv_of_thermal_cauchy_green, make_stress_like_voigt_view(thermal_cauchy_green.value)); + + // compute derivatives of the thermal stretch principal invariants + Core::LinAlg::Matrix<3, 1> dPI{Core::LinAlg::Initialization::zero}; + Core::LinAlg::Matrix<6, 1> ddPII{Core::LinAlg::Initialization::zero}; + for (const auto& p : potsumel) // only for isotropic components + { + p->add_derivatives_principal(dPI, ddPII, prinv_of_thermal_cauchy_green, gp, eleGID); + } + + /// \f$\left.\mathbb{C}_\text{he}\right|_{\boldsymbol{C}_T}\f$ + Core::LinAlg::SymmetricTensor hyperelast_stiffness{}; + elast_hyper_add_isotropic_stress_cmat(thermoelastic_stress_contribution.value, + hyperelast_stiffness, thermal_cauchy_green.value, inv(thermal_cauchy_green.value), + prinv_of_thermal_cauchy_green, dPI, ddPII); + + thermoelastic_stress_contribution.temperature_derivative = + 0.5 * ddot(hyperelast_stiffness, thermal_cauchy_green.temperature_derivative); + + return thermoelastic_stress_contribution; + } + + /// contribution to the 2nd Piola-Kirchhoff stress due to thermal expansion, + /// \f$\det(\boldsymbol{F}_\text{in}) \boldsymbol{F}_\text{in}^{-1} \boldsymbol{S}_T + /// \boldsymbol{F}_\text{in}^{-T}\f$, and its partial derivative w.r.t. temperature, + /// \f$\det(\boldsymbol{F}_\text{in}) \boldsymbol{F}_\text{in}^{-1} \cdot \frac{\partial + /// \mathbf{S}_T}{\partial T} \cdot \boldsymbol{F}_\text{in}^{-T}\f$ + [[nodiscard]] inline TensorAndTemperatureDerivative compute_pk2_stress_contribution( + const TensorAndTemperatureDerivative& thermoelastic_stress_contribution, + const Core::LinAlg::Matrix<3, 3>& iFinM) + { + const auto iFin = make_tensor_view(iFinM); + const double detFin = 1.0 / det(iFin); + + return { + .value = detFin * assume_symmetry(dot(dot(iFin, thermoelastic_stress_contribution.value), + transpose(iFin))), + .temperature_derivative = + detFin * + assume_symmetry( + dot(dot(iFin, get_full(thermoelastic_stress_contribution.temperature_derivative)), + transpose(iFin)))}; + } + }; // namespace ThermalExpansion + inline void evaluate_ce(const Core::LinAlg::Matrix<3, 3>& F, const Core::LinAlg::Matrix<3, 3>& iFin, Core::LinAlg::Matrix<3, 3>& Ce) { @@ -192,165 +259,7 @@ namespace Mat Core::LinAlg::FourTensorOperations::add_holzapfel_product(cmat, iCinv, delta(7)); } - /*! - * @brief Subtracts the thermal contribution from the 2nd Piola-Kirchhoff stress - * - * \f[\texttt{stress} \mathrel{{-}{=}} \det(\boldsymbol{F}_\text{in}) - * \boldsymbol{F}_\text{in}^{-1} - * \boldsymbol{S}_\text{he}[\boldsymbol{C}_\text{he} = \boldsymbol{C}_T] - * \boldsymbol{F}_\text{in}^{-T}\f] - * where \f$\boldsymbol{S}_\text{he}[\boldsymbol{C}_\text{he} = \boldsymbol{C}_T]\f$ denotes - * the hyperelastic 2nd Piola-Kirchhoff stress evaluated - * at the thermal right Cauchy-Green tensor \f$\boldsymbol{C}_T\f$. - * - * @param[in] thermal_quant Thermal stretch quantities and invariants - * @param[in] thermal_stress_fact Holzapfel stress factors for the thermal stretch - * @param[in] iCinV inverse inelastic right Cauchy-Green tensor in stress-like Voigt notation - * @param[in] detFin determinant of the inelastic deformation gradient - * @param[in,out] stress 2nd Piola-Kirchhoff stress in stress-like Voigt notation to be updated by - * the thermal contribution - */ - inline void add_thermal_stress_contribution(Core::LinAlg::Matrix<6, 1>& stress, - const ThermalQuantities& thermal_quant, const StressFactors& thermal_stress_fact, - const Core::LinAlg::Matrix<6, 1>& iCinV, const double detFin) - { - const Core::LinAlg::Matrix<3, 1>& thermal_gamma = thermal_stress_fact.gamma; - - stress.update(-detFin * thermal_gamma(0), iCinV, 1.0); - stress.update(-detFin * thermal_gamma(1), thermal_quant.iFinCTiFinTV, 1.0); - stress.update(-detFin * thermal_gamma(2), thermal_quant.iFiniCTiFinTV, 1.0); - } - - - - /*! - * @brief Evaluate the partial derivative of the 2nd Piola-Kirchhoff stress wrt. temperature: - * - * \f[\frac{\partial \boldsymbol{S}}{\partial T} - * = -\det(\boldsymbol{F}_\text{in}) \boldsymbol{F}_{\text{in}}^{-1} - * \left(\frac{1}{2}\left.\mathbb{C}_\text{he}\right|_{\boldsymbol{C}_T} - * : \frac{\partial \boldsymbol{C}_T}{\partial T} \right) - * \boldsymbol{F}_{\text{in}}^{-T}\f] - * - * where \f$\left.\mathbb{C}_\text{he}\right|_{\boldsymbol{C}_T}\f$ denotes the hyperelastic - * stiffness evaluated at the thermal right Cauchy-Green tensor \f$\boldsymbol{C}_T\f$. - * - * @param[in] iFinM inverse inelastic deformation gradient - * @param[in] thermal_quant Thermal stretch quantities and temperature derivative - * @return derivative of the thermal 2nd Piola-Kirchhoff stress w.r.t. temperature - */ - inline Core::LinAlg::Matrix<6, 1> compute_partial_d_stress_d_temperature( - const Core::LinAlg::Matrix<3, 3>& iFinM, const ThermalQuantities& thermal_quant) - { - Core::LinAlg::Matrix<6, 1> thermal_stress_deriv{Core::LinAlg::Initialization::zero}; - - const Core::LinAlg::Matrix<6, 1>& dCTdTV = thermal_quant.dCTdTV; - const double detFin = 1.0 / iFinM.determinant(); - - // evaluate purely hyperelastic stiffness with the thermal right CG tensor as input - Core::LinAlg::SymmetricTensor hyperelast_stress{}; - Core::LinAlg::SymmetricTensor hyperelast_stiffness{}; - elast_hyper_add_isotropic_stress_cmat(hyperelast_stress, hyperelast_stiffness, - Core::LinAlg::make_symmetric_tensor_from_stress_like_voigt_matrix(thermal_quant.CTV), - Core::LinAlg::make_symmetric_tensor_from_stress_like_voigt_matrix(thermal_quant.iCTV), - thermal_quant.prinv, thermal_quant.dPI, thermal_quant.ddPII); - - - /// compute derivative \f$ \frac{\partial \mathbf{S}_{\theta}}{\partial T} \f$ - - Core::LinAlg::Matrix<6, 1> pStheta_pT_stress{Core::LinAlg::Initialization::zero}; - pStheta_pT_stress.multiply_nn( - 0.5, Core::LinAlg::make_stress_like_voigt_view(hyperelast_stiffness), dCTdTV, 0.0); - Core::LinAlg::Matrix<3, 3> pStheta_pT{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Stresses::vector_to_matrix(pStheta_pT_stress, pStheta_pT); - - /// compute product \f$ \mathbf{F}_{\text{in}}^{-1} \frac{\partial - /// \mathbf{S}_{\theta}}{\partial T} \mathbf{F}_{\text{in}}^{-T} \f$ - Core::LinAlg::Matrix<3, 3> iFin_pStheta_pT{Core::LinAlg::Initialization::zero}; - iFin_pStheta_pT.multiply_nn(1.0, iFinM, pStheta_pT, 0.0); - Core::LinAlg::Matrix<3, 3> iFin_pStheta_pT_iFinT{Core::LinAlg::Initialization::zero}; - iFin_pStheta_pT_iFinT.multiply_nt(1.0, iFin_pStheta_pT, iFinM, 0.0); - Core::LinAlg::Matrix<6, 1> iFin_pStheta_pT_iFinT_V{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Stresses::matrix_to_vector(iFin_pStheta_pT_iFinT, iFin_pStheta_pT_iFinT_V); - - // thermal derivative - thermal_stress_deriv.update(-detFin, iFin_pStheta_pT_iFinT_V, 0.0); - - return thermal_stress_deriv; - } - - /*! - * @brief Compute thermal stretch quantities for isotropic thermal expansion. - * - * @param[in] delta_temperature current absolute temperature minus reference temperature - * @param[in] thermal_expansion_coefficient isotropic thermal expansion coefficient - * @param[in] iFinM inverse inelastic deformation gradient - * @param[in] gp Gauss point - * @param[in] eleGID element global ID - * @param[in] potsumel isotropic elastic summands used to evaluate invariant derivatives - * @return collected thermal kinematic quantities and invariant derivatives - */ - inline ThermalQuantities evaluate_thermal_quantities(const double delta_temperature, - const double thermal_expansion_coefficient, const Core::LinAlg::Matrix<3, 3>& iFinM, - const int gp, const int eleGID, - const std::vector>& potsumel) - { - ThermalQuantities quantities{}; - - // compute the thermal stretch, along with its temperature - // derivative - Core::LinAlg::SymmetricTensor thermal_right_cg_tensor{ - Core::LinAlg::TensorGenerators::identity}; - Core::LinAlg::SymmetricTensor thermal_right_cg_temp_deriv_tensor{}; - thermal_right_cg_tensor += 2 * thermal_expansion_coefficient * delta_temperature * - Core::LinAlg::TensorGenerators::identity; - thermal_right_cg_temp_deriv_tensor += - 2 * thermal_expansion_coefficient * Core::LinAlg::TensorGenerators::identity; - - // compute inverse of the thermal stretch - Core::LinAlg::SymmetricTensor inv_thermal_right_cg_tensor = - inv(thermal_right_cg_tensor); - - // get matrices for the thermal stretch - const Core::LinAlg::Matrix<3, 3> CTM = - Core::LinAlg::make_matrix(get_full(thermal_right_cg_tensor)); - const Core::LinAlg::Matrix<3, 3> iCTM = - Core::LinAlg::make_matrix(Core::LinAlg::get_full(inv_thermal_right_cg_tensor)); - - // compute terms with iFin - Core::LinAlg::Matrix<3, 3> iFinCT{}; - iFinCT.multiply(1.0, iFinM, CTM, 0.0); - Core::LinAlg::Matrix<3, 3> iFinCTiFinT{}; - iFinCTiFinT.multiply_nt(1.0, iFinCT, iFinM, 0.0); - Core::LinAlg::Matrix<3, 3> iFiniCT{}; - iFiniCT.multiply(1.0, iFinM, iCTM, 0.0); - Core::LinAlg::Matrix<3, 3> iFiniCTiFinT{}; - iFiniCTiFinT.multiply_nt(1.0, iFiniCT, iFinM, 0.0); - - // add computed tensors to quantities in the specified form - quantities.CTV = Core::LinAlg::make_stress_like_voigt_view(thermal_right_cg_tensor); - quantities.iCTV = Core::LinAlg::make_stress_like_voigt_view(inv_thermal_right_cg_tensor); - Core::LinAlg::Voigt::Stresses::matrix_to_vector(iFinCTiFinT, quantities.iFinCTiFinTV); - Core::LinAlg::Voigt::Stresses::matrix_to_vector(iFiniCTiFinT, quantities.iFiniCTiFinTV); - quantities.dCTdTV = Core::LinAlg::make_strain_like_voigt_matrix( - thermal_right_cg_temp_deriv_tensor); // must be in strain-form for contraction afterwards! - - // compute principal invariants of the thermal stretch - Core::LinAlg::Voigt::Stresses::invariants_principal(quantities.prinv, quantities.CTV); - - // compute derivatives of the thermal stretch principal invariants - quantities.dPI.clear(); - quantities.ddPII.clear(); - for (const auto& p : potsumel) // only for isotropic components - { - p->add_derivatives_principal(quantities.dPI, quantities.ddPII, quantities.prinv, gp, eleGID); - } - - - return quantities; - } - } // namespace Mat FOUR_C_NAMESPACE_CLOSE -#endif \ No newline at end of file +#endif diff --git a/src/mat/4C_mat_trait_thermo_solid.hpp b/src/mat/4C_mat_trait_thermo_solid.hpp index 211d86e1e99..0cc92889422 100644 --- a/src/mat/4C_mat_trait_thermo_solid.hpp +++ b/src/mat/4C_mat_trait_thermo_solid.hpp @@ -21,7 +21,7 @@ namespace Mat { namespace Trait { - class ThermoSolid : public Thermo, public Solid, public MonolithicSolidScalarMaterial + class ThermoSolid : public Thermo, public MonolithicSolidScalarMaterial { public: /*! diff --git a/src/thermo/src/element/4C_thermo_ele_impl.cpp b/src/thermo/src/element/4C_thermo_ele_impl.cpp index 6466b4a55ac..d51d0b14df8 100644 --- a/src/thermo/src/element/4C_thermo_ele_impl.cpp +++ b/src/thermo/src/element/4C_thermo_ele_impl.cpp @@ -16,11 +16,15 @@ #include "4C_fem_nurbs_discretization.hpp" #include "4C_global_data.hpp" #include "4C_inpar_structure.hpp" +#include "4C_linalg_fixedsizematrix.hpp" #include "4C_linalg_fixedsizematrix_solver.hpp" #include "4C_linalg_symmetric_tensor.hpp" #include "4C_linalg_tensor_conversion.hpp" #include "4C_linalg_tensor_generators.hpp" +#include "4C_mat_multiplicative_split_defgrad_elasthyper.hpp" +#include "4C_mat_multiplicative_split_defgrad_elasthyper_service.hpp" #include "4C_mat_plasticelasthyper.hpp" +#include "4C_mat_so3_material.hpp" #include "4C_mat_thermoplastichyperelast.hpp" #include "4C_mat_thermoplasticlinelast.hpp" #include "4C_mat_thermostvenantkirchhoff.hpp" @@ -34,6 +38,7 @@ #include #include +#include FOUR_C_NAMESPACE_OPEN @@ -204,7 +209,8 @@ int Discret::Elements::TemperImpl::evaluate( // tangent ctemp plasticmat_ = false; if ((structmat->material_type() == Core::Materials::m_thermopllinelast) or - (structmat->material_type() == Core::Materials::m_thermoplhyperelast)) + (structmat->material_type() == Core::Materials::m_thermoplhyperelast) or + (structmat->material_type() == Core::Materials::m_multiplicative_split_defgrad_elasthyper)) plasticmat_ = true; } // (la.Size > 1) @@ -2064,41 +2070,40 @@ void Discret::Elements::TemperImpl::nonlinear_dissipation_fint_tang( Core::Geo::fill_initial_position_array>( ele, xyze_); - // update element geometry - Core::LinAlg::Matrix xrefe; // material coord. of element - Core::LinAlg::Matrix xcurr; // current coord. of element - - // now get current element displacements and velocities - auto nodes = ele->nodes(); - for (int i = 0; i < nen_; ++i) - { - const auto& x = nodes[i]->x(); - // (8x3) = (nen_xnsd_) - for (int j = 0; j < nsd_; ++j) - { - xrefe(i, j) = x[j]; - xcurr(i, j) = x[j] + disp[i * nsd_ + j]; - } - } - - // --------------------------------------------------------------- initialise - // thermal material tangent - Core::LinAlg::Matrix<6, 1> ctemp(Core::LinAlg::Initialization::zero); - // ------------------------------------------------------ structural material std::shared_ptr structmat = get_str_material(ele); - if (structmat->material_type() != Core::Materials::m_thermoplhyperelast) + // store possible pointers for specific material types for later use + std::shared_ptr thermoplhyperelast; + std::shared_ptr + multiplicative_split_defgrad_elast_hyper_ptr; + + if (structmat->material_type() == Core::Materials::m_thermoplhyperelast) { - FOUR_C_THROW("So far dissipation only for ThermoPlasticHyperElast material!"); + thermoplhyperelast = std::dynamic_pointer_cast(structmat); + FOUR_C_ASSERT(thermoplhyperelast != nullptr, "Cast failed."); + } + else if (structmat->material_type() == Core::Materials::m_multiplicative_split_defgrad_elasthyper) + { + multiplicative_split_defgrad_elast_hyper_ptr = + std::dynamic_pointer_cast(structmat); + FOUR_C_ASSERT(multiplicative_split_defgrad_elast_hyper_ptr != nullptr, "Cast failed."); + } + else + { + FOUR_C_THROW( + "So far dissipation only for ThermoPlasticHyperElast and " + "MultiplicativeSplitDefgradElastHyper materials!"); } - std::shared_ptr thermoplhyperelast = - std::dynamic_pointer_cast(structmat); - // true: error if cast fails // --------------------------------------------------------- time integration // get step size dt const double stepsize = params.get("delta time"); + const double total_time = params.get("total time"); + + Mat::EvaluationContext eval_context; + eval_context.total_time = &total_time; + eval_context.time_step_size = &stepsize; // ----------------------------------------- integration loop for one element @@ -2106,8 +2111,17 @@ void Discret::Elements::TemperImpl::nonlinear_dissipation_fint_tang( Core::FE::IntPointsAndWeights intpoints(Thermo::DisTypeToOptGaussRule::rule); if (intpoints.ip().nquad != nquad_) FOUR_C_THROW("Trouble with number of Gauss points"); + // update element geometry + Core::LinAlg::Matrix xcurr; // current coord. of element + Core::LinAlg::Matrix xcurrrate; // current velocity of element + + std::vector vel(disp.size(), 0.0); // dummy velocity vector + + initial_and_current_nodal_position_velocity(ele, disp, vel, xcurr, xcurrrate); + // initialise the deformation gradient w.r.t. material configuration Core::LinAlg::Matrix defgrd(Core::LinAlg::Initialization::uninitialized); + Core::LinAlg::Matrix<1, 1> current_temperature(Core::LinAlg::Initialization::uninitialized); // --------------------------------------------------- loop over Gauss Points for (int iquad = 0; iquad < intpoints.ip().nquad; ++iquad) @@ -2116,13 +2130,39 @@ void Discret::Elements::TemperImpl::nonlinear_dissipation_fint_tang( // coordinates eval_shape_func_and_derivs_at_int_point(intpoints, iquad, ele->id()); + // (material) deformation gradient F + // F = d xcurr / d xrefe = xcurr^T . N_XYZ^T + defgrd.multiply_tt(xcurr, derxy_); + + current_temperature.multiply_tn(funct_, etempn_); + // ------------------------------------------------------------ dissipation // plastic contribution thermoplastichyperelastic material - // mechanical Dissipation - // Dmech := sqrt(2/3) . sigma_y(T_{n+1}) . Dgamma/Dt - // with MechDiss := sqrt(2/3) . sigma_y(T_{n+1}) . Dgamma - const double Dmech = thermoplhyperelast->mech_diss(iquad) / stepsize; + double Dmech = 0.0; + Mat::HeatSource heat_source; + if (structmat->material_type() == Core::Materials::m_thermoplhyperelast) + { + // mechanical Dissipation + // Dmech := sqrt(2/3) . sigma_y(T_{n+1}) . Dgamma/Dt + // with MechDiss := sqrt(2/3) . sigma_y(T_{n+1}) . Dgamma + Dmech = thermoplhyperelast->mech_diss(iquad) / stepsize; + } + else if (structmat->material_type() == + Core::Materials::m_multiplicative_split_defgrad_elasthyper) + { + if constexpr (nsd_ == 3) + { + heat_source = multiplicative_split_defgrad_elast_hyper_ptr->evaluate_additional_heat_source( + eval_context, iquad, ele->id(), &defgrd, current_temperature(0)); + Dmech = heat_source.value; + } + else + { + FOUR_C_THROW( + "Dissipation currently only implemented for 3D multiplicative split materials"); + } + } // update/integrate internal force vector (coupling fraction towards displacements) if (efint != nullptr) @@ -2134,10 +2174,26 @@ void Discret::Elements::TemperImpl::nonlinear_dissipation_fint_tang( if (econd != nullptr) { - // Contribution of dissipation to cond matrix - // econd += - N_T^T . dDmech_dT/Dt . N_T - econd->multiply_nt( - (-fac_ * thermoplhyperelast->mech_diss_k_tt(iquad) / stepsize), funct_, funct_, 1.0); + if (structmat->material_type() == Core::Materials::m_thermoplhyperelast) + { + // Contribution of dissipation to cond matrix + // econd += - N_T^T . dDmech_dT/Dt . N_T + econd->multiply_nt( + (-fac_ * thermoplhyperelast->mech_diss_k_tt(iquad) / stepsize), funct_, funct_, 1.0); + } + else if (structmat->material_type() == + Core::Materials::m_multiplicative_split_defgrad_elasthyper) + { + if constexpr (nsd_ == 3) + { + econd->multiply_nt((-fac_ * heat_source.derivative_wrt_temperature), funct_, funct_, 1.0); + } + else + { + FOUR_C_THROW( + "Dissipation currently only implemented for 3D multiplicative split materials"); + } + } } } // ---------------------------------- end loop over Gauss Points @@ -2161,16 +2217,42 @@ void Discret::Elements::TemperImpl::nonlinear_dissipation_coupled_tang( Core::LinAlg::Matrix defgrd(Core::LinAlg::Initialization::uninitialized); // inverse of deformation gradient Core::LinAlg::Matrix invdefgrd(Core::LinAlg::Initialization::uninitialized); + Core::LinAlg::Matrix<1, 1> current_temperature(Core::LinAlg::Initialization::uninitialized); // ------------------------------------------------ structural material std::shared_ptr structmat = get_str_material(ele); - std::shared_ptr thermoplhyperelast = - std::dynamic_pointer_cast(structmat); - // true: error if cast fails + + // setup possible pointers for specific material types for later use + std::shared_ptr thermoplhyperelast; + std::shared_ptr + multiplicative_split_defgrad_elast_hyper; + + if (structmat->material_type() == Core::Materials::m_thermoplhyperelast) + { + thermoplhyperelast = std::dynamic_pointer_cast(structmat); + FOUR_C_ASSERT(thermoplhyperelast != nullptr, "Cast failed."); + } + else if (structmat->material_type() == Core::Materials::m_multiplicative_split_defgrad_elasthyper) + { + multiplicative_split_defgrad_elast_hyper = + std::dynamic_pointer_cast(structmat); + FOUR_C_ASSERT(multiplicative_split_defgrad_elast_hyper != nullptr, "Cast failed."); + } + else + { + FOUR_C_THROW( + "So far dissipation only for ThermoPlasticHyperElast and " + "MultiplicativeSplitDefgradElastHyper materials!"); + } // --------------------------------------------------- time integration // get step size dt const double stepsize = params.get("delta time"); + const double total_time = params.get("total time"); + + Mat::EvaluationContext eval_context; + eval_context.total_time = &total_time; + eval_context.time_step_size = &stepsize; // check the time integrator and add correct time factor const auto timint = @@ -2223,26 +2305,53 @@ void Discret::Elements::TemperImpl::nonlinear_dissipation_coupled_tang( // (material) deformation gradient F // F = d xcurr / d xrefe = xcurr^T . N_XYZ^T defgrd.multiply_tt(xcurr, derxy_); + current_temperature.multiply_tn(funct_, etempn_); // calculate the nonlinear B-operator Core::LinAlg::Matrix<6, nsd_ * nen_ * numdofpernode_> bop( Core::LinAlg::Initialization::uninitialized); calculate_bop(&bop, &defgrd, &derxy_); - // ----------------------------------------------- linearisation of Dmech_d - // k_Td += - timefac . N_T^T . 1/Dt . mechdiss_kTd . dE/dd - Core::LinAlg::Matrix<6, 1> dDmech_dE(Core::LinAlg::Initialization::uninitialized); - dDmech_dE.update(thermoplhyperelast->mech_diss_k_td(iquad)); + // Linearization of the mechanical heat-source contribution w.r.t. the + // Green-Lagrange strain. + // k_Td += - timefac . N_T^T . d(D_mech)/dE . dE/dd + Core::LinAlg::Matrix<1, 6> dDmech_dE(Core::LinAlg::Initialization::uninitialized); + + if (structmat->material_type() == Core::Materials::m_thermoplhyperelast) + { + dDmech_dE.update_t(1 / stepsize, thermoplhyperelast->mech_diss_k_td(iquad)); + } + else if (structmat->material_type() == + Core::Materials::m_multiplicative_split_defgrad_elasthyper) + { + if constexpr (nsd_ == 3) + { + const auto& mech_diss = + multiplicative_split_defgrad_elast_hyper->evaluate_additional_heat_source( + eval_context, iquad, ele->id(), &defgrd, current_temperature(0)); + + /// \f[ \frac{\mathrm{d}D_\text{mech}}{\mathrm{d}\mathbf{E}} = + /// 2\frac{\mathrm{d}D_\text{mech}}{\mathrm{d}\mathbf{C}}\f] + /// using \f[\mathbf{C} = 2\mathbf{E} + \mathbf{I}\f] + dDmech_dE.update(2.0, mech_diss.derivative_wrt_cauchy_green); + } + else + { + FOUR_C_THROW( + "Dissipation currently only implemented for 3D multiplicative split materials"); + } + } + Core::LinAlg::Matrix<1, nsd_ * nen_ * numdofpernode_> dDmech_dd( Core::LinAlg::Initialization::uninitialized); - dDmech_dd.multiply_tn(dDmech_dE, bop); + dDmech_dd.multiply(dDmech_dE, bop); // coupling stiffness matrix if (etangcoupl != nullptr) { - // k_Td^e += - timefac . N_T^T . 1/Dt . dDmech_dE . B . detJ . w(gp) + // k_Td^e += - timefac . N_T^T . d(D_mech)/dE . B . detJ . w(gp) // (8x24) = (8x1) . (1x6) (6x24) - etangcoupl->multiply_nn(-fac_ * timefac / stepsize, funct_, dDmech_dd, 1.0); + etangcoupl->multiply_nn(-fac_ * timefac, funct_, dDmech_dd, 1.0); } // (etangcoupl != nullptr) } //--------------------------------------------- end loop over Gauss Points diff --git a/src/tsi/4C_tsi_monolithic.cpp b/src/tsi/4C_tsi_monolithic.cpp index 5b0caefceae..bf3097c3289 100644 --- a/src/tsi/4C_tsi_monolithic.cpp +++ b/src/tsi/4C_tsi_monolithic.cpp @@ -1638,6 +1638,7 @@ void TSI::Monolithic::apply_str_coupl_matrix( // other parameters that might be needed by the elements sparams.set("delta time", dt()); sparams.set("total time", time()); + sparams.set("differentiationtype", static_cast(Solid::DifferentiationType::temp)); structure_field()->discretization()->clear_state(true); structure_field()->discretization()->set_state(0, "displacement", *structure_field()->dispnp()); diff --git a/tests/input_files/mat_iso_thermoviscoplast_refJC_log_timint_tsi_monolithic.4C.yaml b/tests/input_files/mat_iso_thermoviscoplast_refJC_log_timint_tsi_monolithic.4C.yaml new file mode 100644 index 00000000000..e64328eb8dc --- /dev/null +++ b/tests/input_files/mat_iso_thermoviscoplast_refJC_log_timint_tsi_monolithic.4C.yaml @@ -0,0 +1,326 @@ +PROBLEM TYPE: + PROBLEMTYPE: "Thermo_Structure_Interaction" +IO: + STRUCT_STRESS: "Cauchy" + STRUCT_STRAIN: "LOG" +IO/RUNTIME VTK OUTPUT/STRUCTURE: + OUTPUT_STRUCTURE: true + DISPLACEMENT: true + STRESS_STRAIN: true +IO/RUNTIME VTK OUTPUT: + INTERVAL_STEPS: 1 +STRUCTURAL DYNAMIC: + DYNAMICTYPE: "Statics" + TOLDISP: 1e-08 + NEGLECTINERTIA: true + LINEAR_SOLVER: 1 +THERMAL DYNAMIC: + DYNAMICTYPE: OneStepTheta + INITIALFIELD: "field_by_function" + INITFUNCNO: 2 + TOLTEMP: 1e-08 + NORM_TEMP: Abs + TOLRES: 1e-06 + NORM_RESF: Abs + NORMCOMBI_RESFTEMP: And + ITERNORM: L2 + PREDICT: ConstTemp + ADAPTCONV: false + ADAPTCONV_BETTER: 0.1 + LUMPCAPA: false + LINEAR_SOLVER: 1 +THERMAL DYNAMIC/RUNTIME VTK OUTPUT: + OUTPUT_THERMO: true + TEMPERATURE: true +TSI DYNAMIC: + COUPALGO: tsi_monolithic + MATCHINGGRID: true + RESTARTEVERY: 30 + NUMSTEP: 100000000 + MAXTIME: 0.0001 # [s] + TIMESTEP: 1e-6 # [s] + ITEMAX: 10 + ITEMIN: 0 + RESULTSEVERY: 1 + NORM_INC: Abs +TSI DYNAMIC/MONOLITHIC: + LINEAR_SOLVER: 1 + MERGE_TSI_BLOCK_MATRIX: true + TOLINC: 1e-08 + CONVTOL: 1e-08 + NORM_RESF: Abs +SOLVER 1: + SOLVER: UMFPACK +MATERIALS: + - MAT: 1 + MAT_MultiplicativeSplitDefgradElastHyper: + NUMMATEL: 1 + MATIDSEL: [2] + NUMFACINEL: 1 + INELDEFGRADFACIDS: [3] + DENS: 7830e-12 # [t/mm^3 = N*s^2/mm^4] + REF_TEMPERATURE: 293.0 # [K] + THERMAL_EXPANSION_COEFFICIENT: 11e-6 # [1/K] + - MAT: 2 + ELAST_CoupNeoHooke: + YOUNG: 200000 # [N/mm^2] + NUE: 0.29 # [-] + - MAT: 3 + MAT_InelasticDefgradTransvIsotropElastViscoplast: + VISCOPLAST_LAW_ID: 4 + TAYLOR_QUINNEY_COEFFICIENT: 0.85 # [-] + FIBER_READER_ID: 5 + MAT_BEHAVIOR: "isotropic" + TIME_INTEGRATION_HIST_VARS: logarithmic + LOCAL_NEWTON: + CONV_CHECK: residual_and_increment_ratio + MAX_ITER: 100 + RES_TOL: 1e-8 + INCR_TOL: 1e-8 + MAX_EXCEEDANCE_FACT_RES_TOL: 10 + MAX_EXCEEDANCE_FACT_INCR_TOL: 10 + DIVER_CONT: stop + - MAT: 4 + MAT_ViscoplasticLawReformulatedJohnsonCook: + STRAIN_RATE_PREFAC: 1 # [1/s] + STRAIN_RATE_EXP_FAC: 0.014 # [-] + INIT_YIELD_STRENGTH: 792 # [N/mm^2] + ISOTROP_HARDEN_PREFAC: 510 # [N/mm^2] + ISOTROP_HARDEN_EXP: 0.26 # [-] + REF_TEMPERATURE: 293.0 # [K] + TEMPERATURE_SENS: 1.03 # [-] + MELT_TEMPERATURE: 1793 # [K] + - MAT: 5 + ELAST_CoupTransverselyIsotropic: + ALPHA: 1 + BETA: 1 + GAMMA: 1 + ANGLE: 0 + STR_TENS_ID: 100 + - MAT: 100 + ELAST_StructuralTensor: + STRATEGY: "Standard" + + - MAT: 10 + MAT_Fourier: + CAPA: 3.734910 # [mJ/(mm^3*K) = N/(mm^2*K)] + CONDUCT: + constant: [37] # [mW/(mm*K) = N/s/K] + +CLONING MATERIAL MAP: + - SRC_FIELD: structure + SRC_MAT: 1 + TAR_FIELD: thermo + TAR_MAT: 10 + +FUNCT1: + - SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "multifunction" + NUMPOINTS: 2 + TIMES: [0, 1.6e+16] + DESCRIPTION: ["(exp(1.0e2*t)-1.0)"] # [mm] +FUNCT2: + - SYMBOLIC_FUNCTION_OF_SPACE_TIME: "temperature_initial_field" + - VARIABLE: 0 + TYPE: expression + NAME: "temperature_initial_field" + DESCRIPTION: "293" +RESULT DESCRIPTION: + - STRUCTURE: + DIS: "structure" + NODE: 4 + QUANTITY: "dispy" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 5 + QUANTITY: "dispx" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 8 + QUANTITY: "dispx" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 8 + QUANTITY: "dispy" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 8 + QUANTITY: "dispz" + VALUE: 0.010050167084167949 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 6 + QUANTITY: "dispx" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 4 + QUANTITY: "stress_zz" + VALUE: 977.652620618 + TOLERANCE: 1e-8 + - STRUCTURE: + DIS: "structure" + NODE: 8 + QUANTITY: "stress_zz" + VALUE: 977.652620618 + TOLERANCE: 1e-8 + - THERMAL: + DIS: thermo + NODE: 1 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 2 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 3 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 4 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 5 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 6 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 7 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 8 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-10 +DESIGN POINT DIRICH CONDITIONS: + - E: 1 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 2 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 1] + FUNCT: [null, null, 1] +DESIGN LINE DIRICH CONDITIONS: + - E: 1 + NUMDOF: 3 + ONOFF: [1, 0, 1] + VAL: [0, 0, 1] + FUNCT: [null, null, 1] + - E: 2 + NUMDOF: 3 + ONOFF: [0, 1, 1] + VAL: [0, 0, 1] + FUNCT: [null, null, 1] + - E: 3 + NUMDOF: 3 + ONOFF: [1, 1, 0] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 4 + NUMDOF: 3 + ONOFF: [1, 0, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 5 + NUMDOF: 3 + ONOFF: [0, 1, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] +DESIGN SURF DIRICH CONDITIONS: + - E: 1 + NUMDOF: 3 + ONOFF: [0, 0, 1] + VAL: [0, 0, 1] + FUNCT: [null, null, 1] + - E: 2 + NUMDOF: 3 + ONOFF: [0, 0, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 3 + NUMDOF: 3 + ONOFF: [1, 0, 0] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 4 + NUMDOF: 3 + ONOFF: [0, 1, 0] + VAL: [0, 0, 0] + FUNCT: [null, null, null] +DNODE-NODE TOPOLOGY: + - "NODE 2 DNODE 1" + - "NODE 1 DNODE 2" +DLINE-NODE TOPOLOGY: + - "NODE 1 DLINE 1" + - "NODE 4 DLINE 1" + - "NODE 1 DLINE 2" + - "NODE 5 DLINE 2" + - "NODE 1 DLINE 3" + - "NODE 2 DLINE 3" + - "NODE 2 DLINE 4" + - "NODE 3 DLINE 4" + - "NODE 2 DLINE 5" + - "NODE 6 DLINE 5" +DSURF-NODE TOPOLOGY: + - "NODE 1 DSURFACE 1" + - "NODE 4 DSURFACE 1" + - "NODE 5 DSURFACE 1" + - "NODE 8 DSURFACE 1" + - "NODE 2 DSURFACE 2" + - "NODE 3 DSURFACE 2" + - "NODE 6 DSURFACE 2" + - "NODE 7 DSURFACE 2" + - "NODE 1 DSURFACE 3" + - "NODE 2 DSURFACE 3" + - "NODE 3 DSURFACE 3" + - "NODE 4 DSURFACE 3" + - "NODE 1 DSURFACE 4" + - "NODE 2 DSURFACE 4" + - "NODE 5 DSURFACE 4" + - "NODE 6 DSURFACE 4" +NODE COORDS: + - "NODE 1 COORD -5.0000000000000000e-01 -5.0000000000000000e-01 5.0000000000000000e-01" + - "NODE 2 COORD -5.0000000000000000e-01 -5.0000000000000000e-01 -5.0000000000000000e-01" + - "NODE 3 COORD -5.0000000000000000e-01 5.0000000000000000e-01 -5.0000000000000000e-01" + - "NODE 4 COORD -5.0000000000000000e-01 5.0000000000000000e-01 5.0000000000000000e-01" + - "NODE 5 COORD 5.0000000000000000e-01 -5.0000000000000000e-01 5.0000000000000000e-01" + - "NODE 6 COORD 5.0000000000000000e-01 -5.0000000000000000e-01 -5.0000000000000000e-01" + - "NODE 7 COORD 5.0000000000000000e-01 5.0000000000000000e-01 -5.0000000000000000e-01" + - "NODE 8 COORD 5.0000000000000000e-01 5.0000000000000000e-01 5.0000000000000000e-01" +STRUCTURE ELEMENTS: + - "1 SOLIDSCATRA HEX8 1 2 3 4 5 6 7 8 MAT 1 KINEM nonlinear FIBER1 0 0 1.0 TYPE Undefined" diff --git a/tests/input_files/mat_iso_thermoviscoplast_refJC_log_timint_tsi_partitioned.4C.yaml b/tests/input_files/mat_iso_thermoviscoplast_refJC_log_timint_tsi_partitioned.4C.yaml new file mode 100644 index 00000000000..08b66316a04 --- /dev/null +++ b/tests/input_files/mat_iso_thermoviscoplast_refJC_log_timint_tsi_partitioned.4C.yaml @@ -0,0 +1,329 @@ +PROBLEM TYPE: + PROBLEMTYPE: "Thermo_Structure_Interaction" +IO: + STRUCT_STRESS: "Cauchy" + STRUCT_STRAIN: "LOG" +IO/RUNTIME VTK OUTPUT/STRUCTURE: + OUTPUT_STRUCTURE: true + DISPLACEMENT: true + STRESS_STRAIN: true +IO/RUNTIME VTK OUTPUT: + INTERVAL_STEPS: 1 +STRUCTURAL DYNAMIC: + DYNAMICTYPE: "Statics" + RESTARTEVERY: 30 + TOLDISP: 1e-08 + NEGLECTINERTIA: true + LINEAR_SOLVER: 1 +THERMAL DYNAMIC: + DYNAMICTYPE: OneStepTheta + INITIALFIELD: "field_by_function" + INITFUNCNO: 2 + TOLTEMP: 1e-08 + NORM_TEMP: Abs + TOLRES: 1e-06 + NORM_RESF: Abs + NORMCOMBI_RESFTEMP: And + MAXITER: 50 + MINITER: 0 + ITERNORM: L2 + NLNSOL: fullnewton + PREDICT: ConstTemp + ADAPTCONV: false + ADAPTCONV_BETTER: 0.1 + LUMPCAPA: false + LINEAR_SOLVER: 1 + CALCERROR: "No" + CALCERRORFUNCNO: -1 +THERMAL DYNAMIC/RUNTIME VTK OUTPUT: + OUTPUT_THERMO: true + TEMPERATURE: true +TSI DYNAMIC: + COUPALGO: tsi_iterstagg + MATCHINGGRID: true + RESTARTEVERY: 30 + NUMSTEP: 100000000 + MAXTIME: 0.0001 # [s] + TIMESTEP: 1e-6 # [s] + ITEMAX: 10 + ITEMIN: 0 + RESULTSEVERY: 1 + NORM_INC: Abs +TSI DYNAMIC/PARTITIONED: + CONVTOL: 1e-10 + COUPVARIABLE: Temperature +SOLVER 1: + SOLVER: "UMFPACK" +MATERIALS: + - MAT: 1 + MAT_MultiplicativeSplitDefgradElastHyper: + NUMMATEL: 1 + MATIDSEL: [2] + NUMFACINEL: 1 + INELDEFGRADFACIDS: [3] + DENS: 7830e-12 # [t/mm^3 = N*s^2/mm^4] + REF_TEMPERATURE: 293.0 # [K] + THERMAL_EXPANSION_COEFFICIENT: 11e-6 # [1/K] + - MAT: 2 + ELAST_CoupNeoHooke: + YOUNG: 200000 # [N/mm^2] + NUE: 0.29 # [-] + - MAT: 3 + MAT_InelasticDefgradTransvIsotropElastViscoplast: + VISCOPLAST_LAW_ID: 4 + TAYLOR_QUINNEY_COEFFICIENT: 0.85 # [-] + FIBER_READER_ID: 5 + MAT_BEHAVIOR: "isotropic" + TIME_INTEGRATION_HIST_VARS: logarithmic + LOCAL_NEWTON: + CONV_CHECK: residual_and_increment_ratio + MAX_ITER: 100 + RES_TOL: 1e-8 + INCR_TOL: 1e-8 + MAX_EXCEEDANCE_FACT_RES_TOL: 10 + MAX_EXCEEDANCE_FACT_INCR_TOL: 10 + DIVER_CONT: stop + - MAT: 4 + MAT_ViscoplasticLawReformulatedJohnsonCook: + STRAIN_RATE_PREFAC: 1 # [1/s] + STRAIN_RATE_EXP_FAC: 0.014 # [-] + INIT_YIELD_STRENGTH: 792 # [N/mm^2] + ISOTROP_HARDEN_PREFAC: 510 # [N/mm^2] + ISOTROP_HARDEN_EXP: 0.26 # [-] + REF_TEMPERATURE: 293.0 # [K] + TEMPERATURE_SENS: 1.03 # [-] + MELT_TEMPERATURE: 1793 # [K] + - MAT: 5 + ELAST_CoupTransverselyIsotropic: + ALPHA: 1 + BETA: 1 + GAMMA: 1 + ANGLE: 0 + STR_TENS_ID: 100 + - MAT: 100 + ELAST_StructuralTensor: + STRATEGY: "Standard" + + - MAT: 10 + MAT_Fourier: + CAPA: 3.734910 # [mJ/(mm^3*K) = N/(mm^2*K)] + CONDUCT: + constant: [37] # [mW/(mm*K) = N/s/K] + +CLONING MATERIAL MAP: + - SRC_FIELD: structure + SRC_MAT: 1 + TAR_FIELD: thermo + TAR_MAT: 10 + +FUNCT1: + - SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "multifunction" + NUMPOINTS: 2 + TIMES: [0, 1.6e+16] + DESCRIPTION: ["(exp(1.0e2*t)-1.0)"] # [mm] +FUNCT2: + - SYMBOLIC_FUNCTION_OF_SPACE_TIME: "temperature_initial_field" + - VARIABLE: 0 + TYPE: expression + NAME: "temperature_initial_field" + DESCRIPTION: "293" +RESULT DESCRIPTION: + - STRUCTURE: + DIS: "structure" + NODE: 4 + QUANTITY: "dispy" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 5 + QUANTITY: "dispx" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 8 + QUANTITY: "dispx" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 8 + QUANTITY: "dispy" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 8 + QUANTITY: "dispz" + VALUE: 0.010050167084167949 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 6 + QUANTITY: "dispx" + VALUE: -0.00394895027488 + TOLERANCE: 1e-14 + - STRUCTURE: + DIS: "structure" + NODE: 4 + QUANTITY: "stress_zz" + VALUE: 977.652620618 + TOLERANCE: 1e-8 + - STRUCTURE: + DIS: "structure" + NODE: 8 + QUANTITY: "stress_zz" + VALUE: 977.652620618 + TOLERANCE: 1e-8 + - THERMAL: + DIS: thermo + NODE: 1 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 2 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 3 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 4 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 5 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 6 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 7 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 + - THERMAL: + DIS: thermo + NODE: 8 + QUANTITY: temp + VALUE: 294.095019277192 + TOLERANCE: 1e-11 +DESIGN POINT DIRICH CONDITIONS: + - E: 1 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 2 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 1] + FUNCT: [null, null, 1] +DESIGN LINE DIRICH CONDITIONS: + - E: 1 + NUMDOF: 3 + ONOFF: [1, 0, 1] + VAL: [0, 0, 1] + FUNCT: [null, null, 1] + - E: 2 + NUMDOF: 3 + ONOFF: [0, 1, 1] + VAL: [0, 0, 1] + FUNCT: [null, null, 1] + - E: 3 + NUMDOF: 3 + ONOFF: [1, 1, 0] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 4 + NUMDOF: 3 + ONOFF: [1, 0, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 5 + NUMDOF: 3 + ONOFF: [0, 1, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] +DESIGN SURF DIRICH CONDITIONS: + - E: 1 + NUMDOF: 3 + ONOFF: [0, 0, 1] + VAL: [0, 0, 1] + FUNCT: [null, null, 1] + - E: 2 + NUMDOF: 3 + ONOFF: [0, 0, 1] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 3 + NUMDOF: 3 + ONOFF: [1, 0, 0] + VAL: [0, 0, 0] + FUNCT: [null, null, null] + - E: 4 + NUMDOF: 3 + ONOFF: [0, 1, 0] + VAL: [0, 0, 0] + FUNCT: [null, null, null] +DNODE-NODE TOPOLOGY: + - "NODE 2 DNODE 1" + - "NODE 1 DNODE 2" +DLINE-NODE TOPOLOGY: + - "NODE 1 DLINE 1" + - "NODE 4 DLINE 1" + - "NODE 1 DLINE 2" + - "NODE 5 DLINE 2" + - "NODE 1 DLINE 3" + - "NODE 2 DLINE 3" + - "NODE 2 DLINE 4" + - "NODE 3 DLINE 4" + - "NODE 2 DLINE 5" + - "NODE 6 DLINE 5" +DSURF-NODE TOPOLOGY: + - "NODE 1 DSURFACE 1" + - "NODE 4 DSURFACE 1" + - "NODE 5 DSURFACE 1" + - "NODE 8 DSURFACE 1" + - "NODE 2 DSURFACE 2" + - "NODE 3 DSURFACE 2" + - "NODE 6 DSURFACE 2" + - "NODE 7 DSURFACE 2" + - "NODE 1 DSURFACE 3" + - "NODE 2 DSURFACE 3" + - "NODE 3 DSURFACE 3" + - "NODE 4 DSURFACE 3" + - "NODE 1 DSURFACE 4" + - "NODE 2 DSURFACE 4" + - "NODE 5 DSURFACE 4" + - "NODE 6 DSURFACE 4" +NODE COORDS: + - "NODE 1 COORD -5.0000000000000000e-01 -5.0000000000000000e-01 5.0000000000000000e-01" + - "NODE 2 COORD -5.0000000000000000e-01 -5.0000000000000000e-01 -5.0000000000000000e-01" + - "NODE 3 COORD -5.0000000000000000e-01 5.0000000000000000e-01 -5.0000000000000000e-01" + - "NODE 4 COORD -5.0000000000000000e-01 5.0000000000000000e-01 5.0000000000000000e-01" + - "NODE 5 COORD 5.0000000000000000e-01 -5.0000000000000000e-01 5.0000000000000000e-01" + - "NODE 6 COORD 5.0000000000000000e-01 -5.0000000000000000e-01 -5.0000000000000000e-01" + - "NODE 7 COORD 5.0000000000000000e-01 5.0000000000000000e-01 -5.0000000000000000e-01" + - "NODE 8 COORD 5.0000000000000000e-01 5.0000000000000000e-01 5.0000000000000000e-01" +STRUCTURE ELEMENTS: + - "1 SOLIDSCATRA HEX8 1 2 3 4 5 6 7 8 MAT 1 KINEM nonlinear FIBER1 0 0 1.0 TYPE Undefined" diff --git a/tests/list_of_tests.cmake b/tests/list_of_tests.cmake index 851d5240350..df7fe7157f7 100644 --- a/tests/list_of_tests.cmake +++ b/tests/list_of_tests.cmake @@ -899,6 +899,10 @@ four_c_test(TEST_FILE mat_humphreycardio.4C.yaml NP 2) four_c_test(TEST_FILE mat_iso_viscoplast_refJC_log_timint.4C.yaml RETURN_AS current) __four_c_test_restart(BASED_ON ${current} SAME_FILE RESTART_STEP 90) four_c_test(TEST_FILE mat_iso_viscoplast_refJC_log_timint_substepping.4C.yaml RETURN_AS current) +four_c_test(TEST_FILE mat_iso_thermoviscoplast_refJC_log_timint_tsi_monolithic.4C.yaml RETURN_AS current) +__four_c_test_restart(BASED_ON ${current} SAME_FILE RESTART_STEP 90) +four_c_test(TEST_FILE mat_iso_thermoviscoplast_refJC_log_timint_tsi_partitioned.4C.yaml RETURN_AS current) +__four_c_test_restart(BASED_ON ${current} SAME_FILE RESTART_STEP 90) four_c_test(TEST_FILE mat_muscle_combo_hex.4C.yaml NP 2 RETURN_AS current) __four_c_test_restart(BASED_ON ${current} SAME_FILE NP 2 RESTART_STEP 140) four_c_test(TEST_FILE mat_muscle_combo_hex_act_map_every_timestep.4C.yaml NP 2 RETURN_AS current) diff --git a/unittests/mat/4C_multiplicative_split_defgrad_elasthyper_service_test.cpp b/unittests/mat/4C_multiplicative_split_defgrad_elasthyper_service_test.cpp index 95a5833cbd1..5f2094eb9e2 100644 --- a/unittests/mat/4C_multiplicative_split_defgrad_elasthyper_service_test.cpp +++ b/unittests/mat/4C_multiplicative_split_defgrad_elasthyper_service_test.cpp @@ -8,7 +8,7 @@ #include #include "4C_linalg_fixedsizematrix.hpp" -#include "4C_linalg_fixedsizematrix_voigt_notation.hpp" +#include "4C_linalg_symmetric_tensor.hpp" #include "4C_mat_elast_coupneohooke.hpp" #include "4C_mat_elast_isoneohooke.hpp" #include "4C_mat_elasthyper_service.hpp" @@ -175,58 +175,32 @@ namespace iFinM(2, 1) = 0.0000000000000000; iFinM(2, 2) = 0.8021447823814358; //************************************************** - Core::LinAlg::Matrix<3, 3> CTM_ref_{Core::LinAlg::Initialization::zero}; - CTM_ref_(0, 0) = 21.0000000000000000; - CTM_ref_(0, 1) = 0.0000000000000000; - CTM_ref_(0, 2) = 0.0000000000000000; - CTM_ref_(1, 0) = 0.0000000000000000; - CTM_ref_(1, 1) = 21.0000000000000000; - CTM_ref_(1, 2) = 0.0000000000000000; - CTM_ref_(2, 0) = 0.0000000000000000; - CTM_ref_(2, 1) = 0.0000000000000000; - CTM_ref_(2, 2) = 21.0000000000000000; + Core::LinAlg::SymmetricTensor thermal_contribution_to_2pk_stress_ref_{}; + thermal_contribution_to_2pk_stress_ref_(0, 0) = 60.3191058810404357; + thermal_contribution_to_2pk_stress_ref_(0, 1) = 32.4795185513294626; + thermal_contribution_to_2pk_stress_ref_(0, 2) = 0.0000000000000000; + thermal_contribution_to_2pk_stress_ref_(1, 0) = 32.4795185513294626; + thermal_contribution_to_2pk_stress_ref_(1, 1) = 103.2384696810115088; + thermal_contribution_to_2pk_stress_ref_(1, 2) = 0.0000000000000000; + thermal_contribution_to_2pk_stress_ref_(2, 0) = 0.0000000000000000; + thermal_contribution_to_2pk_stress_ref_(2, 1) = 0.0000000000000000; + thermal_contribution_to_2pk_stress_ref_(2, 2) = 37.1194497729479664; //************************************************** - Core::LinAlg::Matrix<3, 3> dCTM_dT_ref_{Core::LinAlg::Initialization::zero}; - dCTM_dT_ref_(0, 0) = 0.2000000000000000; - dCTM_dT_ref_(0, 1) = 0.0000000000000000; - dCTM_dT_ref_(0, 2) = 0.0000000000000000; - dCTM_dT_ref_(1, 0) = 0.0000000000000000; - dCTM_dT_ref_(1, 1) = 0.2000000000000000; - dCTM_dT_ref_(1, 2) = 0.0000000000000000; - dCTM_dT_ref_(2, 0) = 0.0000000000000000; - dCTM_dT_ref_(2, 1) = 0.0000000000000000; - dCTM_dT_ref_(2, 2) = 0.2000000000000000; - //************************************************** - Core::LinAlg::Matrix<3, 3> S_ref{Core::LinAlg::Initialization::zero}; - S_ref(0, 0) = -60.3191058810404357; - S_ref(0, 1) = -32.4795185513294626; - S_ref(0, 2) = 0.0000000000000000; - S_ref(1, 0) = -32.4795185513294626; - S_ref(1, 1) = -103.2384696810115088; - S_ref(1, 2) = 0.0000000000000000; - S_ref(2, 0) = 0.0000000000000000; - S_ref(2, 1) = 0.0000000000000000; - S_ref(2, 2) = -37.1194497729479664; - //************************************************** - Core::LinAlg::Matrix<3, 3> pS_pT_ref_{Core::LinAlg::Initialization::zero}; - pS_pT_ref_(0, 0) = -0.0000941798851085; - pS_pT_ref_(0, 1) = -0.0000507122458277; - pS_pT_ref_(0, 2) = -0.0000000000000000; - pS_pT_ref_(1, 0) = -0.0000507122458277; - pS_pT_ref_(1, 1) = -0.0001611924956665; - pS_pT_ref_(1, 2) = -0.0000000000000000; - pS_pT_ref_(2, 0) = -0.0000000000000000; - pS_pT_ref_(2, 1) = -0.0000000000000000; - pS_pT_ref_(2, 2) = -0.0000579568523745; + Core::LinAlg::SymmetricTensor + p_thermal_contribution_to_2pk_stress_p_temperature_ref_{}; + p_thermal_contribution_to_2pk_stress_p_temperature_ref_(0, 0) = 0.0000941798851085; + p_thermal_contribution_to_2pk_stress_p_temperature_ref_(0, 1) = 0.0000507122458277; + p_thermal_contribution_to_2pk_stress_p_temperature_ref_(0, 2) = 0.0000000000000000; + p_thermal_contribution_to_2pk_stress_p_temperature_ref_(1, 0) = 0.0000507122458277; + p_thermal_contribution_to_2pk_stress_p_temperature_ref_(1, 1) = 0.0001611924956665; + p_thermal_contribution_to_2pk_stress_p_temperature_ref_(1, 2) = 0.0000000000000000; + p_thermal_contribution_to_2pk_stress_p_temperature_ref_(2, 0) = 0.0000000000000000; + p_thermal_contribution_to_2pk_stress_p_temperature_ref_(2, 1) = 0.0000000000000000; + p_thermal_contribution_to_2pk_stress_p_temperature_ref_(2, 2) = 0.0000579568523745; // set thermal info const double thermal_expansion_fac = 0.1; - Core::LinAlg::Matrix<3, 3> iCinM{Core::LinAlg::Initialization::zero}; - iCinM.multiply_nt(1.0, iFinM, iFinM, 0.0); - Core::LinAlg::Matrix<6, 1> iCinV{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Stresses::matrix_to_vector(iCinM, iCinV); - // Create summand vector std::vector> potsum; Core::IO::InputParameterContainer elast_pot_coup_neo_hooke_data; @@ -238,37 +212,15 @@ namespace dynamic_cast(coup_neo_hooke_params.get()))); - // evaluate thermal quantities - Mat::ThermalQuantities thermal_quantities = Mat::evaluate_thermal_quantities( - delta_temperature, thermal_expansion_fac, iFinM, 0, 0, potsum); - - // evaluate thermal stress factors - Mat::StressFactors thermal_stress_factors; - Mat::calculate_gamma_delta(thermal_stress_factors.gamma, thermal_stress_factors.delta, - thermal_quantities.prinv, thermal_quantities.dPI, thermal_quantities.ddPII); - - // evaluate thermal contribution to second Piola-Kirchhoff stress - Core::LinAlg::Matrix<6, 1> S_V{Core::LinAlg::Initialization::zero}; - Mat::add_thermal_stress_contribution( - S_V, thermal_quantities, thermal_stress_factors, iCinV, 1.0 / iFinM.determinant()); - Core::LinAlg::Matrix<3, 3> S_M{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Stresses::vector_to_matrix(S_V, S_M); - // evaluate partial derivative of 2nd Piola-Kirchhoff stress wrt temperature - Core::LinAlg::Matrix<6, 1> pS_pT_V = - Mat::compute_partial_d_stress_d_temperature(iFinM, thermal_quantities); - Core::LinAlg::Matrix<3, 3> pS_pT_M{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Stresses::vector_to_matrix(pS_pT_V, pS_pT_M); - - - // postprocessed data for assertions - Core::LinAlg::Matrix<3, 3> CTM{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Stresses::vector_to_matrix(thermal_quantities.CTV, CTM); - Core::LinAlg::Matrix<3, 3> dCTM_dT{Core::LinAlg::Initialization::zero}; - Core::LinAlg::Voigt::Strains::vector_to_matrix(thermal_quantities.dCTdTV, dCTM_dT); + auto thermoelastic_stress_contribution = + Mat::ThermalExpansion::compute_thermoelastic_stress_contribution( + delta_temperature, thermal_expansion_fac, potsum, 0, 0); - FOUR_C_EXPECT_NEAR(CTM, CTM_ref_, 1.0e-10); - FOUR_C_EXPECT_NEAR(dCTM_dT, dCTM_dT_ref_, 1.0e-10); - FOUR_C_EXPECT_NEAR(S_M, S_ref, 1.0e-10); - FOUR_C_EXPECT_NEAR(pS_pT_M, pS_pT_ref_, 1.0e-10); + const auto pk2_stress_contribution = Mat::ThermalExpansion::compute_pk2_stress_contribution( + thermoelastic_stress_contribution, iFinM); + FOUR_C_EXPECT_NEAR( + pk2_stress_contribution.value, thermal_contribution_to_2pk_stress_ref_, 1.0e-10); + FOUR_C_EXPECT_NEAR(pk2_stress_contribution.temperature_derivative, + p_thermal_contribution_to_2pk_stress_p_temperature_ref_, 1.0e-10); } } // namespace diff --git a/unittests/mat/4C_multiplicative_split_defgrad_elasthyper_test.cpp b/unittests/mat/4C_multiplicative_split_defgrad_elasthyper_test.cpp index 3840c0be331..d49a344a3df 100644 --- a/unittests/mat/4C_multiplicative_split_defgrad_elasthyper_test.cpp +++ b/unittests/mat/4C_multiplicative_split_defgrad_elasthyper_test.cpp @@ -9,9 +9,11 @@ #include "4C_global_data.hpp" #include "4C_linalg_fixedsizematrix.hpp" +#include "4C_linalg_symmetric_tensor.hpp" #include "4C_mat_elasthyper_service.hpp" #include "4C_mat_material_factory.hpp" #include "4C_mat_multiplicative_split_defgrad_elasthyper.hpp" +#include "4C_mat_multiplicative_split_defgrad_elasthyper_service.hpp" #include "4C_mat_par_bundle.hpp" #include "4C_material_parameter_base.hpp" #include "4C_ssi_input.hpp" @@ -121,6 +123,8 @@ namespace std::vector inelastic_defgrad_factor_ids = {inelastic_defgrad_id}; multiplicativeSplitDefgradData.add("INELDEFGRADFACIDS", inelastic_defgrad_factor_ids); multiplicativeSplitDefgradData.add("DENS", 1.32e1); + multiplicativeSplitDefgradData.add("REF_TEMPERATURE", 293.0); + multiplicativeSplitDefgradData.add("THERMAL_EXPANSION_COEFFICIENT", 0.1); // get pointer to parameter class parameters_multiplicative_split_defgrad_ = @@ -547,8 +551,9 @@ namespace stress_fact.gamma = gamma_ref_; stress_fact.delta = delta_ref_; + const Core::LinAlg::SymmetricTensor ST{}; // no stress due to thermal expansion Core::LinAlg::Matrix<6, 9> dSdiFin = - multiplicative_split_defgrad_->evaluated_sdi_fin(kinemat_quant, stress_fact); + multiplicative_split_defgrad_->evaluate_d_stress_d_ifin(kinemat_quant, stress_fact, ST); FOUR_C_EXPECT_NEAR(dSdiFin, dSdiFin_ref_, 1.0e-10); } @@ -624,7 +629,7 @@ namespace // do the actual call that is tested auto source(Mat::PAR::InelasticSource::concentration); - Core::LinAlg::Matrix<6, 1> dSdx(Core::LinAlg::Initialization::zero); + // reference solution Core::LinAlg::Matrix<6, 1> dSdx_ref; dSdx_ref(0) = -1.907155639254611e-05; @@ -634,7 +639,8 @@ namespace dSdx_ref(4) = 1.08343997650926e-06; dSdx_ref(5) = 1.949130554546719e-06; - multiplicative_split_defgrad_->evaluate_od_stiff_mat(source, &FM_, dSdiFin_ref_, dSdx); + Core::LinAlg::Matrix<6, 1> dSdx = + multiplicative_split_defgrad_->evaluate_od_stiff_mat(source, &FM_, dSdiFin_ref_); FOUR_C_EXPECT_NEAR(dSdx, dSdx_ref, 1.0e-10); } From ef58ce679f22b33babd9a86ff4e450cfafaeaab7 Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Thu, 18 Jun 2026 16:36:10 +0200 Subject: [PATCH 20/28] Remove anisotropy back-reference from extensions Instead pass Anisotropy& through the setup callbacks. --- src/mat/4C_mat_anisotropy.cpp | 9 ++--- src/mat/4C_mat_anisotropy_extension.cpp | 6 +-- src/mat/4C_mat_anisotropy_extension.hpp | 25 ++++++++----- src/mat/4C_mat_anisotropy_extension_base.cpp | 21 ----------- src/mat/4C_mat_anisotropy_extension_base.hpp | 37 +++---------------- ...mat_anisotropy_extension_cylinder_cosy.cpp | 27 ++++++++++---- ...mat_anisotropy_extension_cylinder_cosy.hpp | 19 +++++++--- .../4C_mat_anisotropy_extension_default.cpp | 23 ++++++------ .../4C_mat_anisotropy_extension_default.hpp | 4 +- .../elast/4C_mat_elast_coupanisoexposhear.cpp | 36 +++++++++--------- .../elast/4C_mat_elast_coupanisoexposhear.hpp | 6 +-- 11 files changed, 97 insertions(+), 116 deletions(-) delete mode 100644 src/mat/4C_mat_anisotropy_extension_base.cpp diff --git a/src/mat/4C_mat_anisotropy.cpp b/src/mat/4C_mat_anisotropy.cpp index fa09f0d5a4a..ef09b695d1c 100644 --- a/src/mat/4C_mat_anisotropy.cpp +++ b/src/mat/4C_mat_anisotropy.cpp @@ -227,7 +227,6 @@ const Core::LinAlg::Tensor& Mat::Anisotropy::get_gauss_point_fiber( void Mat::Anisotropy::register_anisotropy_extension(BaseAnisotropyExtension& extension) { extensions_.emplace_back(Core::Utils::shared_ptr_from_ref(extension)); - extension.set_anisotropy(*this); } void Mat::Anisotropy::on_element_fibers_initialized() @@ -235,14 +234,14 @@ void Mat::Anisotropy::on_element_fibers_initialized() element_fibers_initialized_ = true; for (auto& extension : extensions_) { - extension->on_global_element_data_initialized(); + extension->on_global_element_data_initialized(*this); } if (element_fibers_initialized_ and gp_fibers_initialized_) { for (auto& extension : extensions_) { - extension->on_global_data_initialized(); + extension->on_global_data_initialized(*this); } } } @@ -252,14 +251,14 @@ void Mat::Anisotropy::on_gp_fibers_initialized() gp_fibers_initialized_ = true; for (auto& extension : extensions_) { - extension->on_global_gp_data_initialized(); + extension->on_global_gp_data_initialized(*this); } if (element_fibers_initialized_ and gp_fibers_initialized_) { for (auto& extension : extensions_) { - extension->on_global_data_initialized(); + extension->on_global_data_initialized(*this); } } } diff --git a/src/mat/4C_mat_anisotropy_extension.cpp b/src/mat/4C_mat_anisotropy_extension.cpp index c9d0b36e4a7..19b9bda5af5 100644 --- a/src/mat/4C_mat_anisotropy_extension.cpp +++ b/src/mat/4C_mat_anisotropy_extension.cpp @@ -37,11 +37,11 @@ template void Mat::FiberAnisotropyExtension::set_fibers( int gp, const std::array, numfib>& fibers) { - if (gp >= get_anisotropy()->get_number_of_gauss_points()) + if (gp >= numgp_) { FOUR_C_THROW( "The current Gauss point {} is out of range of the expected number of Gauss points {}.", gp, - get_anisotropy()->get_number_of_gauss_points()); + numgp_); } if (fibers_.empty()) @@ -171,7 +171,7 @@ int Mat::FiberAnisotropyExtension::get_fibers_per_element() const return 1; } - return get_anisotropy()->get_number_of_gauss_points(); + return numgp_; } // explicit instantiations of template classes diff --git a/src/mat/4C_mat_anisotropy_extension.hpp b/src/mat/4C_mat_anisotropy_extension.hpp index 857e9bf2aed..82a0f3f864f 100644 --- a/src/mat/4C_mat_anisotropy_extension.hpp +++ b/src/mat/4C_mat_anisotropy_extension.hpp @@ -58,9 +58,6 @@ namespace Mat template class FiberAnisotropyExtension : public BaseAnisotropyExtension, public FiberProvider { - // Anisotropy is a friend to create back reference - friend class Anisotropy; - public: //! @name Tensors needed for the evaluation /// @{ @@ -193,7 +190,7 @@ namespace Mat * \return true if the fibers are initialized * \return false if the fibers are not initialized */ - virtual bool do_element_fiber_initialization() { return false; } + virtual bool do_element_fiber_initialization(Anisotropy& anisotropy) { return false; } /*! * \brief Method that initialized Gauss point fibers. @@ -203,7 +200,7 @@ namespace Mat * \return true if the fibers are initialized * \return false if the fibers are not initialized */ - virtual bool do_gp_fiber_initialization() { return false; } + virtual bool do_gp_fiber_initialization(Anisotropy& anisotropy) { return false; } /*! * \brief Method that will be called of the fibers are initialized. @@ -231,16 +228,20 @@ namespace Mat * \brief This method will be called by Mat::Anisotropy if element and Gauss point fibers are * available */ - void on_global_data_initialized() override {} + void on_global_data_initialized(Anisotropy& anisotropy) override + { + numgp_ = anisotropy.get_number_of_gauss_points(); + } private: /*! * \brief This method will be called by Mat::Anisotropy to notify that element information is * available. */ - void on_global_element_data_initialized() override + void on_global_element_data_initialized(Anisotropy& anisotropy) override { - const bool initialized = do_element_fiber_initialization(); + numgp_ = anisotropy.get_number_of_gauss_points(); + const bool initialized = do_element_fiber_initialization(anisotropy); if (initialized) on_fibers_initialized(); } @@ -248,9 +249,10 @@ namespace Mat * \brief This method will be called by Mat::Anisotropy to notify that Gauss point information * is available. */ - void on_global_gp_data_initialized() override + void on_global_gp_data_initialized(Anisotropy& anisotropy) override { - const bool initialized = do_gp_fiber_initialization(); + numgp_ = anisotropy.get_number_of_gauss_points(); + const bool initialized = do_gp_fiber_initialization(anisotropy); if (initialized) on_fibers_initialized(); } /// \} @@ -266,6 +268,9 @@ namespace Mat */ void compute_structural_tensors_stress(); + /// Number of Gauss points supplied by the Anisotropy class during setup + int numgp_ = 0; + /// Indication of the fiber location FiberLocation fiber_location_ = FiberLocation::None; diff --git a/src/mat/4C_mat_anisotropy_extension_base.cpp b/src/mat/4C_mat_anisotropy_extension_base.cpp deleted file mode 100644 index 564fee17f99..00000000000 --- a/src/mat/4C_mat_anisotropy_extension_base.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of 4C multiphysics licensed under the -// GNU Lesser General Public License v3.0 or later. -// -// See the LICENSE.md file in the top-level for license information. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include "4C_mat_anisotropy_extension_base.hpp" - -#include "4C_comm_pack_helpers.hpp" -#include "4C_mat_anisotropy.hpp" -#include "4C_utils_shared_ptr_from_ref.hpp" - -FOUR_C_NAMESPACE_OPEN - -void Mat::BaseAnisotropyExtension::set_anisotropy(Mat::Anisotropy& anisotropy) -{ - anisotropy_ = Core::Utils::shared_ptr_from_ref(anisotropy); -} - -FOUR_C_NAMESPACE_CLOSE diff --git a/src/mat/4C_mat_anisotropy_extension_base.hpp b/src/mat/4C_mat_anisotropy_extension_base.hpp index 349a21b8f5f..782d0387d96 100644 --- a/src/mat/4C_mat_anisotropy_extension_base.hpp +++ b/src/mat/4C_mat_anisotropy_extension_base.hpp @@ -10,7 +10,6 @@ #include "4C_config.hpp" -#include #include FOUR_C_NAMESPACE_OPEN @@ -28,7 +27,8 @@ namespace Mat class BaseAnisotropyExtension { - // Anisotropy is a friend to create back reference + // Anisotropy calls the private notification methods on_global_element_data_initialized + // and on_global_gp_data_initialized. friend class Anisotropy; public: @@ -57,48 +57,21 @@ namespace Mat * \brief This method will be called by Mat::Anisotropy if element and Gauss point fibers are * available */ - virtual void on_global_data_initialized() = 0; - - protected: - /*! - * \brief Returns the reference to the anisotropy - * - * \return std::shared_ptr& Reference to the anisotropy - */ - std::shared_ptr& get_anisotropy() { return anisotropy_; } - /*! - * \brief Returns the reference to the anisotropy - * - * \return std::shared_ptr& Reference to the anisotropy - */ - const std::shared_ptr& get_anisotropy() const { return anisotropy_; } + virtual void on_global_data_initialized(Anisotropy& anisotropy) = 0; private: /*! * \brief This method will be called by Mat::Anisotropy to notify that element information is * available. */ - virtual void on_global_element_data_initialized() = 0; + virtual void on_global_element_data_initialized(Anisotropy& anisotropy) = 0; /*! * \brief This method will be called by Mat::Anisotropy to notify that Gauss point information * is available. */ - virtual void on_global_gp_data_initialized() = 0; - - /// \name Private methods called by the friend class Mat::Anisotropy - /// \{ - /*! - * \brief Set the anisotropy. This method will only be used by Anisotropy itself to give the - * extension access to all anisotropy information. - * - * \param anisotropy - */ - void set_anisotropy(Anisotropy& anisotropy); - - /// Reference to Anisotropy - std::shared_ptr anisotropy_; + virtual void on_global_gp_data_initialized(Anisotropy& anisotropy) = 0; }; } // namespace Mat FOUR_C_NAMESPACE_CLOSE diff --git a/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.cpp b/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.cpp index 8ba4a85a9cd..dc51ae2487c 100644 --- a/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.cpp +++ b/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.cpp @@ -24,23 +24,34 @@ void Mat::CylinderCoordinateSystemAnisotropyExtension::pack_anisotropy( Core::Communication::PackBuffer& data) const { add_to_pack(data, cosy_location_); + add_to_pack(data, element_cosy_); + add_to_pack(data, gp_cosy_); } void Mat::CylinderCoordinateSystemAnisotropyExtension::unpack_anisotropy( Core::Communication::UnpackBuffer& buffer) { extract_from_pack(buffer, cosy_location_); + extract_from_pack(buffer, element_cosy_); + extract_from_pack(buffer, gp_cosy_); } -void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_data_initialized() +void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_data_initialized( + Mat::Anisotropy& anisotropy) { - if (get_anisotropy()->has_gp_cylinder_coordinate_system()) + if (anisotropy.has_gp_cylinder_coordinate_system()) { cosy_location_ = CosyLocation::GPCosy; + gp_cosy_.clear(); + for (int gp = 0; gp < anisotropy.get_number_of_gauss_points(); ++gp) + { + gp_cosy_.push_back(anisotropy.get_gp_cylinder_coordinate_system(gp)); + } } - else if (get_anisotropy()->has_element_cylinder_coordinate_system()) + else if (anisotropy.has_element_cylinder_coordinate_system()) { cosy_location_ = CosyLocation::ElementCosy; + element_cosy_ = anisotropy.get_element_cylinder_coordinate_system(); } else { @@ -48,12 +59,14 @@ void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_data_initialize } } -void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_element_data_initialized() +void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_element_data_initialized( + Mat::Anisotropy& anisotropy) { // do nothing } -void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_gp_data_initialized() +void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_gp_data_initialized( + Mat::Anisotropy& anisotropy) { // do nothing } @@ -68,10 +81,10 @@ Mat::CylinderCoordinateSystemAnisotropyExtension::get_cylinder_coordinate_system if (cosy_location_ == CosyLocation::ElementCosy) { - return get_anisotropy()->get_element_cylinder_coordinate_system(); + return *element_cosy_; } - return get_anisotropy()->get_gp_cylinder_coordinate_system(gp); + return gp_cosy_.at(gp); } std::shared_ptr diff --git a/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.hpp b/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.hpp index 4ddd4398edd..b6e677594ad 100644 --- a/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.hpp +++ b/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.hpp @@ -10,9 +10,10 @@ #include "4C_config.hpp" +#include "4C_mat_anisotropy_cylinder_coordinate_system_manager.hpp" #include "4C_mat_anisotropy_extension_base.hpp" - +#include FOUR_C_NAMESPACE_OPEN @@ -66,7 +67,7 @@ namespace Mat * \brief This method will be called by Mat::Anisotropy if element and Gauss point fibers are * available */ - void on_global_data_initialized() override; + void on_global_data_initialized(Anisotropy& anisotropy) override; /*! * \brief Returns the cylinder coordinate system for a specific Gausspoint. @@ -87,19 +88,27 @@ namespace Mat * \brief This method will be called by Mat::Anisotropy to notify that element information is * available. */ - void on_global_element_data_initialized() override; + void on_global_element_data_initialized(Anisotropy& anisotropy) override; /*! * \brief This method will be called by Mat::Anisotropy to notify that Gauss point information * is available. */ - void on_global_gp_data_initialized() override; + void on_global_gp_data_initialized(Anisotropy& anisotropy) override; /// flag where the coordinate system is located CosyLocation cosy_location_; + + /// element-level cylinder coordinate system manager supplied by the Anisotropy class during + /// setup + std::optional element_cosy_; + + /// Gauss-point-level cylinder coordinate system managers supplied by the Anisotropy class + /// during setup + std::vector gp_cosy_; }; } // namespace Mat FOUR_C_NAMESPACE_CLOSE -#endif \ No newline at end of file +#endif diff --git a/src/mat/4C_mat_anisotropy_extension_default.cpp b/src/mat/4C_mat_anisotropy_extension_default.cpp index 9a8425d7fe5..b0822d5afd0 100644 --- a/src/mat/4C_mat_anisotropy_extension_default.cpp +++ b/src/mat/4C_mat_anisotropy_extension_default.cpp @@ -146,7 +146,8 @@ void Mat::DefaultAnisotropyExtension::set_fiber_vecs( } template -bool Mat::DefaultAnisotropyExtension::do_element_fiber_initialization() +bool Mat::DefaultAnisotropyExtension::do_element_fiber_initialization( + Mat::Anisotropy& anisotropy) { switch (init_mode_) { @@ -156,25 +157,24 @@ bool Mat::DefaultAnisotropyExtension::do_element_fiber_initialization() case INIT_MODE_ELEMENT_FIBERS: // check, whether a coordinate system is given - if (this->get_anisotropy()->has_element_cylinder_coordinate_system()) + if (anisotropy.has_element_cylinder_coordinate_system()) { // initialize fiber vector with local coordinate system Core::LinAlg::Tensor locsys{}; const Core::LinAlg::Tensor Id = Core::LinAlg::get_full(Core::LinAlg::TensorGenerators::identity); - this->get_anisotropy() - ->get_element_cylinder_coordinate_system() - .evaluate_local_coordinate_system(locsys); + anisotropy.get_element_cylinder_coordinate_system().evaluate_local_coordinate_system( + locsys); this->set_fiber_vecs(-1.0, locsys, Id); } - else if (this->get_anisotropy()->get_number_of_element_fibers() > 0) + else if (anisotropy.get_number_of_element_fibers() > 0) { // initialize fibers from global given fibers std::array, numfib> fibers; for (unsigned int i = 0; i < numfib; ++i) { - fibers[i] = this->get_anisotropy()->get_element_fibers().at(fiber_ids_.at(i)); + fibers[i] = anisotropy.get_element_fibers().at(fiber_ids_.at(i)); } this->set_fibers(BaseAnisotropyExtension::GPDEFAULT, fibers); } @@ -190,7 +190,8 @@ bool Mat::DefaultAnisotropyExtension::do_element_fiber_initialization() } template -bool Mat::DefaultAnisotropyExtension::do_gp_fiber_initialization() +bool Mat::DefaultAnisotropyExtension::do_gp_fiber_initialization( + Mat::Anisotropy& anisotropy) { switch (init_mode_) { @@ -200,17 +201,17 @@ bool Mat::DefaultAnisotropyExtension::do_gp_fiber_initialization() case INIT_MODE_NODAL_FIBERS: // check, whether a coordinate system is given - if (this->get_anisotropy()->has_gp_cylinder_coordinate_system()) + if (anisotropy.has_gp_cylinder_coordinate_system()) { FOUR_C_THROW( "Gauss-point fibers defined via Gauss-point cylinder coordinate systems is not yet " "defined"); } - else if (this->get_anisotropy()->get_number_of_gauss_point_fibers() > 0) + else if (anisotropy.get_number_of_gauss_point_fibers() > 0) { // initialize fibers from global given fibers int gp = 0; - for (const auto& fiberList : this->get_anisotropy()->get_gauss_point_fibers()) + for (const auto& fiberList : anisotropy.get_gauss_point_fibers()) { std::array, numfib> fibers; diff --git a/src/mat/4C_mat_anisotropy_extension_default.hpp b/src/mat/4C_mat_anisotropy_extension_default.hpp index 423552aad00..de75e58b97f 100644 --- a/src/mat/4C_mat_anisotropy_extension_default.hpp +++ b/src/mat/4C_mat_anisotropy_extension_default.hpp @@ -74,7 +74,7 @@ namespace Mat * \return true if the material is parametrized so that element fibers should be used * \return false otherwise */ - bool do_element_fiber_initialization() override; + bool do_element_fiber_initialization(Anisotropy& anisotropy) override; /*! * \brief Initializes Gauss point fibers @@ -82,7 +82,7 @@ namespace Mat * \return true if the materials is parametrized so that Gauss point fibers should be used * \return false otherwise */ - bool do_gp_fiber_initialization() override; + bool do_gp_fiber_initialization(Anisotropy& anisotropy) override; /*! * \brief Set Fiber vectors by a new angle gamma in the current configuration diff --git a/src/mat/elast/4C_mat_elast_coupanisoexposhear.cpp b/src/mat/elast/4C_mat_elast_coupanisoexposhear.cpp index ed51136e522..25c6b916f46 100644 --- a/src/mat/elast/4C_mat_elast_coupanisoexposhear.cpp +++ b/src/mat/elast/4C_mat_elast_coupanisoexposhear.cpp @@ -69,12 +69,14 @@ Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::get_structural_tensor(int g return structural_tensors_[gp]; } -void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_data_initialized() +void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_data_initialized( + Mat::Anisotropy& anisotropy) { // do nothing } -void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_element_data_initialized() +void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_element_data_initialized( + Mat::Anisotropy& anisotropy) { if (init_mode_ == DefaultAnisotropyExtension<2>::INIT_MODE_NODAL_EXTERNAL || init_mode_ == DefaultAnisotropyExtension<2>::INIT_MODE_NODAL_FIBERS) @@ -92,19 +94,18 @@ void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_element_data DefaultAnisotropyExtension<2>::INIT_MODE_NODAL_FIBERS); } - if (get_anisotropy()->get_element_fibers().empty()) + if (anisotropy.get_element_fibers().empty()) { FOUR_C_THROW("No element fibers are given with the FIBER1 FIBER2 notation"); } scalar_products_.resize(1); structural_tensors_.resize(1); - scalar_products_[0] = get_anisotropy()->get_element_fiber(fiber_ids_[0]) * - get_anisotropy()->get_element_fiber(fiber_ids_[1]); + scalar_products_[0] = + anisotropy.get_element_fiber(fiber_ids_[0]) * anisotropy.get_element_fiber(fiber_ids_[1]); - Core::LinAlg::Tensor fiber1fiber2T = - Core::LinAlg::dyadic(get_anisotropy()->get_element_fiber(fiber_ids_[0]), - get_anisotropy()->get_element_fiber(fiber_ids_[1])); + Core::LinAlg::Tensor fiber1fiber2T = Core::LinAlg::dyadic( + anisotropy.get_element_fiber(fiber_ids_[0]), anisotropy.get_element_fiber(fiber_ids_[1])); structural_tensors_[0] = 0.5 * Core::LinAlg::assume_symmetry(fiber1fiber2T + Core::LinAlg::transpose(fiber1fiber2T)); @@ -112,7 +113,8 @@ void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_element_data is_initialized_ = true; } -void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_gp_data_initialized() +void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_gp_data_initialized( + Mat::Anisotropy& anisotropy) { if (init_mode_ == DefaultAnisotropyExtension<2>::INIT_MODE_ELEMENT_EXTERNAL || init_mode_ == DefaultAnisotropyExtension<2>::INIT_MODE_ELEMENT_FIBERS) @@ -130,22 +132,22 @@ void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_gp_data_init DefaultAnisotropyExtension<2>::INIT_MODE_NODAL_FIBERS); } - if (get_anisotropy()->get_number_of_gauss_point_fibers() == 0) + if (anisotropy.get_number_of_gauss_point_fibers() == 0) { FOUR_C_THROW("No element fibers are given with the FIBER1 FIBER2 notation"); } - scalar_products_.resize(get_anisotropy()->get_number_of_gauss_points()); - structural_tensors_.resize(get_anisotropy()->get_number_of_gauss_points()); + scalar_products_.resize(anisotropy.get_number_of_gauss_points()); + structural_tensors_.resize(anisotropy.get_number_of_gauss_points()); - for (auto gp = 0; gp < get_anisotropy()->get_number_of_gauss_points(); ++gp) + for (auto gp = 0; gp < anisotropy.get_number_of_gauss_points(); ++gp) { - scalar_products_[gp] = get_anisotropy()->get_gauss_point_fiber(gp, fiber_ids_[0]) * - get_anisotropy()->get_gauss_point_fiber(gp, fiber_ids_[1]); + scalar_products_[gp] = anisotropy.get_gauss_point_fiber(gp, fiber_ids_[0]) * + anisotropy.get_gauss_point_fiber(gp, fiber_ids_[1]); Core::LinAlg::Tensor fiber1fiber2T = - Core::LinAlg::dyadic(get_anisotropy()->get_gauss_point_fiber(gp, fiber_ids_[0]), - get_anisotropy()->get_gauss_point_fiber(gp, fiber_ids_[1])); + Core::LinAlg::dyadic(anisotropy.get_gauss_point_fiber(gp, fiber_ids_[0]), + anisotropy.get_gauss_point_fiber(gp, fiber_ids_[1])); structural_tensors_[gp] = 0.5 * Core::LinAlg::assume_symmetry(fiber1fiber2T + Core::LinAlg::transpose(fiber1fiber2T)); diff --git a/src/mat/elast/4C_mat_elast_coupanisoexposhear.hpp b/src/mat/elast/4C_mat_elast_coupanisoexposhear.hpp index c77a8ce6e26..1a6ef72026b 100644 --- a/src/mat/elast/4C_mat_elast_coupanisoexposhear.hpp +++ b/src/mat/elast/4C_mat_elast_coupanisoexposhear.hpp @@ -55,11 +55,11 @@ namespace Mat * * The coupling structural tensor and the scalar product will be computed here */ - void on_global_data_initialized() override; + void on_global_data_initialized(Anisotropy& anisotropy) override; protected: - void on_global_element_data_initialized() override; - void on_global_gp_data_initialized() override; + void on_global_element_data_initialized(Anisotropy& anisotropy) override; + void on_global_gp_data_initialized(Anisotropy& anisotropy) override; private: /** From 6adaf4a3c3fbac832491053eea7c63c01e9f9035 Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Thu, 18 Jun 2026 16:38:14 +0200 Subject: [PATCH 21/28] Store anisotropy by value in all materials --- ...t_multiplicative_split_defgrad_elasthyper.cpp | 16 ++++++++-------- ...t_multiplicative_split_defgrad_elasthyper.hpp | 4 +++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp index 880fc4c173e..2c19630928a 100644 --- a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp +++ b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp @@ -88,7 +88,7 @@ Core::Communication::ParObject* Mat::MultiplicativeSplitDefgradElastHyperType::c /*--------------------------------------------------------------------* *--------------------------------------------------------------------*/ Mat::MultiplicativeSplitDefgradElastHyper::MultiplicativeSplitDefgradElastHyper() - : anisotropy_(std::make_shared()), + : anisotropy_(), inelastic_(std::make_shared()), params_(nullptr), potsumel_(0), @@ -100,7 +100,7 @@ Mat::MultiplicativeSplitDefgradElastHyper::MultiplicativeSplitDefgradElastHyper( *--------------------------------------------------------------------*/ Mat::MultiplicativeSplitDefgradElastHyper::MultiplicativeSplitDefgradElastHyper( Mat::PAR::MultiplicativeSplitDefgradElastHyper* params) - : anisotropy_(std::make_shared()), + : anisotropy_(), inelastic_(std::make_shared()), params_(params), potsumel_(0), @@ -120,7 +120,7 @@ Mat::MultiplicativeSplitDefgradElastHyper::MultiplicativeSplitDefgradElastHyper( { potsumel_.push_back(elastic_summand); } - elastic_summand->register_anisotropy_extensions(*anisotropy_); + elastic_summand->register_anisotropy_extensions(anisotropy_); } inelastic_->assign_to_source(params); @@ -138,7 +138,7 @@ void Mat::MultiplicativeSplitDefgradElastHyper::pack(Core::Communication::PackBu if (params_ != nullptr) matid = params_->id(); // in case we are in post-process mode add_to_pack(data, matid); - anisotropy_->pack_anisotropy(data); + anisotropy_.pack_anisotropy(data); Core::Communication::PotentiallyUnusedBufferScope summand_scope{data}; if (params_ != nullptr) // summands are not accessible in postprocessing mode @@ -183,7 +183,7 @@ void Mat::MultiplicativeSplitDefgradElastHyper::unpack(Core::Communication::Unpa } } - anisotropy_->unpack_anisotropy(buffer); + anisotropy_.unpack_anisotropy(buffer); Core::Communication::PotentiallyUnusedBufferScope summand_scope{buffer}; if (params_ != nullptr) // summands are not accessible in postprocessing mode @@ -211,7 +211,7 @@ void Mat::MultiplicativeSplitDefgradElastHyper::unpack(Core::Communication::Unpa for (const auto& elastic_summand : potsumel_) { elastic_summand->unpack_summand(buffer); - elastic_summand->register_anisotropy_extensions(*anisotropy_); + elastic_summand->register_anisotropy_extensions(anisotropy_); } for (const std::shared_ptr& elastic_summand : potsumel_transviso_) @@ -1015,8 +1015,8 @@ void Mat::MultiplicativeSplitDefgradElastHyper::setup(const int numgp, const std::optional& coord_system) { // Read anisotropy - anisotropy_->set_number_of_gauss_points(numgp); - anisotropy_->read_anisotropy_from_element(fibers, coord_system); + anisotropy_.set_number_of_gauss_points(numgp); + anisotropy_.read_anisotropy_from_element(fibers, coord_system); // elastic materials for (const auto& summand : potsumel_) summand->setup(numgp, fibers, coord_system); diff --git a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp index 19f9a5821dc..91f77626910 100644 --- a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp +++ b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp @@ -24,6 +24,8 @@ #include +#include + FOUR_C_NAMESPACE_OPEN @@ -583,7 +585,7 @@ namespace Mat private: /// Holder for anisotropy - std::shared_ptr anisotropy_; + Anisotropy anisotropy_; /// Holds and classifies all inelastic factors std::shared_ptr inelastic_; From c5bdb8086b45a8e67c51ec417e3b3b228e860a1e Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Thu, 18 Jun 2026 16:38:30 +0200 Subject: [PATCH 22/28] Remove empty lines in mixture --- src/mat/4C_mat_mixture.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mat/4C_mat_mixture.cpp b/src/mat/4C_mat_mixture.cpp index e1c75eb0c65..735b43ada85 100644 --- a/src/mat/4C_mat_mixture.cpp +++ b/src/mat/4C_mat_mixture.cpp @@ -133,8 +133,6 @@ void Mat::Mixture::unpack(Core::Communication::UnpackBuffer& buffer) constituents_->clear(); setup_ = false; - - Core::Communication::extract_and_assert_id(buffer, unique_par_object_id()); // matid and recover params_ @@ -161,7 +159,6 @@ void Mat::Mixture::unpack(Core::Communication::UnpackBuffer& buffer) // Extract setup flag extract_from_pack(buffer, setup_); - // Extract is isPreEvaluated std::vector isPreEvaluatedInt; extract_from_pack(buffer, isPreEvaluatedInt); From 30882d006ec54666282b3787b1c0504cc02f1ea1 Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Fri, 19 Jun 2026 18:02:17 +0200 Subject: [PATCH 23/28] Clear anisotropy extensions in anisotropy unpack to prevent dangling pointers when extensions re-register --- src/mat/4C_mat_anisotropy.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mat/4C_mat_anisotropy.cpp b/src/mat/4C_mat_anisotropy.cpp index ef09b695d1c..3d0da62b332 100644 --- a/src/mat/4C_mat_anisotropy.cpp +++ b/src/mat/4C_mat_anisotropy.cpp @@ -57,6 +57,10 @@ void Mat::Anisotropy::pack_anisotropy(Core::Communication::PackBuffer& data) con void Mat::Anisotropy::unpack_anisotropy(Core::Communication::UnpackBuffer& buffer) { + // Extensions are external references that are not packed. The summands that own them + // may be recreated during unpack, so clear the stale references before re-registration. + extensions_.clear(); + extract_from_pack(buffer, numgp_); extract_from_pack(buffer, element_fibers_initialized_); extract_from_pack(buffer, gp_fibers_initialized_); From ef763293678ff27e7c24f94508102930a471eec9 Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Mon, 22 Jun 2026 09:55:59 +0200 Subject: [PATCH 24/28] Pack/unpack numgp_ in FiberAnisotropyExtension --- src/mat/4C_mat_anisotropy_extension.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mat/4C_mat_anisotropy_extension.cpp b/src/mat/4C_mat_anisotropy_extension.cpp index 19b9bda5af5..e38e3c12e42 100644 --- a/src/mat/4C_mat_anisotropy_extension.cpp +++ b/src/mat/4C_mat_anisotropy_extension.cpp @@ -130,6 +130,7 @@ template void Mat::FiberAnisotropyExtension::pack_anisotropy( Core::Communication::PackBuffer& data) const { + add_to_pack(data, numgp_); add_to_pack(data, fibers_); add_to_pack(data, fiber_structural_tensors_); add_to_pack(data, tensor_flags_); @@ -140,6 +141,7 @@ template void Mat::FiberAnisotropyExtension::unpack_anisotropy( Core::Communication::UnpackBuffer& buffer) { + extract_from_pack(buffer, numgp_); extract_from_pack(buffer, fibers_); extract_from_pack(buffer, fiber_structural_tensors_); extract_from_pack(buffer, tensor_flags_); From 1fee01acea80a61daa5a4640c4437fce303afd94 Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Tue, 23 Jun 2026 15:17:14 +0200 Subject: [PATCH 25/28] Initialize numgp_ to -1 --- src/mat/4C_mat_anisotropy_extension.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mat/4C_mat_anisotropy_extension.hpp b/src/mat/4C_mat_anisotropy_extension.hpp index 82a0f3f864f..440d9879a67 100644 --- a/src/mat/4C_mat_anisotropy_extension.hpp +++ b/src/mat/4C_mat_anisotropy_extension.hpp @@ -269,7 +269,7 @@ namespace Mat void compute_structural_tensors_stress(); /// Number of Gauss points supplied by the Anisotropy class during setup - int numgp_ = 0; + int numgp_ = -1; /// Indication of the fiber location FiberLocation fiber_location_ = FiberLocation::None; From 8009b0e9a35cde2b7aec601df1bbe6158b1a8762 Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Tue, 23 Jun 2026 15:18:20 +0200 Subject: [PATCH 26/28] Minor fixes in anisotropy framework --- src/mat/4C_mat_anisotropy_extension.hpp | 4 ++-- src/mat/4C_mat_anisotropy_extension_cylinder_cosy.cpp | 9 +++++++-- src/mat/4C_mat_anisotropy_extension_cylinder_cosy.hpp | 7 +++++-- .../4C_mat_multiplicative_split_defgrad_elasthyper.hpp | 3 +-- src/mat/elast/4C_mat_elast_coupanisoexposhear.cpp | 4 ++-- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/mat/4C_mat_anisotropy_extension.hpp b/src/mat/4C_mat_anisotropy_extension.hpp index 440d9879a67..6c8e30ed90e 100644 --- a/src/mat/4C_mat_anisotropy_extension.hpp +++ b/src/mat/4C_mat_anisotropy_extension.hpp @@ -190,7 +190,7 @@ namespace Mat * \return true if the fibers are initialized * \return false if the fibers are not initialized */ - virtual bool do_element_fiber_initialization(Anisotropy& anisotropy) { return false; } + virtual bool do_element_fiber_initialization(Anisotropy& /*anisotropy*/) { return false; } /*! * \brief Method that initialized Gauss point fibers. @@ -200,7 +200,7 @@ namespace Mat * \return true if the fibers are initialized * \return false if the fibers are not initialized */ - virtual bool do_gp_fiber_initialization(Anisotropy& anisotropy) { return false; } + virtual bool do_gp_fiber_initialization(Anisotropy& /*anisotropy*/) { return false; } /*! * \brief Method that will be called of the fibers are initialized. diff --git a/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.cpp b/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.cpp index dc51ae2487c..0d6dc6cfce4 100644 --- a/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.cpp +++ b/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.cpp @@ -11,6 +11,7 @@ #include "4C_comm_parobject.hpp" #include "4C_mat_anisotropy.hpp" #include "4C_mat_anisotropy_coordinate_system_provider.hpp" +#include "4C_utils_exceptions.hpp" #include "4C_utils_shared_ptr_from_ref.hpp" FOUR_C_NAMESPACE_OPEN @@ -62,13 +63,13 @@ void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_data_initialize void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_element_data_initialized( Mat::Anisotropy& anisotropy) { - // do nothing + (void)anisotropy; } void Mat::CylinderCoordinateSystemAnisotropyExtension::on_global_gp_data_initialized( Mat::Anisotropy& anisotropy) { - // do nothing + (void)anisotropy; } const Mat::CylinderCoordinateSystemProvider& @@ -81,6 +82,10 @@ Mat::CylinderCoordinateSystemAnisotropyExtension::get_cylinder_coordinate_system if (cosy_location_ == CosyLocation::ElementCosy) { + FOUR_C_ASSERT(element_cosy_.has_value(), + "Invalid state: CosyLocation=ElementCosy, but element_cosy_ is empty. " + "Check initialization in on_global_data_initialized()."); + return *element_cosy_; } diff --git a/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.hpp b/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.hpp index b6e677594ad..7c245a6fefe 100644 --- a/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.hpp +++ b/src/mat/4C_mat_anisotropy_extension_cylinder_cosy.hpp @@ -13,6 +13,7 @@ #include "4C_mat_anisotropy_cylinder_coordinate_system_manager.hpp" #include "4C_mat_anisotropy_extension_base.hpp" +#include #include FOUR_C_NAMESPACE_OPEN @@ -79,9 +80,11 @@ namespace Mat * \return const CylinderCoordinateSystemProvider& Reference to the cylinder coordinate system * provider */ - const CylinderCoordinateSystemProvider& get_cylinder_coordinate_system(int gp) const; + [[nodiscard]] const CylinderCoordinateSystemProvider& get_cylinder_coordinate_system( + int gp) const; - std::shared_ptr get_coordinate_system_provider(int gp) const; + [[nodiscard]] std::shared_ptr get_coordinate_system_provider( + int gp) const; private: /*! diff --git a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp index 91f77626910..6edcd09b248 100644 --- a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp +++ b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.hpp @@ -22,9 +22,8 @@ #include "4C_material_parameter_base.hpp" #include "4C_utils_exceptions.hpp" -#include - #include +#include FOUR_C_NAMESPACE_OPEN diff --git a/src/mat/elast/4C_mat_elast_coupanisoexposhear.cpp b/src/mat/elast/4C_mat_elast_coupanisoexposhear.cpp index 25c6b916f46..479b2ff4ab0 100644 --- a/src/mat/elast/4C_mat_elast_coupanisoexposhear.cpp +++ b/src/mat/elast/4C_mat_elast_coupanisoexposhear.cpp @@ -72,7 +72,7 @@ Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::get_structural_tensor(int g void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_data_initialized( Mat::Anisotropy& anisotropy) { - // do nothing + (void)anisotropy; } void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_element_data_initialized( @@ -134,7 +134,7 @@ void Mat::Elastic::CoupAnisoExpoShearAnisotropyExtension::on_global_gp_data_init if (anisotropy.get_number_of_gauss_point_fibers() == 0) { - FOUR_C_THROW("No element fibers are given with the FIBER1 FIBER2 notation"); + FOUR_C_THROW("No Gauss-point fibers are given with the FIBER1 FIBER2 notation"); } scalar_products_.resize(anisotropy.get_number_of_gauss_points()); From a63db39577aed93d106d91c5390c056ba7d66721 Mon Sep 17 00:00:00 2001 From: Laura Engelhardt Date: Wed, 17 Jun 2026 15:53:30 +0200 Subject: [PATCH 27/28] Add 3D solid superposition material --- .../4C_legacy_enum_definitions_materials.cpp | 2 + .../4C_legacy_enum_definitions_materials.hpp | 1 + .../4C_global_legacy_module.cpp | 2 + ...4C_global_legacy_module_validmaterials.cpp | 20 ++ src/mat/4C_mat_material_factory.cpp | 5 + src/mat/4C_mat_solid_superposition.cpp | 190 +++++++++++++++ src/mat/4C_mat_solid_superposition.hpp | 161 +++++++++++++ .../mat_solid_superposition.4C.yaml | 185 ++++++++++++++ ...perposition_elasthyper_anisotropic.4C.yaml | 213 +++++++++++++++++ ..._superposition_mixture_anisotropic.4C.yaml | 225 ++++++++++++++++++ tests/list_of_tests.cmake | 6 + 11 files changed, 1010 insertions(+) create mode 100644 src/mat/4C_mat_solid_superposition.cpp create mode 100644 src/mat/4C_mat_solid_superposition.hpp create mode 100644 tests/input_files/mat_solid_superposition.4C.yaml create mode 100644 tests/input_files/mat_solid_superposition_elasthyper_anisotropic.4C.yaml create mode 100644 tests/input_files/mat_solid_superposition_mixture_anisotropic.4C.yaml diff --git a/src/core/legacy_enum_definitions/4C_legacy_enum_definitions_materials.cpp b/src/core/legacy_enum_definitions/4C_legacy_enum_definitions_materials.cpp index c12a9dd8be3..a342a8a6e74 100644 --- a/src/core/legacy_enum_definitions/4C_legacy_enum_definitions_materials.cpp +++ b/src/core/legacy_enum_definitions/4C_legacy_enum_definitions_materials.cpp @@ -105,6 +105,8 @@ std::string_view Core::Materials::to_string(Core::Materials::MaterialType materi return "MAT_Struct_ThermoPlasticLinElast"; case m_superelast: return "MAT_Struct_SuperElastSMA"; + case m_superposition: + return "MAT_Solid_Superposition"; case m_thermoplhyperelast: return "MAT_Struct_ThermoPlasticHyperElast"; case m_plnlnlogneohooke: diff --git a/src/core/legacy_enum_definitions/4C_legacy_enum_definitions_materials.hpp b/src/core/legacy_enum_definitions/4C_legacy_enum_definitions_materials.hpp index fe4008d14da..e3805640d7f 100644 --- a/src/core/legacy_enum_definitions/4C_legacy_enum_definitions_materials.hpp +++ b/src/core/legacy_enum_definitions/4C_legacy_enum_definitions_materials.hpp @@ -177,6 +177,7 @@ namespace Core::Materials m_structpororeaction, ///< wrapper material for poroelasticity (structure) m_structpororeactionECM, ///< wrapper material for poroelasticity (structure) m_superelast, ///< Superelastic material behaviour of shape memory alloys + m_superposition, ///< material for superposition of multiple materials m_stvenant, ///< St.Venant Kirchhoff material m_orthostvenant, ///< St.Venant Kirchhoff material with orthotropy m_sutherland, ///< material with temperature dependence according to Sutherland law diff --git a/src/global_legacy_module/4C_global_legacy_module.cpp b/src/global_legacy_module/4C_global_legacy_module.cpp index 3e1ca3dc422..2b40ba75b0b 100644 --- a/src/global_legacy_module/4C_global_legacy_module.cpp +++ b/src/global_legacy_module/4C_global_legacy_module.cpp @@ -92,6 +92,7 @@ #include "4C_mat_scatra_multiporo.hpp" #include "4C_mat_scatra_poro_ecm.hpp" #include "4C_mat_shell_kl.hpp" +#include "4C_mat_solid_superposition.hpp" #include "4C_mat_spring.hpp" #include "4C_mat_structporo.hpp" #include "4C_mat_structporo_reaction.hpp" @@ -243,6 +244,7 @@ namespace << Mat::StVenantKirchhoffType::instance().name() << " " << Mat::LinElast1DType::instance().name() << " " << Mat::LinElast1DGrowthType::instance().name() << " " + << Mat::SolidSuperpositionType::instance().name() << " " << Mat::SutherlandType::instance().name() << " " << Mat::ThermoStVenantKirchhoffType::instance().name() << " " << Mat::ThermoPlasticLinElastType::instance().name() << " " diff --git a/src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp b/src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp index 72bfed185c1..684ca47e0a5 100644 --- a/src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp +++ b/src/global_legacy_module/4C_global_legacy_module_validmaterials.cpp @@ -1293,6 +1293,26 @@ std::unordered_map Global::v {.description = "finite strain superelastic shape memory alloy"}); } + /*----------------------------------------------------------------------*/ + // 3D solid material superposition + { + using namespace Core::IO::InputSpecBuilders::Validators; + + known_materials[Core::Materials::m_superposition] = group("MAT_Solid_Superposition", + { + parameter>("MATIDS", + { + .description = "List of material IDs to be superimposed", + .validator = all_elements(positive()), + }), + parameter("DENS", {.description = "mass density of superposition material"}), + }, + {.description = + "3D solid material superposition. Each constituent material defined by " + "MATIDS is evaluated independently, and its responses are accumulated, " + "such that the stress S = sum_i S_i and the material tangent C = sum_i C_i"}); + } + /*----------------------------------------------------------------------*/ // Thermo-hyperelasticity / finite strain von-Mises plasticity { diff --git a/src/mat/4C_mat_material_factory.cpp b/src/mat/4C_mat_material_factory.cpp index 6e0924609c0..c9b20a9bdf8 100644 --- a/src/mat/4C_mat_material_factory.cpp +++ b/src/mat/4C_mat_material_factory.cpp @@ -129,6 +129,7 @@ #include "4C_mat_scatra_reaction.hpp" #include "4C_mat_scl.hpp" #include "4C_mat_shell_kl.hpp" +#include "4C_mat_solid_superposition.hpp" #include "4C_mat_soret.hpp" #include "4C_mat_spring.hpp" #include "4C_mat_structporo.hpp" @@ -1028,6 +1029,10 @@ std::unique_ptr Mat::make_parameter( { return make_parameter_impl(id, type, input_data); } + case Core::Materials::m_superposition: + { + return make_parameter_impl(id, type, input_data); + } case Core::Materials::m_linelast1D: { return make_parameter_impl(id, type, input_data); diff --git a/src/mat/4C_mat_solid_superposition.cpp b/src/mat/4C_mat_solid_superposition.cpp new file mode 100644 index 00000000000..69f3a1a7c23 --- /dev/null +++ b/src/mat/4C_mat_solid_superposition.cpp @@ -0,0 +1,190 @@ +// This file is part of 4C multiphysics licensed under the +// GNU Lesser General Public License v3.0 or later. +// +// See the LICENSE.md file in the top-level for license information. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "4C_mat_solid_superposition.hpp" + +#include "4C_comm_pack_helpers.hpp" +#include "4C_global_data.hpp" +#include "4C_mat_material_factory.hpp" +#include "4C_mat_par_bundle.hpp" +#include "4C_mat_service.hpp" +#include "4C_utils_exceptions.hpp" + +FOUR_C_NAMESPACE_OPEN + +Mat::PAR::SolidSuperposition::SolidSuperposition(const Core::Mat::PAR::Parameter::Data& matdata) + : Parameter(matdata), + density_(matdata.parameters.get("DENS")), + matids_(matdata.parameters.get>("MATIDS")) +{ +} + +std::shared_ptr Mat::PAR::SolidSuperposition::create_material() +{ + return std::make_shared(this); +} + +Mat::SolidSuperpositionType Mat::SolidSuperpositionType::instance_; + +Core::Communication::ParObject* Mat::SolidSuperpositionType::create( + Core::Communication::UnpackBuffer& buffer) +{ + auto* mat_solid_superposition = new Mat::SolidSuperposition(); + mat_solid_superposition->unpack(buffer); + + return mat_solid_superposition; +} + +Mat::SolidSuperposition::SolidSuperposition() : params_(nullptr), materials_(0) {} + +Mat::SolidSuperposition::SolidSuperposition(Mat::PAR::SolidSuperposition* params) + : params_(params), materials_(0) +{ + // create the materials from the given material ids + for (const auto& matid : params_->matids_) + { + auto mat = std::dynamic_pointer_cast(Mat::factory(matid)); + if (!mat) FOUR_C_THROW("Failed to allocate material for matid {}", matid); + + materials_.push_back(std::move(mat)); + } +} + +void Mat::SolidSuperposition::pack(Core::Communication::PackBuffer& data) const +{ + // pack type of this instance of ParObject + int type = unique_par_object_id(); + add_to_pack(data, type); + + // pack material id + int matid = -1; + if (params_ != nullptr) matid = params_->id(); // in case we are in post-process mode + add_to_pack(data, matid); + + // pack all materials + Core::Communication::PotentiallyUnusedBufferScope materials_scope{data}; + + if (params_ != nullptr) // materials are not accessible during post processing + { + for (const auto& m : materials_) m->pack(data); + } +} + +void Mat::SolidSuperposition::unpack(Core::Communication::UnpackBuffer& buffer) +{ + // make sure we have a pristine material + params_ = nullptr; + materials_.clear(); + + Core::Communication::extract_and_assert_id(buffer, unique_par_object_id()); + + // extract matid and recover params_ + int matid; + extract_from_pack(buffer, matid); + if (Global::Problem::instance()->materials() != nullptr) + { + if (Global::Problem::instance()->materials()->num() != 0) + { + const int probinst = Global::Problem::instance()->materials()->get_read_from_problem(); + Core::Mat::PAR::Parameter* mat = + Global::Problem::instance(probinst)->materials()->parameter_by_id(matid); + if (mat->type() == material_type()) + params_ = dynamic_cast(mat); + else + FOUR_C_THROW("Type of parameter material {} does not fit to calling type {}", mat->type(), + material_type()); + } + + // extract materials + Core::Communication::PotentiallyUnusedBufferScope materials_scope{buffer}; + + if (params_ != nullptr) // materials are not accessible during post processing + { + // recreate the materials from the given material ids + for (const auto& matid : params_->matids_) + { + auto mat = std::dynamic_pointer_cast(Mat::factory(matid)); + if (!mat) FOUR_C_THROW("Failed to allocate material for matid {}", matid); + + materials_.push_back(std::move(mat)); + } + + // unpack the materials + for (const auto& m : materials_) m->unpack(buffer); + } + } +} + +void Mat::SolidSuperposition::setup(int numgp, const Discret::Elements::Fibers& fibers, + const std::optional& coord_system) +{ + for (const auto& m : materials_) m->setup(numgp, fibers, coord_system); +} + +void Mat::SolidSuperposition::post_setup(const Teuchos::ParameterList& params, const int eleGID) +{ + for (const auto& m : materials_) m->post_setup(params, eleGID); +} + +void Mat::SolidSuperposition::update() +{ + for (const auto& m : materials_) m->update(); +} + +void Mat::SolidSuperposition::update(const Core::LinAlg::Tensor& defgrd, int gp, + const Teuchos::ParameterList& params, const EvaluationContext<3>& context, int eleGID) +{ + for (const auto& m : materials_) m->update(defgrd, gp, params, context, eleGID); +} + +void Mat::SolidSuperposition::evaluate(const Core::LinAlg::Tensor* defgrad, + const Core::LinAlg::SymmetricTensor& glstrain, + const Teuchos::ParameterList& params, const EvaluationContext<3>& context, + Core::LinAlg::SymmetricTensor& stress, + Core::LinAlg::SymmetricTensor& cmat, int gp, int eleGID) +{ + stress = {}; + cmat = {}; + + Core::LinAlg::SymmetricTensor s_tmp{}; + Core::LinAlg::SymmetricTensor c_tmp{}; + + // evaluate stress and material tangent for all materials + for (const auto& m : materials_) + { + s_tmp = {}; + c_tmp = {}; + + m->evaluate(defgrad, glstrain, params, context, s_tmp, c_tmp, gp, eleGID); + + // sum up the material contributions + stress += s_tmp; + cmat += c_tmp; + } +} + +void Mat::SolidSuperposition::register_output_data_names( + std::unordered_map& names_and_size) const +{ + for (const auto& m : materials_) m->register_output_data_names(names_and_size); +} + +bool Mat::SolidSuperposition::evaluate_output_data( + const std::string& name, Core::LinAlg::SerialDenseMatrix& data) const +{ + bool data_was_set = false; + for (const auto& m : materials_) + { + if (m->evaluate_output_data(name, data)) + { + data_was_set = true; + } + } + return data_was_set; +} + +FOUR_C_NAMESPACE_CLOSE \ No newline at end of file diff --git a/src/mat/4C_mat_solid_superposition.hpp b/src/mat/4C_mat_solid_superposition.hpp new file mode 100644 index 00000000000..68c6d478eda --- /dev/null +++ b/src/mat/4C_mat_solid_superposition.hpp @@ -0,0 +1,161 @@ +// This file is part of 4C multiphysics licensed under the +// GNU Lesser General Public License v3.0 or later. +// +// See the LICENSE.md file in the top-level for license information. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef FOUR_C_MAT_SOLID_SUPERPOSITION_HPP +#define FOUR_C_MAT_SOLID_SUPERPOSITION_HPP + +#include "4C_config.hpp" + +#include "4C_comm_parobjectfactory.hpp" +#include "4C_mat_so3_material.hpp" +#include "4C_material_parameter_base.hpp" + +FOUR_C_NAMESPACE_OPEN + +namespace Mat +{ + // forward declaration + class SolidSuperposition; + + namespace PAR + { + /// parameter class for the superposition material + class SolidSuperposition : public Core::Mat::PAR::Parameter + { + friend class Mat::SolidSuperposition; + + public: + /// standard constructor + explicit SolidSuperposition(const Core::Mat::PAR::Parameter::Data& matdata); + + std::shared_ptr create_material() override; + + /// @name material parameters + /// @{ + + /// density of the material + const double density_; + + /// list of the IDs of the materials to superpose + const std::vector matids_; + + /// @} + }; + } // namespace PAR + + + class SolidSuperpositionType : public Core::Communication::ParObjectType + { + public: + [[nodiscard]] std::string name() const override { return "SolidSuperpositionType"; } + + static SolidSuperpositionType& instance() { return instance_; } + + Core::Communication::ParObject* create(Core::Communication::UnpackBuffer& buffer) override; + + private: + static SolidSuperpositionType instance_; + }; + + /*! + * \brief Material that superposes multiple 3D solid materials. + * + * This material evaluates stress and consistent tangents by combining + * contributions from multiple 3D solid materials. + * + * The second Piola-Kirchhoff stress is computed as a linear sum: + * \f[ + * S = \sum_{i} S_i + * \f] + * + * and similarly the material tangent: + * \f[ + * \mathbb{C} = \sum_{i} \mathbb{C}_i + * \f] + * + * Each constituent material is evaluated independently, and their responses are accumulated. + */ + class SolidSuperposition : public So3Material + { + public: + /// constructor for an empty material object + SolidSuperposition(); + + /// constructor for the material given the material parameters + explicit SolidSuperposition(Mat::PAR::SolidSuperposition* params); + + [[nodiscard]] int unique_par_object_id() const override + { + return SolidSuperpositionType::instance().unique_par_object_id(); + } + + void pack(Core::Communication::PackBuffer& data) const override; + + void unpack(Core::Communication::UnpackBuffer& buffer) override; + + void valid_kinematics(Inpar::Solid::KinemType kinem) override + { + if (!(kinem == Inpar::Solid::KinemType::nonlinearTotLag)) + { + FOUR_C_THROW( + "Element and material kinematics are not compatible. Use nonlinear total lagrangian" + "kinematics (KINEM nonlinear) in your element definition."); + } + } + + [[nodiscard]] Core::Materials::MaterialType material_type() const override + { + return Core::Materials::m_superposition; + } + + [[nodiscard]] std::shared_ptr clone() const override + { + return std::make_shared(*this); + } + + [[nodiscard]] Core::Mat::PAR::Parameter* parameter() const override { return params_; } + + void setup(int numgp, const Discret::Elements::Fibers& fibers, + const std::optional& coord_system) override; + + void post_setup(const Teuchos::ParameterList& params, const int eleGID) override; + + void update() override; + + void update(const Core::LinAlg::Tensor& defgrd, int gp, + const Teuchos::ParameterList& params, const EvaluationContext<3>& context, + int eleGID) override; + + bool uses_extended_update() override { return true; } + + void evaluate(const Core::LinAlg::Tensor* defgrad, + const Core::LinAlg::SymmetricTensor& glstrain, + const Teuchos::ParameterList& params, const EvaluationContext<3>& context, + Core::LinAlg::SymmetricTensor& stress, + Core::LinAlg::SymmetricTensor& cmat, int gp, int eleGID) override; + + [[nodiscard]] double density() const override { return params_->density_; } + + void register_output_data_names( + std::unordered_map& names_and_size) const override; + + bool evaluate_output_data( + const std::string& name, Core::LinAlg::SerialDenseMatrix& data) const override; + + private: + /// material parameters, i.e., the density and the list of material IDs to superpose + Mat::PAR::SolidSuperposition* params_; + + /// list of the references to the materials to superpose + std::vector> materials_; + }; + +} // namespace Mat + +FOUR_C_NAMESPACE_CLOSE + +#endif \ No newline at end of file diff --git a/tests/input_files/mat_solid_superposition.4C.yaml b/tests/input_files/mat_solid_superposition.4C.yaml new file mode 100644 index 00000000000..8496b0686e4 --- /dev/null +++ b/tests/input_files/mat_solid_superposition.4C.yaml @@ -0,0 +1,185 @@ +TITLE: + - Testcase for testing the superposition for 3D solid materials (MAT_Solid_Superposition) + - The setup of the test-case is a single cube with HEX8 elements. + - The cube is fixed on the bottom surface (z=0). On the top surface (z=1), a surface force is applied + in x-, y- and z-direction subsequently. + - The test uses the MAT_Solid_Superposition with two St. Venant Kirchhoff constituents with Young moduli + 200 and 600 (summing to 800). + - The results match a single St. Venant Kirchhoff material with Young's modulus 800, verifying linear + superposition of stresses and tangents. +PROBLEM TYPE: + PROBLEMTYPE: "Structure" +IO: + STRUCT_STRESS: "2PK" + STRUCT_STRAIN: "GL" +IO/RUNTIME VTK OUTPUT: + INTERVAL_STEPS: 1 +IO/RUNTIME VTK OUTPUT/STRUCTURE: + OUTPUT_STRUCTURE: true + DISPLACEMENT: true + ELEMENT_OWNER: true + NODE_GID: true + STRESS_STRAIN: true +STRUCTURAL DYNAMIC: + RESTARTEVERY: 25 + DYNAMICTYPE: "Statics" + TIMESTEP: 0.1 + NUMSTEP: 30 + MAXTIME: 3 + TOLDISP: 1e-09 + TOLRES: 1e-09 + ITERNORM: "Inf" + LINEAR_SOLVER: 1 +SOLVER 1: + SOLVER: "UMFPACK" +DESIGN SURF DIRICH CONDITIONS: + - E: 1 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 0] + FUNCT: [0, 0, 0] +DESIGN SURF NEUMANN CONDITIONS: + - E: 2 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [10, 10, 10] + FUNCT: [1, 2, 3] +MATERIALS: + - MAT: 1 + MAT_Solid_Superposition: + MATIDS: [11, 12] + DENS: 1.0 + - MAT: 11 + MAT_Struct_StVenantKirchhoff: + YOUNG: 200 + NUE: 0 + DENS: 1 + - MAT: 12 + MAT_Struct_StVenantKirchhoff: + YOUNG: 600 + NUE: 0 + DENS: 1 +FUNCT1: + - COMPONENT: 0 + SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "linearinterpolation" + NUMPOINTS: 3 + TIMES: [0, 1, 3] + VALUES: [0, 1, 1] +FUNCT2: + - COMPONENT: 0 + SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "linearinterpolation" + NUMPOINTS: 4 + TIMES: [0, 1, 2, 3] + VALUES: [0, 0, 1, 1] +FUNCT3: + - COMPONENT: 0 + SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "linearinterpolation" + NUMPOINTS: 3 + TIMES: [0, 2, 3] + VALUES: [0, 0, 1] +RESULT DESCRIPTION: + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "dispx" + VALUE: 0.06338889942814144 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "dispy" + VALUE: 0.0633888994281415 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "dispz" + VALUE: 0.06798864578422244 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "stress_xx" + VALUE: 0.08497433481156066 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "stress_yy" + VALUE: 0.08497433481171451 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "stress_zz" + VALUE: 35.57024088052319 + TOLERANCE: 1e-07 +DNODE-NODE TOPOLOGY: + - "NODE 1 DNODE 1" + - "NODE 9 DNODE 2" + - "NODE 17 DNODE 3" +DSURF-NODE TOPOLOGY: + - "NODE 1 DSURFACE 1" + - "NODE 2 DSURFACE 1" + - "NODE 3 DSURFACE 1" + - "NODE 5 DSURFACE 1" + - "NODE 9 DSURFACE 1" + - "NODE 10 DSURFACE 1" + - "NODE 13 DSURFACE 1" + - "NODE 14 DSURFACE 1" + - "NODE 21 DSURFACE 1" + - "NODE 17 DSURFACE 2" + - "NODE 18 DSURFACE 2" + - "NODE 19 DSURFACE 2" + - "NODE 20 DSURFACE 2" + - "NODE 23 DSURFACE 2" + - "NODE 24 DSURFACE 2" + - "NODE 25 DSURFACE 2" + - "NODE 26 DSURFACE 2" + - "NODE 27 DSURFACE 2" +NODE COORDS: + - "NODE 1 COORD 0.0 0.0 0.0" + - "NODE 2 COORD 0.5 0.0 0.0" + - "NODE 3 COORD 0.0 0.5 0.0" + - "NODE 4 COORD 0.0 0.0 0.5" + - "NODE 5 COORD 0.5 0.5 0.0" + - "NODE 6 COORD 0.5 0.0 0.5" + - "NODE 7 COORD 0.0 0.5 0.5" + - "NODE 8 COORD 0.5 0.5 0.5" + - "NODE 9 COORD 1.0 0.0 0.0" + - "NODE 10 COORD 1.0 0.5 0.0" + - "NODE 11 COORD 1.0 0.0 0.5" + - "NODE 12 COORD 1.0 0.5 0.5" + - "NODE 13 COORD 0.0 1.0 0.0" + - "NODE 14 COORD 0.5 1.0 0.0" + - "NODE 15 COORD 0.0 1.0 0.5" + - "NODE 16 COORD 0.5 1.0 0.5" + - "NODE 17 COORD 0.0 0.0 1.0" + - "NODE 18 COORD 0.5 0.0 1.0" + - "NODE 19 COORD 0.0 0.5 1.0" + - "NODE 20 COORD 0.5 0.5 1.0" + - "NODE 21 COORD 1.0 1.0 0.0" + - "NODE 22 COORD 1.0 1.0 0.5" + - "NODE 23 COORD 1.0 0.0 1.0" + - "NODE 24 COORD 1.0 0.5 1.0" + - "NODE 25 COORD 0.0 1.0 1.0" + - "NODE 26 COORD 0.5 1.0 1.0" + - "NODE 27 COORD 1.0 1.0 1.0" +STRUCTURE ELEMENTS: + - "1 SOLID HEX8 1 2 5 3 4 6 8 7 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "2 SOLID HEX8 2 9 10 5 6 11 12 8 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "3 SOLID HEX8 5 10 21 14 8 12 22 16 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "4 SOLID HEX8 3 5 14 13 7 8 16 15 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "5 SOLID HEX8 4 6 8 7 17 18 20 19 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "6 SOLID HEX8 6 11 12 8 18 23 24 20 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "7 SOLID HEX8 8 12 22 16 20 24 27 26 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "8 SOLID HEX8 7 8 16 15 19 20 26 25 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" diff --git a/tests/input_files/mat_solid_superposition_elasthyper_anisotropic.4C.yaml b/tests/input_files/mat_solid_superposition_elasthyper_anisotropic.4C.yaml new file mode 100644 index 00000000000..c3ee7cb2590 --- /dev/null +++ b/tests/input_files/mat_solid_superposition_elasthyper_anisotropic.4C.yaml @@ -0,0 +1,213 @@ +TITLE: + - Testcase for testing the superposition for 3D solid materials (MAT_Solid_Superposition) using the + elasthyper framework + - The setup of the test-case is a single cube with HEX8 elements. + - The cube is fixed on the bottom surface (z=0). On the top surface (z=1), a surface force is applied + in x-, y- and z-direction subsequently. + - The test uses the MAT_Solid_Superposition with two elasthyper materials. A CoupAnisoExpo (GAMMA 10) + + CoupNeoHooke (YOUNG 15) and a CoupAnisoExpo (GAMMA 25) + CoupNeoHooke (YOUNG 5). + - This is equivalent to a single material with CoupAnisoExpo (GAMMA 35) + CoupNeoHooke (YOUNG 20), verifying + that the anisotropic contributions superpose correctly. +PROBLEM TYPE: + PROBLEMTYPE: "Structure" +IO: + STRUCT_STRESS: "2PK" + STRUCT_STRAIN: "GL" +IO/RUNTIME VTK OUTPUT: + INTERVAL_STEPS: 1 +IO/RUNTIME VTK OUTPUT/STRUCTURE: + OUTPUT_STRUCTURE: true + DISPLACEMENT: true + ELEMENT_OWNER: true + NODE_GID: true + STRESS_STRAIN: true +STRUCTURAL DYNAMIC: + RESTARTEVERY: 25 + DYNAMICTYPE: "Statics" + TIMESTEP: 0.1 + NUMSTEP: 30 + MAXTIME: 3 + TOLDISP: 1e-09 + TOLRES: 1e-09 + ITERNORM: "Inf" + LINEAR_SOLVER: 1 +SOLVER 1: + SOLVER: "UMFPACK" +DESIGN SURF DIRICH CONDITIONS: + - E: 1 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 0] + FUNCT: [0, 0, 0] +DESIGN SURF NEUMANN CONDITIONS: + - E: 2 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [10, 10, 10] + FUNCT: [1, 2, 3] +MATERIALS: + - MAT: 1 + MAT_Solid_Superposition: + MATIDS: [10, 20] + DENS: 1.0 + - MAT: 10 + MAT_ElastHyper: + NUMMAT: 2 + MATIDS: [11, 12] + DENS: 1 # note that this density is ignored by the superposition material + - MAT: 11 + ELAST_CoupAnisoExpo: + K1: 100 + K2: 1 + GAMMA: 10 + K1COMP: 0 + K2COMP: 1 + STR_TENS_ID: 1000 + - MAT: 12 + ELAST_CoupNeoHooke: + YOUNG: 15 + NUE: 0.3 + - MAT: 20 + MAT_ElastHyper: + NUMMAT: 2 + MATIDS: [21, 22] + DENS: 1 # note that this density is ignored by the superposition material + - MAT: 21 + ELAST_CoupAnisoExpo: + K1: 100 + K2: 1 + GAMMA: 25 + K1COMP: 0 + K2COMP: 1 + STR_TENS_ID: 1000 + - MAT: 22 + ELAST_CoupNeoHooke: + YOUNG: 5 + NUE: 0.3 + - MAT: 1000 + ELAST_StructuralTensor: + STRATEGY: "Standard" +FUNCT1: + - COMPONENT: 0 + SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "linearinterpolation" + NUMPOINTS: 3 + TIMES: [0, 1, 3] + VALUES: [0, 1, 1] +FUNCT2: + - COMPONENT: 0 + SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "linearinterpolation" + NUMPOINTS: 4 + TIMES: [0, 1, 2, 3] + VALUES: [0, 0, 1, 1] +FUNCT3: + - COMPONENT: 0 + SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "linearinterpolation" + NUMPOINTS: 3 + TIMES: [0, 2, 3] + VALUES: [0, 0, 1] +RESULT DESCRIPTION: + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "dispx" + VALUE: 1.64568384680415725e+00 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "dispy" + VALUE: 1.64568384680415702e+00 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "dispz" + VALUE: 9.35092459998460135e-01 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "stress_xx" + VALUE: 7.66716255631645582e-01 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "stress_yy" + VALUE: 7.66716255631638921e-01 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "stress_zz" + VALUE: 7.11387414277126773e+00 + TOLERANCE: 1e-07 +DNODE-NODE TOPOLOGY: + - "NODE 1 DNODE 1" + - "NODE 9 DNODE 2" + - "NODE 17 DNODE 3" +DSURF-NODE TOPOLOGY: + - "NODE 1 DSURFACE 1" + - "NODE 2 DSURFACE 1" + - "NODE 3 DSURFACE 1" + - "NODE 5 DSURFACE 1" + - "NODE 9 DSURFACE 1" + - "NODE 10 DSURFACE 1" + - "NODE 13 DSURFACE 1" + - "NODE 14 DSURFACE 1" + - "NODE 21 DSURFACE 1" + - "NODE 17 DSURFACE 2" + - "NODE 18 DSURFACE 2" + - "NODE 19 DSURFACE 2" + - "NODE 20 DSURFACE 2" + - "NODE 23 DSURFACE 2" + - "NODE 24 DSURFACE 2" + - "NODE 25 DSURFACE 2" + - "NODE 26 DSURFACE 2" + - "NODE 27 DSURFACE 2" +NODE COORDS: + - "NODE 1 COORD 0.0 0.0 0.0" + - "NODE 2 COORD 0.5 0.0 0.0" + - "NODE 3 COORD 0.0 0.5 0.0" + - "NODE 4 COORD 0.0 0.0 0.5" + - "NODE 5 COORD 0.5 0.5 0.0" + - "NODE 6 COORD 0.5 0.0 0.5" + - "NODE 7 COORD 0.0 0.5 0.5" + - "NODE 8 COORD 0.5 0.5 0.5" + - "NODE 9 COORD 1.0 0.0 0.0" + - "NODE 10 COORD 1.0 0.5 0.0" + - "NODE 11 COORD 1.0 0.0 0.5" + - "NODE 12 COORD 1.0 0.5 0.5" + - "NODE 13 COORD 0.0 1.0 0.0" + - "NODE 14 COORD 0.5 1.0 0.0" + - "NODE 15 COORD 0.0 1.0 0.5" + - "NODE 16 COORD 0.5 1.0 0.5" + - "NODE 17 COORD 0.0 0.0 1.0" + - "NODE 18 COORD 0.5 0.0 1.0" + - "NODE 19 COORD 0.0 0.5 1.0" + - "NODE 20 COORD 0.5 0.5 1.0" + - "NODE 21 COORD 1.0 1.0 0.0" + - "NODE 22 COORD 1.0 1.0 0.5" + - "NODE 23 COORD 1.0 0.0 1.0" + - "NODE 24 COORD 1.0 0.5 1.0" + - "NODE 25 COORD 0.0 1.0 1.0" + - "NODE 26 COORD 0.5 1.0 1.0" + - "NODE 27 COORD 1.0 1.0 1.0" +STRUCTURE ELEMENTS: + - "1 SOLID HEX8 1 2 5 3 4 6 8 7 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "2 SOLID HEX8 2 9 10 5 6 11 12 8 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "3 SOLID HEX8 5 10 21 14 8 12 22 16 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "4 SOLID HEX8 3 5 14 13 7 8 16 15 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "5 SOLID HEX8 4 6 8 7 17 18 20 19 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "6 SOLID HEX8 6 11 12 8 18 23 24 20 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "7 SOLID HEX8 8 12 22 16 20 24 27 26 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "8 SOLID HEX8 7 8 16 15 19 20 26 25 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" diff --git a/tests/input_files/mat_solid_superposition_mixture_anisotropic.4C.yaml b/tests/input_files/mat_solid_superposition_mixture_anisotropic.4C.yaml new file mode 100644 index 00000000000..d11c8d4a58f --- /dev/null +++ b/tests/input_files/mat_solid_superposition_mixture_anisotropic.4C.yaml @@ -0,0 +1,225 @@ +TITLE: + - Testcase for testing the superposition for 3D solid materials (MAT_Solid_Superposition) using a mixture + with anisotropic elasthyper constituents + - The setup of the test-case is a single cube with HEX8 elements. + - The cube is fixed on the bottom surface (z=0). On the top surface (z=1), a surface force is applied + in x-, y- and z-direction subsequently. + - The test uses the MAT_Solid_Superposition with two material constituents. + - A MAT_Mixture (MAT 10) wrapping anisotropic elasthyper materials (ELAST_CoupAnisoExpo GAMMA 10 + ELAST_CoupNeoHooke + YOUNG 15) and a MAT_ElastHyper (MAT 20) with anisotropic elasthyper materials (ELAST_CoupAnisoExpo + GAMMA 25 + ELAST_CoupNeoHooke YOUNG 5). + - MAT 10 contains only a single constituent with mass fraction 1.0, so it acts as a pure wrapper around + the elasthyper material with no actual mixture behavior. This is done to verify that the mixture framework + works correctly within a MAT_Solid_Superposition context. + - The expected results match those of mat_solid_superposition_elasthyper_anisotropic, confirming that + MAT_Solid_Superposition handles mixture constituents correctly." +PROBLEM TYPE: + PROBLEMTYPE: "Structure" +IO: + STRUCT_STRESS: "2PK" + STRUCT_STRAIN: "GL" +IO/RUNTIME VTK OUTPUT: + INTERVAL_STEPS: 1 +IO/RUNTIME VTK OUTPUT/STRUCTURE: + OUTPUT_STRUCTURE: true + DISPLACEMENT: true + ELEMENT_OWNER: true + NODE_GID: true + STRESS_STRAIN: true +STRUCTURAL DYNAMIC: + RESTARTEVERY: 25 + DYNAMICTYPE: "Statics" + TIMESTEP: 0.1 + NUMSTEP: 30 + MAXTIME: 3 + TOLDISP: 1e-09 + TOLRES: 1e-09 + ITERNORM: "Inf" + LINEAR_SOLVER: 1 +SOLVER 1: + SOLVER: "UMFPACK" +DESIGN SURF DIRICH CONDITIONS: + - E: 1 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [0, 0, 0] + FUNCT: [0, 0, 0] +DESIGN SURF NEUMANN CONDITIONS: + - E: 2 + NUMDOF: 3 + ONOFF: [1, 1, 1] + VAL: [10, 10, 10] + FUNCT: [1, 2, 3] +MATERIALS: + - MAT: 1 + MAT_Solid_Superposition: + MATIDS: [10, 20] + DENS: 1.0 + - MAT: 10 + MAT_Mixture: + MATIDMIXTURERULE: 30 + MATIDSCONST: [40] + - MAT: 30 + MIX_Rule_Simple: + DENS: 1.0 # note that this density is ignored by the superposition material + MASSFRAC: + constant: [1.0] + - MAT: 40 + MIX_Constituent_ElastHyper: + MATIDS: [11, 12] + - MAT: 11 + ELAST_CoupAnisoExpo: + K1: 100 + K2: 1 + GAMMA: 10 + K1COMP: 0 + K2COMP: 1 + STR_TENS_ID: 1000 + - MAT: 12 + ELAST_CoupNeoHooke: + YOUNG: 15 + NUE: 0.3 + - MAT: 20 + MAT_ElastHyper: + NUMMAT: 2 + MATIDS: [21, 22] + DENS: 1 # note that this density is ignored by the superposition material + - MAT: 21 + ELAST_CoupAnisoExpo: + K1: 100 + K2: 1 + GAMMA: 25 + K1COMP: 0 + K2COMP: 1 + STR_TENS_ID: 1000 + - MAT: 22 + ELAST_CoupNeoHooke: + YOUNG: 5 + NUE: 0.3 + - MAT: 1000 + ELAST_StructuralTensor: + STRATEGY: "Standard" +FUNCT1: + - COMPONENT: 0 + SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "linearinterpolation" + NUMPOINTS: 3 + TIMES: [0, 1, 3] + VALUES: [0, 1, 1] +FUNCT2: + - COMPONENT: 0 + SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "linearinterpolation" + NUMPOINTS: 4 + TIMES: [0, 1, 2, 3] + VALUES: [0, 0, 1, 1] +FUNCT3: + - COMPONENT: 0 + SYMBOLIC_FUNCTION_OF_SPACE_TIME: "a" + - VARIABLE: 0 + NAME: "a" + TYPE: "linearinterpolation" + NUMPOINTS: 3 + TIMES: [0, 2, 3] + VALUES: [0, 0, 1] +RESULT DESCRIPTION: + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "dispx" + VALUE: 1.64568384680415725e+00 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "dispy" + VALUE: 1.64568384680415702e+00 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "dispz" + VALUE: 9.35092459998460135e-01 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "stress_xx" + VALUE: 7.66716255631645582e-01 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "stress_yy" + VALUE: 7.66716255631638921e-01 + TOLERANCE: 1e-07 + - STRUCTURE: + DIS: "structure" + NODE: 17 + QUANTITY: "stress_zz" + VALUE: 7.11387414277126773e+00 + TOLERANCE: 1e-07 +DNODE-NODE TOPOLOGY: + - "NODE 1 DNODE 1" + - "NODE 9 DNODE 2" + - "NODE 17 DNODE 3" +DSURF-NODE TOPOLOGY: + - "NODE 1 DSURFACE 1" + - "NODE 2 DSURFACE 1" + - "NODE 3 DSURFACE 1" + - "NODE 5 DSURFACE 1" + - "NODE 9 DSURFACE 1" + - "NODE 10 DSURFACE 1" + - "NODE 13 DSURFACE 1" + - "NODE 14 DSURFACE 1" + - "NODE 21 DSURFACE 1" + - "NODE 17 DSURFACE 2" + - "NODE 18 DSURFACE 2" + - "NODE 19 DSURFACE 2" + - "NODE 20 DSURFACE 2" + - "NODE 23 DSURFACE 2" + - "NODE 24 DSURFACE 2" + - "NODE 25 DSURFACE 2" + - "NODE 26 DSURFACE 2" + - "NODE 27 DSURFACE 2" +NODE COORDS: + - "NODE 1 COORD 0.0 0.0 0.0" + - "NODE 2 COORD 0.5 0.0 0.0" + - "NODE 3 COORD 0.0 0.5 0.0" + - "NODE 4 COORD 0.0 0.0 0.5" + - "NODE 5 COORD 0.5 0.5 0.0" + - "NODE 6 COORD 0.5 0.0 0.5" + - "NODE 7 COORD 0.0 0.5 0.5" + - "NODE 8 COORD 0.5 0.5 0.5" + - "NODE 9 COORD 1.0 0.0 0.0" + - "NODE 10 COORD 1.0 0.5 0.0" + - "NODE 11 COORD 1.0 0.0 0.5" + - "NODE 12 COORD 1.0 0.5 0.5" + - "NODE 13 COORD 0.0 1.0 0.0" + - "NODE 14 COORD 0.5 1.0 0.0" + - "NODE 15 COORD 0.0 1.0 0.5" + - "NODE 16 COORD 0.5 1.0 0.5" + - "NODE 17 COORD 0.0 0.0 1.0" + - "NODE 18 COORD 0.5 0.0 1.0" + - "NODE 19 COORD 0.0 0.5 1.0" + - "NODE 20 COORD 0.5 0.5 1.0" + - "NODE 21 COORD 1.0 1.0 0.0" + - "NODE 22 COORD 1.0 1.0 0.5" + - "NODE 23 COORD 1.0 0.0 1.0" + - "NODE 24 COORD 1.0 0.5 1.0" + - "NODE 25 COORD 0.0 1.0 1.0" + - "NODE 26 COORD 0.5 1.0 1.0" + - "NODE 27 COORD 1.0 1.0 1.0" +STRUCTURE ELEMENTS: + - "1 SOLID HEX8 1 2 5 3 4 6 8 7 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "2 SOLID HEX8 2 9 10 5 6 11 12 8 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "3 SOLID HEX8 5 10 21 14 8 12 22 16 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "4 SOLID HEX8 3 5 14 13 7 8 16 15 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "5 SOLID HEX8 4 6 8 7 17 18 20 19 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "6 SOLID HEX8 6 11 12 8 18 23 24 20 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "7 SOLID HEX8 8 12 22 16 20 24 27 26 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" + - "8 SOLID HEX8 7 8 16 15 19 20 26 25 MAT 1 KINEM nonlinear FIBER1 1.0 0.0 0.0" diff --git a/tests/list_of_tests.cmake b/tests/list_of_tests.cmake index 83b72313c00..66a9153178a 100644 --- a/tests/list_of_tests.cmake +++ b/tests/list_of_tests.cmake @@ -915,6 +915,12 @@ four_c_test(TEST_FILE mat_muscle_giantesio_hex.4C.yaml NP 2 RETURN_AS current) __four_c_test_restart(BASED_ON ${current} SAME_FILE NP 2 RESTART_STEP 140) four_c_test(TEST_FILE mat_muscle_weickenmeier_hex.4C.yaml NP 2 RETURN_AS current) __four_c_test_restart(BASED_ON ${current} SAME_FILE NP 2 RESTART_STEP 140) +four_c_test(TEST_FILE mat_solid_superposition.4C.yaml NP 2 RETURN_AS current) +__four_c_test_restart(BASED_ON ${current} SAME_FILE NP 2 RESTART_STEP 25) +four_c_test(TEST_FILE mat_solid_superposition_elasthyper_anisotropic.4C.yaml NP 2 RETURN_AS current) +__four_c_test_restart(BASED_ON ${current} SAME_FILE NP 2 RESTART_STEP 25) +four_c_test(TEST_FILE mat_solid_superposition_mixture_anisotropic.4C.yaml NP 2 RETURN_AS current) +__four_c_test_restart(BASED_ON ${current} SAME_FILE NP 2 RESTART_STEP 25) four_c_test(TEST_FILE mat_transversely_isotropic.4C.yaml) four_c_test(TEST_FILE mat_transviso_viscoplast_refJC_log_timint.4C.yaml RETURN_AS current) __four_c_test_restart(BASED_ON ${current} SAME_FILE RESTART_STEP 90) From cb856d6873162cbbaa6ab481f67aed3b811e9116 Mon Sep 17 00:00:00 2001 From: Paul Tuch Date: Mon, 8 Jun 2026 13:54:05 +0200 Subject: [PATCH 28/28] Migrate elastic right CG derivs to tensor API --- ...linalg_fixedsizematrix_tensor_products.cpp | 124 ------------------ ...linalg_fixedsizematrix_tensor_products.hpp | 30 ----- .../src/dense/4C_linalg_tensor_conversion.hpp | 84 ++++++++++++ .../4C_linalg_tensor_conversion_test.cpp | 77 +++++++++++ src/mat/4C_mat_elasthyper_service.cpp | 35 ++--- src/mat/4C_mat_elasthyper_service.hpp | 9 +- src/mat/4C_mat_inelastic_defgrad_factors.cpp | 13 +- ...ultiplicative_split_defgrad_elasthyper.cpp | 6 +- 8 files changed, 194 insertions(+), 184 deletions(-) diff --git a/src/core/linalg/src/dense/4C_linalg_fixedsizematrix_tensor_products.cpp b/src/core/linalg/src/dense/4C_linalg_fixedsizematrix_tensor_products.cpp index 25eb203c53e..e0bd4ff6dbb 100644 --- a/src/core/linalg/src/dense/4C_linalg_fixedsizematrix_tensor_products.cpp +++ b/src/core/linalg/src/dense/4C_linalg_fixedsizematrix_tensor_products.cpp @@ -150,120 +150,6 @@ void Core::LinAlg::FourTensorOperations::add_kronecker_tensor_product(Core::LinA scalar_this * C(5, 5) + scalar_AB_half * (A(0, 0) * B(2, 2) + A(0, 2) * B(2, 0)); // C1313 } - -void Core::LinAlg::FourTensorOperations::add_kronecker_tensor_product(Core::LinAlg::Matrix<6, 9>& C, - const double scalar_AB, const Core::LinAlg::Matrix<3, 3>& A, - const Core::LinAlg::Matrix<3, 3>& B, const double scalar_this) -{ - const double scalar_AB_half = scalar_AB * 0.5; - C(0, 0) = scalar_this * C(0, 0) + scalar_AB * (A(0, 0) * B(0, 0)); // C1111 - C(0, 1) = scalar_this * C(0, 1) + scalar_AB * (A(0, 1) * B(0, 1)); // C1122 - C(0, 2) = scalar_this * C(0, 2) + scalar_AB * (A(0, 2) * B(0, 2)); // C1133 - C(0, 3) = - scalar_this * C(0, 3) + scalar_AB_half * (A(0, 0) * B(0, 1) + A(0, 1) * B(0, 0)); // C1112 - C(0, 4) = - scalar_this * C(0, 4) + scalar_AB_half * (A(0, 1) * B(0, 2) + A(0, 2) * B(0, 1)); // C1123 - C(0, 5) = - scalar_this * C(0, 5) + scalar_AB_half * (A(0, 0) * B(0, 2) + A(0, 2) * B(0, 0)); // C1113 - C(0, 6) = - scalar_this * C(0, 6) + scalar_AB_half * (A(0, 1) * B(0, 0) + A(0, 0) * B(0, 1)); // C1121 - C(0, 7) = - scalar_this * C(0, 7) + scalar_AB_half * (A(0, 2) * B(0, 1) + A(0, 1) * B(0, 2)); // C1132 - C(0, 8) = - scalar_this * C(0, 8) + scalar_AB_half * (A(0, 2) * B(0, 0) + A(0, 0) * B(0, 2)); // C1131 - - - C(1, 0) = scalar_this * C(1, 0) + scalar_AB * (A(1, 0) * B(1, 0)); // C2211 - C(1, 1) = scalar_this * C(1, 1) + scalar_AB * (A(1, 1) * B(1, 1)); // C2222 - C(1, 2) = scalar_this * C(1, 2) + scalar_AB * (A(1, 2) * B(1, 2)); // C2233 - C(1, 3) = - scalar_this * C(1, 3) + scalar_AB_half * (A(1, 0) * B(1, 1) + A(1, 1) * B(1, 0)); // C2212 - C(1, 4) = - scalar_this * C(1, 4) + scalar_AB_half * (A(1, 1) * B(1, 2) + A(1, 2) * B(1, 1)); // C2223 - C(1, 5) = - scalar_this * C(1, 5) + scalar_AB_half * (A(1, 0) * B(1, 2) + A(1, 2) * B(1, 0)); // C2213 - C(1, 6) = - scalar_this * C(1, 6) + scalar_AB_half * (A(1, 1) * B(1, 0) + A(1, 0) * B(1, 1)); // C2221 - C(1, 7) = - scalar_this * C(1, 7) + scalar_AB_half * (A(1, 2) * B(1, 1) + A(1, 1) * B(1, 2)); // C2232 - C(1, 8) = - scalar_this * C(1, 8) + scalar_AB_half * (A(1, 2) * B(1, 0) + A(1, 0) * B(1, 2)); // C2231 - - - - C(2, 0) = scalar_this * C(2, 0) + scalar_AB * (A(2, 0) * B(2, 0)); // C3311 - C(2, 1) = scalar_this * C(2, 1) + scalar_AB * (A(2, 1) * B(2, 1)); // C3322 - C(2, 2) = scalar_this * C(2, 2) + scalar_AB * (A(2, 2) * B(2, 2)); // C3333 - C(2, 3) = - scalar_this * C(2, 3) + scalar_AB_half * (A(2, 0) * B(2, 1) + A(2, 1) * B(2, 0)); // C3312 - C(2, 4) = - scalar_this * C(2, 4) + scalar_AB_half * (A(2, 1) * B(2, 2) + A(2, 2) * B(2, 1)); // C3323 - C(2, 5) = - scalar_this * C(2, 5) + scalar_AB_half * (A(2, 0) * B(2, 2) + A(2, 2) * B(2, 0)); // C3313 - C(2, 6) = - scalar_this * C(2, 6) + scalar_AB_half * (A(2, 0) * B(2, 1) + A(2, 1) * B(2, 0)); // C3321 - C(2, 7) = - scalar_this * C(2, 7) + scalar_AB_half * (A(2, 2) * B(2, 1) + A(2, 1) * B(2, 2)); // C3332 - C(2, 8) = - scalar_this * C(2, 8) + scalar_AB_half * (A(2, 2) * B(2, 0) + A(2, 0) * B(2, 2)); // C3331 - - - - C(3, 0) = scalar_this * C(3, 0) + scalar_AB * (A(0, 0) * B(1, 0)); // C1211 - C(3, 1) = scalar_this * C(3, 1) + scalar_AB * (A(0, 1) * B(1, 1)); // C1222 - C(3, 2) = scalar_this * C(3, 2) + scalar_AB * (A(0, 2) * B(1, 2)); // C1233 - C(3, 3) = - scalar_this * C(3, 3) + scalar_AB_half * (A(0, 0) * B(1, 1) + A(0, 1) * B(1, 0)); // C1212 - C(3, 4) = - scalar_this * C(3, 4) + scalar_AB_half * (A(0, 1) * B(1, 2) + A(0, 2) * B(1, 1)); // C1223 - C(3, 5) = - scalar_this * C(3, 5) + scalar_AB_half * (A(0, 0) * B(1, 2) + A(0, 2) * B(1, 0)); // C1213 - C(3, 6) = - scalar_this * C(3, 6) + scalar_AB_half * (A(0, 1) * B(1, 0) + A(0, 0) * B(1, 1)); // C1221 - C(3, 7) = - scalar_this * C(3, 7) + scalar_AB_half * (A(0, 2) * B(1, 1) + A(0, 1) * B(1, 2)); // C1232 - C(3, 8) = - scalar_this * C(3, 8) + scalar_AB_half * (A(0, 2) * B(1, 0) + A(0, 0) * B(1, 2)); // C1231 - - - - C(4, 0) = scalar_this * C(4, 0) + scalar_AB * (A(1, 0) * B(2, 0)); // C2311 - C(4, 1) = scalar_this * C(4, 1) + scalar_AB * (A(1, 1) * B(2, 1)); // C2322 - C(4, 2) = scalar_this * C(4, 2) + scalar_AB * (A(1, 2) * B(2, 2)); // C2333 - C(4, 3) = - scalar_this * C(4, 3) + scalar_AB_half * (A(1, 0) * B(2, 1) + A(1, 1) * B(2, 0)); // C2312 - C(4, 4) = - scalar_this * C(4, 4) + scalar_AB_half * (A(1, 1) * B(2, 2) + A(1, 2) * B(2, 1)); // C2323 - C(4, 5) = - scalar_this * C(4, 5) + scalar_AB_half * (A(1, 0) * B(2, 2) + A(1, 2) * B(2, 0)); // C2313 - C(4, 6) = - scalar_this * C(4, 6) + scalar_AB_half * (A(1, 1) * B(2, 0) + A(1, 0) * B(2, 1)); // C2321 - C(4, 7) = - scalar_this * C(4, 7) + scalar_AB_half * (A(1, 2) * B(2, 1) + A(1, 1) * B(2, 2)); // C2332 - C(4, 8) = - scalar_this * C(4, 8) + scalar_AB_half * (A(1, 2) * B(2, 0) + A(1, 0) * B(2, 2)); // C2331 - - - - C(5, 0) = scalar_this * C(5, 0) + scalar_AB * (A(0, 0) * B(2, 0)); // C1311 - C(5, 1) = scalar_this * C(5, 1) + scalar_AB * (A(0, 1) * B(2, 1)); // C1322 - C(5, 2) = scalar_this * C(5, 2) + scalar_AB * (A(0, 2) * B(2, 2)); // C1333 - C(5, 3) = - scalar_this * C(5, 3) + scalar_AB_half * (A(0, 0) * B(2, 1) + A(0, 1) * B(2, 0)); // C1312 - C(5, 4) = - scalar_this * C(5, 4) + scalar_AB_half * (A(0, 1) * B(2, 2) + A(0, 2) * B(2, 1)); // C1323 - C(5, 5) = - scalar_this * C(5, 5) + scalar_AB_half * (A(0, 0) * B(2, 2) + A(0, 2) * B(2, 0)); // C1313 - C(5, 5) = - scalar_this * C(5, 5) + scalar_AB_half * (A(0, 0) * B(2, 2) + A(0, 2) * B(2, 0)); // C1313 - C(5, 6) = - scalar_this * C(5, 6) + scalar_AB_half * (A(0, 1) * B(2, 0) + A(0, 0) * B(2, 1)); // C1321 - C(5, 7) = - scalar_this * C(5, 7) + scalar_AB_half * (A(0, 2) * B(2, 1) + A(0, 1) * B(2, 2)); // C1332 - C(5, 8) = - scalar_this * C(5, 7) + scalar_AB_half * (A(0, 2) * B(2, 0) + A(0, 0) * B(2, 2)); // C1331 -} - template void Core::LinAlg::FourTensorOperations::add_holzapfel_product( Core::LinAlg::Matrix<6, 6, T>& cmat, const Core::LinAlg::Matrix<6, 1, T>& invc, const T scalar) @@ -922,16 +808,6 @@ void Core::LinAlg::FourTensorOperations::add_contraction_matrix_four_tensor( matrix_result(i, j) += scale * four_tensor(i, j, k, l) * matrix(k, l); } -double Core::LinAlg::FourTensorOperations::contract_matrix_matrix( - const Core::LinAlg::Matrix<3, 3>& matrix_A, const Core::LinAlg::Matrix<3, 3>& matrix_B) -{ - double scalarContraction = 0.0; - for (unsigned i = 0; i < 3; ++i) - for (unsigned j = 0; j < 3; ++j) scalarContraction += matrix_A(i, j) * matrix_B(i, j); - - return scalarContraction; -} - // explicit instantiation of template functions template void Core::LinAlg::FourTensorOperations::add_holzapfel_product( Core::LinAlg::Matrix<6, 6, double>&, const Core::LinAlg::Matrix<6, 1, double>&, diff --git a/src/core/linalg/src/dense/4C_linalg_fixedsizematrix_tensor_products.hpp b/src/core/linalg/src/dense/4C_linalg_fixedsizematrix_tensor_products.hpp index ec7348595e7..57e0f57fbfe 100644 --- a/src/core/linalg/src/dense/4C_linalg_fixedsizematrix_tensor_products.hpp +++ b/src/core/linalg/src/dense/4C_linalg_fixedsizematrix_tensor_products.hpp @@ -21,7 +21,6 @@ #include "4C_linalg_four_tensor.hpp" #include "4C_linalg_symmetric_tensor.hpp" #include "4C_linalg_tensor.hpp" - FOUR_C_NAMESPACE_OPEN namespace Core::LinAlg::FourTensorOperations @@ -99,25 +98,6 @@ namespace Core::LinAlg::FourTensorOperations const Core::LinAlg::Matrix<3, 3>& A, const Core::LinAlg::Matrix<3, 3>& B, const double scalar_this); - /*! - * @brief Multiply two 2nd order tensors A o B and add the result to a 4th order material tensor - * in matrix notation, possessing left minor symmetry. - * - * In tensor index notation this method does - * \f[ - * C_{IJKL} := \text{scalar_this} \cdot C_{IJKL} + \frac{1}{2} \cdot \text{scalar_AB} \cdot \left( - * A_{IK} \cdot B_{JL} + A_{IL} \cdot B_{JK} \right) \f] - * - * - * @param[in,out] C Material tangent matrix to be modified - * @param[in] scalar_AB Scalar to multiply with A o B - * @param[in] A Dense matrix (3 x 3) as 2nd order tensor A - * @param[in] B Dense matrix (3 x 3) as 2nd order tensor B - * @param[in] scalar_this Scalar to multiply with C before adding A o B - */ - void add_kronecker_tensor_product(Core::LinAlg::Matrix<6, 9>& C, const double scalar_AB, - const Core::LinAlg::Matrix<3, 3>& A, const Core::LinAlg::Matrix<3, 3>& B, - const double scalar_this); /*! @@ -445,16 +425,6 @@ namespace Core::LinAlg::FourTensorOperations const double scale, const Core::LinAlg::FourTensor<3>& four_tensor, const Core::LinAlg::Matrix<3, 3>& matrix); - /*! - * @brief Returns the double contraction of two 2nd order tensors - * - * @param[out] scalarContraction 0th order tensor \f$s = A_{ij} B^{ij}\f$ - * @param[in] matrix_A 2nd order tensor \f$A_{ij}\f$ - * @param[in] matrix_B 2nd order tensor \f$B^{ij}\f$ - */ - double contract_matrix_matrix( - const Core::LinAlg::Matrix<3, 3>& matrix_A, const Core::LinAlg::Matrix<3, 3>& matrix_B); - } // namespace Core::LinAlg::FourTensorOperations diff --git a/src/core/linalg/src/dense/4C_linalg_tensor_conversion.hpp b/src/core/linalg/src/dense/4C_linalg_tensor_conversion.hpp index da917e4e58c..3c8140cfe36 100644 --- a/src/core/linalg/src/dense/4C_linalg_tensor_conversion.hpp +++ b/src/core/linalg/src/dense/4C_linalg_tensor_conversion.hpp @@ -15,6 +15,7 @@ #include "4C_linalg_tensor.hpp" #include "4C_linalg_tensor_internals.hpp" +#include #include #include #include @@ -226,6 +227,89 @@ namespace Core::LinAlg } } + /*! + * @brief Creates a 6x9 Voigt matrix from a 4th order tensor that has the minor symmetry in its + * first index pair (C_ijkl = C_jikl). + * + * The first (symmetric) index pair is stored in stress-like 6-Voigt notation, the second + * (non-symmetric) index pair as a 9-vector. + */ + template + Core::LinAlg::Matrix<6, 9, T> make_6x9_voigt_matrix_from_tensor( + const Core::LinAlg::Tensor& tensor) + { + constexpr std::array, 6> row_index = { + {{0, 0}, {1, 1}, {2, 2}, {0, 1}, {1, 2}, {0, 2}}}; + constexpr std::array, 9> col_index = { + {{0, 0}, {1, 1}, {2, 2}, {0, 1}, {1, 2}, {0, 2}, {1, 0}, {2, 1}, {2, 0}}}; + + Core::LinAlg::Matrix<6, 9, T> matrix_voigt; + for (std::size_t r = 0; r < 6; ++r) + { + for (std::size_t c = 0; c < 9; ++c) + { + matrix_voigt(r, c) = + 0.5 * (tensor(row_index[r][0], row_index[r][1], col_index[c][0], col_index[c][1]) + + tensor(row_index[r][1], row_index[r][0], col_index[c][0], col_index[c][1])); + } + } + return matrix_voigt; + } + + /*! + * @brief Creates a 9x6 Voigt matrix from a 4th order tensor that has the minor symmetry in its + * second index pair (C_ijkl = C_ijlk). + * + * The first (non-symmetric) index pair is stored as a 9-vector, the second (symmetric) index + * pair in stress-like 6-Voigt notation. + */ + template + Core::LinAlg::Matrix<9, 6, T> make_9x6_voigt_matrix_from_tensor( + const Core::LinAlg::Tensor& tensor) + { + constexpr std::array, 9> row_index = { + {{0, 0}, {1, 1}, {2, 2}, {0, 1}, {1, 2}, {0, 2}, {1, 0}, {2, 1}, {2, 0}}}; + constexpr std::array, 6> col_index = { + {{0, 0}, {1, 1}, {2, 2}, {0, 1}, {1, 2}, {0, 2}}}; + + Core::LinAlg::Matrix<9, 6, T> matrix_voigt; + for (std::size_t r = 0; r < 9; ++r) + { + for (std::size_t c = 0; c < 6; ++c) + { + matrix_voigt(r, c) = + 0.5 * (tensor(row_index[r][0], row_index[r][1], col_index[c][0], col_index[c][1]) + + tensor(row_index[r][0], row_index[r][1], col_index[c][1], col_index[c][0])); + } + } + return matrix_voigt; + } + + /*! + * @brief Creates a 6x6 stress-like Voigt matrix from a (minor-)symmetric 4th order tensor. + * + * The minor symmetries (IJ) and (KL) are encoded in the symmetric tensor, so its components map + * directly to stress-like 6-Voigt notation. The result may still be a non-symmetric 6x6 matrix + * if the tensor lacks major symmetry (C_IJKL != C_KLIJ). + */ + template + Core::LinAlg::Matrix<6, 6, T> make_6x6_voigt_matrix_from_tensor( + const Core::LinAlg::SymmetricTensor& tensor) + { + constexpr std::array, 6> vi = { + {{0, 0}, {1, 1}, {2, 2}, {0, 1}, {1, 2}, {0, 2}}}; + + Core::LinAlg::Matrix<6, 6, T> result; + for (std::size_t r = 0; r < 6; ++r) + { + for (std::size_t c = 0; c < 6; ++c) + { + result(r, c) = tensor(vi[r][0], vi[r][1], vi[c][0], vi[c][1]); + } + } + return result; + } + /*! * @brief Creates a strain-like Voigt notation matrix from a symmetric tensor. * diff --git a/src/core/linalg/tests/4C_linalg_tensor_conversion_test.cpp b/src/core/linalg/tests/4C_linalg_tensor_conversion_test.cpp index d124bfe7013..a2f7740713f 100644 --- a/src/core/linalg/tests/4C_linalg_tensor_conversion_test.cpp +++ b/src/core/linalg/tests/4C_linalg_tensor_conversion_test.cpp @@ -12,6 +12,7 @@ #include "4C_linalg_tensor_conversion.hpp" #include "4C_linalg_fixedsizematrix.hpp" +#include "4C_linalg_fixedsizematrix_tensor_products.hpp" #include "4C_linalg_symmetric_tensor.hpp" #include "4C_linalg_symmetric_tensor_eigen.hpp" #include "4C_linalg_tensor_generators.hpp" @@ -314,6 +315,82 @@ namespace EXPECT_DOUBLE_EQ(nested_array[1][1], 4.0); EXPECT_DOUBLE_EQ(nested_array[2][1], 6.0); } + TEST(TensorConversionTest, Make6x9VoigtMatrixFromTensorTest) + { + // arbitrary (non-symmetric) 4th order tensor; both paths apply the same 1st-pair symmetrization + Core::LinAlg::Tensor T{}; + Core::LinAlg::FourTensor<3> ft(true); + int v = 1; + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 3; ++k) + for (int l = 0; l < 3; ++l) + { + const double val = 0.1 * (v++); + T(i, j, k, l) = val; + ft(i, j, k, l) = val; + } + + const Core::LinAlg::Matrix<6, 9> new_voigt = Core::LinAlg::make_6x9_voigt_matrix_from_tensor(T); + Core::LinAlg::Matrix<6, 9> old_voigt(Core::LinAlg::Initialization::zero); + Core::LinAlg::Voigt::setup_6x9_voigt_matrix_from_four_tensor(old_voigt, ft); + + FOUR_C_EXPECT_NEAR(new_voigt, old_voigt, 1e-12); + } + + TEST(TensorConversionTest, Make9x6VoigtMatrixFromTensorTest) + { + // arbitrary (non-symmetric) 4th order tensor; both paths apply the same 2nd-pair symmetrization + Core::LinAlg::Tensor T{}; + Core::LinAlg::FourTensor<3> ft(true); + int v = 1; + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 3; ++k) + for (int l = 0; l < 3; ++l) + { + const double val = 0.1 * (v++); + T(i, j, k, l) = val; + ft(i, j, k, l) = val; + } + + const Core::LinAlg::Matrix<9, 6> new_voigt = Core::LinAlg::make_9x6_voigt_matrix_from_tensor(T); + Core::LinAlg::Matrix<9, 6> old_voigt(Core::LinAlg::Initialization::zero); + Core::LinAlg::Voigt::setup_9x6_voigt_matrix_from_four_tensor(old_voigt, ft); + + FOUR_C_EXPECT_NEAR(new_voigt, old_voigt, 1e-12); + } + + TEST(TensorConversionTest, Make6x6StressLikeVoigtMatrixFromTensorTest) + { + Core::LinAlg::Matrix<3, 3> A; + A(0, 0) = 1.0; + A(0, 1) = 2.0; + A(0, 2) = 3.0; + A(1, 0) = 0.5; + A(1, 1) = 4.0; + A(1, 2) = 1.2; + A(2, 0) = 7.0; + A(2, 1) = 0.3; + A(2, 2) = 6.0; + + Core::LinAlg::Tensor C_full{}; + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 3; ++k) + for (int l = 0; l < 3; ++l) + C_full(i, j, k, l) = 0.5 * (A(i, k) * A(j, l) + A(i, l) * A(j, k)); + const Core::LinAlg::SymmetricTensor C = + Core::LinAlg::assume_symmetry(C_full); + + const Core::LinAlg::Matrix<6, 6> result = Core::LinAlg::make_6x6_voigt_matrix_from_tensor(C); + + // reference: add_kronecker_tensor_product called on non-symmetric matrix + Core::LinAlg::Matrix<6, 6> ref(Core::LinAlg::Initialization::zero); + Core::LinAlg::FourTensorOperations::add_kronecker_tensor_product(ref, 1.0, A, A, 0.0); + + FOUR_C_EXPECT_NEAR(result, ref, 1e-12); + } } // namespace FOUR_C_NAMESPACE_CLOSE \ No newline at end of file diff --git a/src/mat/4C_mat_elasthyper_service.cpp b/src/mat/4C_mat_elasthyper_service.cpp index 12282f8bb9c..65a3d84b11a 100644 --- a/src/mat/4C_mat_elasthyper_service.cpp +++ b/src/mat/4C_mat_elasthyper_service.cpp @@ -12,6 +12,7 @@ #include "4C_linalg_fixedsizematrix_voigt_notation.hpp" #include "4C_linalg_symmetric_tensor_eigen.hpp" #include "4C_linalg_tensor_conversion.hpp" +#include "4C_linalg_tensor_einstein.hpp" #include "4C_linalg_tensor_generators.hpp" #include "4C_linalg_utils_densematrix_eigen.hpp" #include "4C_linalg_vector.hpp" @@ -577,32 +578,24 @@ void Mat::elast_hyper_check_polyconvexity(const Core::LinAlg::Tensor& iFinM, - const Core::LinAlg::SymmetricTensor& CM, Core::LinAlg::Matrix<6, 6>& dCedC, - Core::LinAlg::Matrix<6, 9>& dCediFin) + const Core::LinAlg::SymmetricTensor& CM, + Core::LinAlg::SymmetricTensor& dCedC, + Core::LinAlg::Tensor& dCediFin) { - Core::LinAlg::Matrix<3, 3> iFinM_mat = Core::LinAlg::make_matrix_view(iFinM); - const Core::LinAlg::Matrix<3, 3> C_mat = Core::LinAlg::make_matrix(Core::LinAlg::get_full(CM)); - // auxiliaries - Core::LinAlg::Matrix<3, 3> id3x3(Core::LinAlg::Initialization::zero); - for (int i = 0; i < 3; ++i) id3x3(i, i) = 1.0; - Core::LinAlg::Matrix<9, 9> temp9x9(Core::LinAlg::Initialization::zero); - Core::LinAlg::FourTensor<3> tempFourTensor(true); + // F_in^{-T} and the 2nd order identity tensor + const Core::LinAlg::Tensor iFinT = Core::LinAlg::transpose(iFinM); + const Core::LinAlg::SymmetricTensor id = + Core::LinAlg::TensorGenerators::identity; // \frac{\partial C^e}{\partial C} - dCedC.clear(); - Core::LinAlg::Matrix<3, 3> iFinTM(Core::LinAlg::Initialization::zero); - iFinTM.multiply_nt(1.0, id3x3, iFinM_mat, 0.0); - Core::LinAlg::FourTensorOperations::add_kronecker_tensor_product(dCedC, 1.0, iFinTM, iFinTM, 0.0); + dCedC = Core::LinAlg::assume_symmetry(0.5 * (Core::LinAlg::einsum<"ik", "jl">(iFinT, iFinT) + + Core::LinAlg::einsum<"il", "jk">(iFinT, iFinT))); + + const Core::LinAlg::Tensor iFinTC = Core::LinAlg::dot(iFinT, CM); // \frac{\partial C^e}{\partial F_{in}^{-1}} - dCediFin.clear(); - Core::LinAlg::Matrix<3, 3> iFinTCM(Core::LinAlg::Initialization::zero); - iFinTCM.multiply_tn(1.0, iFinM_mat, C_mat, 0.0); - temp9x9.clear(); - Core::LinAlg::FourTensorOperations::add_adbc_tensor_product(1.0, id3x3, iFinTCM, temp9x9); - Core::LinAlg::FourTensorOperations::add_non_symmetric_product(1.0, iFinTCM, id3x3, temp9x9); - Core::LinAlg::Voigt::setup_four_tensor_from_9x9_voigt_matrix(tempFourTensor, temp9x9); - Core::LinAlg::Voigt::setup_6x9_voigt_matrix_from_four_tensor(dCediFin, tempFourTensor); + dCediFin = + Core::LinAlg::einsum<"ad", "bc">(id, iFinTC) + Core::LinAlg::einsum<"ac", "bd">(iFinTC, id); } FOUR_C_NAMESPACE_CLOSE diff --git a/src/mat/4C_mat_elasthyper_service.hpp b/src/mat/4C_mat_elasthyper_service.hpp index d5b48592d27..879c8487458 100644 --- a/src/mat/4C_mat_elasthyper_service.hpp +++ b/src/mat/4C_mat_elasthyper_service.hpp @@ -379,15 +379,16 @@ namespace Mat * @param[in] iFinM Inverse inelastic deformation gradient * @param[in] CM Right Cauchy-Green deformation tensor * @param[out] dCedC Partial derivative of the elastic right CG tensor w.r.t. right CG - * tensor (Voigt stress-stress notation) + * tensor (symmetric 4th order tensor) * @param[out] dCediFin Partial derivative of the elastic right CG tensor w.r.t. inelastic - * deformation gradient (Voigt stress notation) + * deformation gradient (full 4th order tensor) * */ void elast_hyper_get_derivs_of_elastic_right_cg_tensor( const Core::LinAlg::Tensor& iFinM, - const Core::LinAlg::SymmetricTensor& CM, Core::LinAlg::Matrix<6, 6>& dCedC, - Core::LinAlg::Matrix<6, 9>& dCediFin); + const Core::LinAlg::SymmetricTensor& CM, + Core::LinAlg::SymmetricTensor& dCedC, + Core::LinAlg::Tensor& dCediFin); /** * \brief Class for holding the summand formulation properties diff --git a/src/mat/4C_mat_inelastic_defgrad_factors.cpp b/src/mat/4C_mat_inelastic_defgrad_factors.cpp index 89d8220fa52..cb1e34ebdec 100644 --- a/src/mat/4C_mat_inelastic_defgrad_factors.cpp +++ b/src/mat/4C_mat_inelastic_defgrad_factors.cpp @@ -1990,8 +1990,8 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantities( // determine scalar quantities of invariants / pseudoinvariants needed to compute the // equivalent tensile stress double Mtheta_dev_sym_contract_Mtheta_dev_sym = - Core::LinAlg::FourTensorOperations::contract_matrix_matrix( - state_quantities.curr_Mtheta_dev_sym_M, state_quantities.curr_Mtheta_dev_sym_M); + Core::LinAlg::ddot(Core::LinAlg::make_tensor_view(state_quantities.curr_Mtheta_dev_sym_M), + Core::LinAlg::make_tensor_view(state_quantities.curr_Mtheta_dev_sym_M)); Core::LinAlg::Matrix<3, 3> Mtheta_dev_sym_squared_M(Core::LinAlg::Initialization::zero); Mtheta_dev_sym_squared_M.multiply_nn( 1.0, state_quantities.curr_Mtheta_dev_sym_M, state_quantities.curr_Mtheta_dev_sym_M, 0.0); @@ -2198,9 +2198,14 @@ Mat::InelasticDefgradTransvIsotropElastViscoplast::evaluate_state_quantity_deriv // compute the relevant derivatives of the elastic right Cauchy-Green deformation tensor + Core::LinAlg::SymmetricTensor dCedC_tensor; + Core::LinAlg::Tensor dCediFin_tensor; Mat::elast_hyper_get_derivs_of_elastic_right_cg_tensor(Core::LinAlg::make_tensor(iFinM), - Core::LinAlg::assume_symmetry(Core::LinAlg::make_tensor(CM)), - state_quantity_derivatives.curr_dCedC, state_quantity_derivatives.curr_dCediFin); + Core::LinAlg::assume_symmetry(Core::LinAlg::make_tensor(CM)), dCedC_tensor, dCediFin_tensor); + state_quantity_derivatives.curr_dCedC = + Core::LinAlg::make_6x6_voigt_matrix_from_tensor(dCedC_tensor); + state_quantity_derivatives.curr_dCediFin = + Core::LinAlg::make_6x9_voigt_matrix_from_tensor(dCediFin_tensor); // save these also as four tensors Core::LinAlg::FourTensor<3> dCediFin_FourTensor(true); Core::LinAlg::Voigt::setup_four_tensor_from_6x9_voigt_matrix( diff --git a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp index 2c19630928a..86d56353a28 100644 --- a/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp +++ b/src/mat/4C_mat_multiplicative_split_defgrad_elasthyper.cpp @@ -692,8 +692,12 @@ void Mat::MultiplicativeSplitDefgradElastHyper::evaluate_kin_quant_elast( Core::LinAlg::Voigt::matrix_3x3_to_9x1(CiFiniCeM, CiFiniCe9x1); // derivatives of the elastic right CG + Core::LinAlg::SymmetricTensor dCedC_tensor; + Core::LinAlg::Tensor dCediFin_tensor; Mat::elast_hyper_get_derivs_of_elastic_right_cg_tensor(Core::LinAlg::make_tensor(iFinM), - Core::LinAlg::assume_symmetry(Core::LinAlg::make_tensor(CM)), dCedC, dCediFin); + Core::LinAlg::assume_symmetry(Core::LinAlg::make_tensor(CM)), dCedC_tensor, dCediFin_tensor); + dCedC = Core::LinAlg::make_6x6_voigt_matrix_from_tensor(dCedC_tensor); + dCediFin = Core::LinAlg::make_6x9_voigt_matrix_from_tensor(dCediFin_tensor); } /*--------------------------------------------------------------------*