From 73fc3494c55f49b9202d757a4e0264994d7e5bbf Mon Sep 17 00:00:00 2001 From: Maien Hamed Date: Tue, 20 Jan 2026 22:53:03 -0700 Subject: [PATCH 1/2] Add the code for ALE large-deformation thermoplasticity --- ALE_Finite_Strain_Plasticity/.gitignore | 1 + ALE_Finite_Strain_Plasticity/README.md | 17 + .../src/BodyForceApplier.h | 51 + .../src/BoundaryUnidirectionalPenaltySpec.h | 40 + .../src/CMakeLists.txt | 60 + ALE_Finite_Strain_Plasticity/src/Constants.h | 73 + .../src/ConstitModelUpdateFlags.h | 64 + .../src/ConstitutiveModelRequest.h | 495 +++ .../src/ConvectionBoundaryConditionApplier.h | 80 + ALE_Finite_Strain_Plasticity/src/DoFSystem.h | 62 + ...onentialHardeningElastoplasticMaterial.cpp | 234 ++ ...xponentialHardeningElastoplasticMaterial.h | 88 + ...ntialHardeningThermoviscoplasticYieldLaw.h | 102 + .../src/IncrementInterpolationHandler.h | 89 + .../src/InterpolatoryConstraintApplier.h | 81 + .../JohnsonCookThermoviscoplasticYieldLaw.h | 297 ++ ALE_Finite_Strain_Plasticity/src/LBCSystem.h | 114 + ALE_Finite_Strain_Plasticity/src/Material.h | 58 + .../src/MixedFEProjector.h | 99 + .../src/NewtonStepSystem.h | 135 + .../src/PlasticityLabProg.cpp | 3627 +++++++++++++++++ .../src/PlasticityLabProg.h | 456 +++ .../src/PlasticityLabProgDrivers.cpp | 1450 +++++++ .../src/PointHistory.h | 79 + .../src/ReferencePoint.h | 40 + .../src/RemappedPoint.h | 40 + .../src/RotationFunction.h | 107 + .../src/ScaleComponentFunction.h | 56 + .../src/ScaleZFunction.h | 51 + .../src/TensorUtilities.h | 90 + .../src/ThermoPlasticMaterial.cpp | 486 +++ .../src/ThermoPlasticMaterial.h | 100 + .../src/TimeRateRequest.h | 370 ++ .../src/TimeRateUpdateFlags.h | 57 + ALE_Finite_Strain_Plasticity/src/main.cpp | 128 + .../src/symmetric_tensor_entries.h | 149 + ALE_Finite_Strain_Plasticity/src/utilities.h | 20 + 37 files changed, 9546 insertions(+) create mode 100644 ALE_Finite_Strain_Plasticity/.gitignore create mode 100644 ALE_Finite_Strain_Plasticity/README.md create mode 100644 ALE_Finite_Strain_Plasticity/src/BodyForceApplier.h create mode 100644 ALE_Finite_Strain_Plasticity/src/BoundaryUnidirectionalPenaltySpec.h create mode 100644 ALE_Finite_Strain_Plasticity/src/CMakeLists.txt create mode 100644 ALE_Finite_Strain_Plasticity/src/Constants.h create mode 100644 ALE_Finite_Strain_Plasticity/src/ConstitModelUpdateFlags.h create mode 100644 ALE_Finite_Strain_Plasticity/src/ConstitutiveModelRequest.h create mode 100644 ALE_Finite_Strain_Plasticity/src/ConvectionBoundaryConditionApplier.h create mode 100644 ALE_Finite_Strain_Plasticity/src/DoFSystem.h create mode 100644 ALE_Finite_Strain_Plasticity/src/ExponentialHardeningElastoplasticMaterial.cpp create mode 100644 ALE_Finite_Strain_Plasticity/src/ExponentialHardeningElastoplasticMaterial.h create mode 100644 ALE_Finite_Strain_Plasticity/src/ExponentialHardeningThermoviscoplasticYieldLaw.h create mode 100644 ALE_Finite_Strain_Plasticity/src/IncrementInterpolationHandler.h create mode 100644 ALE_Finite_Strain_Plasticity/src/InterpolatoryConstraintApplier.h create mode 100644 ALE_Finite_Strain_Plasticity/src/JohnsonCookThermoviscoplasticYieldLaw.h create mode 100644 ALE_Finite_Strain_Plasticity/src/LBCSystem.h create mode 100644 ALE_Finite_Strain_Plasticity/src/Material.h create mode 100644 ALE_Finite_Strain_Plasticity/src/MixedFEProjector.h create mode 100644 ALE_Finite_Strain_Plasticity/src/NewtonStepSystem.h create mode 100644 ALE_Finite_Strain_Plasticity/src/PlasticityLabProg.cpp create mode 100644 ALE_Finite_Strain_Plasticity/src/PlasticityLabProg.h create mode 100644 ALE_Finite_Strain_Plasticity/src/PlasticityLabProgDrivers.cpp create mode 100644 ALE_Finite_Strain_Plasticity/src/PointHistory.h create mode 100644 ALE_Finite_Strain_Plasticity/src/ReferencePoint.h create mode 100644 ALE_Finite_Strain_Plasticity/src/RemappedPoint.h create mode 100644 ALE_Finite_Strain_Plasticity/src/RotationFunction.h create mode 100644 ALE_Finite_Strain_Plasticity/src/ScaleComponentFunction.h create mode 100644 ALE_Finite_Strain_Plasticity/src/ScaleZFunction.h create mode 100644 ALE_Finite_Strain_Plasticity/src/TensorUtilities.h create mode 100644 ALE_Finite_Strain_Plasticity/src/ThermoPlasticMaterial.cpp create mode 100644 ALE_Finite_Strain_Plasticity/src/ThermoPlasticMaterial.h create mode 100644 ALE_Finite_Strain_Plasticity/src/TimeRateRequest.h create mode 100644 ALE_Finite_Strain_Plasticity/src/TimeRateUpdateFlags.h create mode 100644 ALE_Finite_Strain_Plasticity/src/main.cpp create mode 100644 ALE_Finite_Strain_Plasticity/src/symmetric_tensor_entries.h create mode 100644 ALE_Finite_Strain_Plasticity/src/utilities.h diff --git a/ALE_Finite_Strain_Plasticity/.gitignore b/ALE_Finite_Strain_Plasticity/.gitignore new file mode 100644 index 00000000..d1638636 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file diff --git a/ALE_Finite_Strain_Plasticity/README.md b/ALE_Finite_Strain_Plasticity/README.md new file mode 100644 index 00000000..e2f2bdca --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/README.md @@ -0,0 +1,17 @@ +## To run: +``` +# in a build directory: +$ cmake -DDEAL_II_DIR= +$ make release +$ make -j 8 && $HOME/share/bin/mpirun -n 18 ./PlasticityLab + +# The triangulation is configured in PlasticityLabProgDrivers.cpp in run() +# The material is configured in main.cpp +# The timestep is configured in PlasticityLabProg.h +``` + +## Citation: +If you use this code as part of your work, please cite: +Hamed, M.M.O., McBride, A.T. & Reddy, B.D. An ALE approach for large-deformation thermoplasticity with application to friction welding. Comput Mech 72, 803–826 (2023). +https://doi.org/10.1007/s00466-023-02303-0 + diff --git a/ALE_Finite_Strain_Plasticity/src/BodyForceApplier.h b/ALE_Finite_Strain_Plasticity/src/BodyForceApplier.h new file mode 100644 index 00000000..d3edf695 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/BodyForceApplier.h @@ -0,0 +1,51 @@ +/* + * BodyForceApplier.h + * + * Created on: 14 Jan 2015 + * Author: maien + */ + +#ifndef BODYFORCEAPPLIER_H_ +#define BODYFORCEAPPLIER_H_ + +namespace PlasticityLab { + + template + class BodyForceApplier { + public: + BodyForceApplier(); + BodyForceApplier(int direction, Number bodyForceMagnitude = 0); + virtual ~BodyForceApplier(); + inline Number apply(const unsigned int direction, + const Number shapeFunctionValue, + const Number JxW) const; + private: + const unsigned int direction; + const Number bodyForceMagnitude; + }; + + + template + BodyForceApplier:: + BodyForceApplier(int direction, Number bodyForceMagnitude) + : direction(direction), bodyForceMagnitude(bodyForceMagnitude) { + } + + + template + BodyForceApplier::~BodyForceApplier() { + } + + template + Number BodyForceApplier:: + apply(const unsigned int direction, + const Number shapeFunctionValue, + const Number JxW) const { + if (this->direction == direction) + return -shapeFunctionValue * this->bodyForceMagnitude * JxW; + return 0.0; + } + +} /* namespace PlasticityLab */ + +#endif /* BODYFORCEAPPLIER_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/BoundaryUnidirectionalPenaltySpec.h b/ALE_Finite_Strain_Plasticity/src/BoundaryUnidirectionalPenaltySpec.h new file mode 100644 index 00000000..d682ed52 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/BoundaryUnidirectionalPenaltySpec.h @@ -0,0 +1,40 @@ +/* + * BoundaryUnidirectionalPenaltySpec.h + * + * Created on: 04 May 2021 + * Author: maien + */ + +#ifndef BOUNDARYUNIDIRECTIONALPENALTYSPEC_H_ +#define BOUNDARYUNIDIRECTIONALPENALTYSPEC_H_ + +namespace PlasticityLab { + + template + class BoundaryUnidirectionalPenaltySpec { + public: + BoundaryUnidirectionalPenaltySpec( + unsigned int boundary_id, + Number reference_displacement_increment, + Number residual_force, + Number quadratic_spring_factor) : + boundary_id(boundary_id), + reference_displacement_increment(reference_displacement_increment), + residual_force(residual_force), + quadratic_spring_factor(quadratic_spring_factor) {} + + unsigned int get_boundary_id() const { return boundary_id; } + Number get_reference_displacement_increment() const { return reference_displacement_increment; } + Number get_residual_force() const { return residual_force; } + Number get_quadratic_spring_factor() const { return quadratic_spring_factor; } + + private: + const unsigned int boundary_id; + const Number quadratic_spring_factor; + const Number reference_displacement_increment; + const Number residual_force; + }; + +} /* namespace PlasticityLab */ + +#endif /* BOUNDARYUNIDIRECTIONALPENALTYSPEC_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/CMakeLists.txt b/ALE_Finite_Strain_Plasticity/src/CMakeLists.txt new file mode 100644 index 00000000..e6c5e9fa --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/CMakeLists.txt @@ -0,0 +1,60 @@ +## +# CMake script for the PlasticityLab project: +## + +# Set the name of the project and target: +SET(TARGET "PlasticityLab") + +# Declare all source files the target consists of. Here, this is only +# the one step-X.cc file, but as you expand your project you may wish +# to add other source files as well. If your project becomes much larger, +# you may want to either replace the following statement by something like +# FILE(GLOB_RECURSE TARGET_SRC "source/*.cc") +# FILE(GLOB_RECURSE TARGET_INC "include/*.h") +# SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC}) +# or switch altogether to the large project CMakeLists.txt file discussed +# in the "CMake in user projects" page accessible from the "User info" +# page of the documentation. +FILE(GLOB_RECURSE TARGET_SRC "*.cpp") +FILE(GLOB_RECURSE TARGET_INC "*.h") +SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC}) + +# Define the output that should be cleaned: +set(CLEAN_UP_FILES *.vtu *.pvtu *.visit) + +# Usually, you will not need to modify anything beyond this point... + +cmake_minimum_required(VERSION 3.13.4) + +find_package(deal.II 9.7.0 + HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR} + ) +if(NOT ${deal.II_FOUND}) + message(FATAL_ERROR "\n" + "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n" + "You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to cmake\n" + "or set an environment variable \"DEAL_II_DIR\" that contains this path." + ) +endif() + +# +# Are all dependencies fulfilled? +# +if(NOT DEAL_II_WITH_MPI OR NOT DEAL_II_WITH_P4EST OR NOT DEAL_II_WITH_TRILINOS) + message(FATAL_ERROR " +Error! This project requires a deal.II library that was configured with the following options: + DEAL_II_WITH_MPI = ON + DEAL_II_WITH_P4EST = ON + DEAL_II_WITH_TRILINOS = ON +However, the deal.II library found at ${DEAL_II_PATH} was configured with these options: + DEAL_II_WITH_MPI = ${DEAL_II_WITH_MPI} + DEAL_II_WITH_P4EST = ${DEAL_II_WITH_P4EST} + DEAL_II_WITH_TRILINOS = ${DEAL_II_WITH_TRILINOS} +This conflicts with the requirements." + ) +endif() + +deal_ii_initialize_cached_variables() +project(${TARGET} CXX) + +deal_ii_invoke_autopilot() diff --git a/ALE_Finite_Strain_Plasticity/src/Constants.h b/ALE_Finite_Strain_Plasticity/src/Constants.h new file mode 100644 index 00000000..ac59b368 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/Constants.h @@ -0,0 +1,73 @@ +/* + * Constants.h + * + * Created on: 10 Feb 2015 + * Author: maien + */ + +#ifndef CONSTANTS_H_ +#define CONSTANTS_H_ + +namespace PlasticityLab { + + + template + class Constants { + public: + inline static const Number one_third() { + return static_cast(0.33333333333333333333333333333333333333333333333333); + } + + inline static const Number sqrt2thirds() { + return static_cast(0.81649658092772603273242802490196379732198249355222); + } + + inline static const Number two_thirds() { + return static_cast(0.66666666666666666666666666666666666666666666666666); + } + + inline static const Number sqrt_half() { + return static_cast(0.70710678118654752440084436210484903928483593768847); + } + + inline static const Number sqrt_2() { + return static_cast(1.41421356237309504880168872420969807856967187537694); + } + + + inline static const Number one_over_dim() { + if(3==dim) + return static_cast(0.33333333333333333333333333333333333333333333333333); + else if (2==dim) + return static_cast(0.5); + else + return static_cast(1./static_cast(dim)); + } + + inline static const Number two_over_dim() { + if(3==dim) + return static_cast(0.66666666666666666666666666666666666666666666666666); + else if (2==dim) + return static_cast(1.0); + else + return static_cast(2./static_cast(dim)); + } + + }; + + inline void get_generalized_alpha_method_params( + double *alpha_m, + double *alpha_f, + double *gamma, + double *beta, + double rho_infty + ) { + *alpha_m = (2. * rho_infty - 1.)/(rho_infty + 1.); + *alpha_f = rho_infty / (rho_infty + 1.); + *gamma = 0.5 - *alpha_m + *alpha_f; + *beta = 0.25 * (1. - *alpha_m + *alpha_f) * (1. - *alpha_m + *alpha_f); + } + +} /* namespace PlasticityLab */ + +#endif /* CONSTANTS_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/ConstitModelUpdateFlags.h b/ALE_Finite_Strain_Plasticity/src/ConstitModelUpdateFlags.h new file mode 100644 index 00000000..147e6d0e --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ConstitModelUpdateFlags.h @@ -0,0 +1,64 @@ +/* + * ConstitModelUpdateFlags.h + * + * Created on: 04 Jan 2015 + * Author: maien + */ + +#ifndef CONSTITMODELUPDATEFLAGS_H_ +#define CONSTITMODELUPDATEFLAGS_H_ + +namespace PlasticityLab { + + enum ConstitutiveModelUpdateFlags { + update_default = 0x0000, + update_pressure = 0x0001, + update_pressure_tangent = 0x0002, + update_stress_deviator = 0x0004, + update_stress_deviator_tangent = 0x0008, + update_heat_flux = 0x0010, + update_heat_flux_tangent = 0x0020, + update_elastic_entropy = 0x0040, + update_elastic_entropy_tangent = 0x0080, + update_mechanical_dissipation = 0x0100, + update_mechanical_dissipation_tangent = 0x0200, + update_thermoelastic_heating = 0x0400, + update_thermoelastic_heating_tangent = 0x0800, + update_stored_heat = 0x1000, + update_stored_heat_tangent = 0x2000, + update_material_point_history = 0x4000 + }; + + inline + ConstitutiveModelUpdateFlags + operator | (ConstitutiveModelUpdateFlags f1, ConstitutiveModelUpdateFlags f2) { + return static_cast ( + static_cast (f1) | + static_cast (f2)); + } + + inline + const ConstitutiveModelUpdateFlags & + operator |= (ConstitutiveModelUpdateFlags &f1, ConstitutiveModelUpdateFlags f2) { + f1 = f1 | f2; + return f1; + } + + inline + ConstitutiveModelUpdateFlags + operator & (ConstitutiveModelUpdateFlags f1, ConstitutiveModelUpdateFlags f2) { + return static_cast ( + static_cast (f1) & + static_cast (f2)); + } + + inline + const ConstitutiveModelUpdateFlags & + operator &= (ConstitutiveModelUpdateFlags &f1, ConstitutiveModelUpdateFlags f2) { + f1 = f1 & f2; + return f1; + } + +} /* namespace PlasticityLab */ + +#endif /*CONSTITMODELUPDATEFLAGS_H_*/ diff --git a/ALE_Finite_Strain_Plasticity/src/ConstitutiveModelRequest.h b/ALE_Finite_Strain_Plasticity/src/ConstitutiveModelRequest.h new file mode 100644 index 00000000..79b718b1 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ConstitutiveModelRequest.h @@ -0,0 +1,495 @@ +/* + * ConstitutiveModelRequest.h + * + * Created on: 03 Feb 2015 + * Author: maien + */ + +#ifndef CONSTITUTIVEMODELREQUEST_H_ +#define CONSTITUTIVEMODELREQUEST_H_ + +#include +#include + +#include "Constants.h" +#include "ConstitModelUpdateFlags.h" +#include "TensorUtilities.h" + +namespace PlasticityLab { + + template + class ConstitutiveModelRequest { + public: + ConstitutiveModelRequest(ConstitutiveModelUpdateFlags); + virtual ~ConstitutiveModelRequest(); + + // Interface to be used by request client (FE system assembler) + // --request configuration stage-- + void set_deformation_gradient(const Tensor<2, dim, Number> &deformation_gradient); + void set_deformation_Jacobian(const Number deformation_Jacobian); + void set_unprojected_deformation_Jacobian(const Number unprojected_deformation_Jacobian); + void set_previous_deformation_Jacobian(const Number previous_deformation_Jacobian); + void set_deformation_Jacobian_time_rate(const Number deformation_Jacobian_time_rate); + void set_temperature(const Number temperature); + void set_previous_temperature(const Number previous_temperature); + void set_temperature_time_rate(const Number temperature_time_rate); + void set_thermal_gradient(const Tensor<1, dim, Number> &thermalGradient); + void set_time_increment(const Number timeIncrement); + + // Interface to be used by request client (FE system assembler) + // --request response retrieval and interrogation stage-- + Number get_pressure(); + Number get_pressure_tangent(const Number volume_change_increment); + SymmetricTensor<2, dim, Number> get_stress_deviator() const; + SymmetricTensor<2, dim, Number> get_stress_deviator_tangent(const Tensor<2, dim, Number> &strain_increment) const; + Tensor<1, dim, Number> get_heat_flux() const; + Tensor<1, dim, Number> get_heat_flux_tangent(const Tensor<1, dim, Number> &thermal_gradient_increment) const; + Number get_stored_heat_rate() const; + Number get_stored_heat_rate_tangent(const Number temperature_increment) const; + Number get_elastic_entropy() const; + bool get_is_plastic() const; + Number get_elastic_entropy_tangent(const Number temperature_increment) const; + Number get_mechanical_dissipation() const; + Number get_mechanical_dissipation_tangent(const Number temperature_increment) const; + Number get_thermo_elastic_heating() const; + Number get_thermo_elastic_heating_tangent(const Number temperature_increment) const; + + // interface used by constitutive model object to perform computation + // TODO consider hiding this interface and exposing it through adapter + ConstitutiveModelUpdateFlags get_update_flags() const; + Tensor<2, dim, Number> get_deformation_gradient() const; + Number get_deformation_Jacobian() const; + Number get_unprojected_deformation_Jacobian() const; + Number get_previous_deformation_Jacobian() const; + Number get_deformation_Jacobian_time_rate() const; + Number get_temperature() const; + Number get_previous_temperature() const; + Number get_temperature_time_rate() const; + Tensor<1, dim, Number> get_thermal_gradient() const; + Number get_time_increment() const; + + void set_pressure(Number pressure); + void set_stress_deviator(const SymmetricTensor<2, dim, Number> &stress_deviator); + void set_heat_flux(const Tensor<1, dim, Number> &heat_flux); + void set_stored_heat_rate(const Number stored_heat_rate); + void set_elastic_entropy(const Number elastic_entropy); + void set_mechanical_dissipation(const Number mechanical_dissipation); + void set_thermo_elastic_heating(const Number thermo_elastic_heating); + + // TODO this can be changed so that smaller objects can be set and used + // to construct the tangents than the full moduli tensors + void set_pressure_tangent_modulus(const Number pressure_tangent_modulus); + void set_b_e_bar(const SymmetricTensor<2, dim, Number> &b_e_bar); + void set_mu(const Number mu); + void set_is_plastic(const bool is_plastic); + void set_delta_gamma(const Number delta_gamma); + void set_dK(const Number dK); + void set_dH(const Number dH); + void set_heat_flux_tangent_moduli(const SymmetricTensor<2, dim, Number> &heat_flux_tangent_modului); + void set_stored_heat_rate_tangent_modulus(const Number stored_heat_rate_tangent_modulus); + void set_elastic_entropy_tangent_modulus(const Number elastic_entropy_tangent_modulus); + void set_mechanical_dissipation_tangent_modulus(const Number mechanicalDissipationTangentModulus); + void set_thermo_elastic_heating_tangent_modulus(const Number thermo_elastic_heating_tangent_modulus); + + protected: + ConstitutiveModelUpdateFlags update_flags; + + Tensor<2, dim, Number> deformation_gradient; + Number deformation_Jacobian, previous_deformation_Jacobian, deformation_Jacobian_time_rate; + Number unprojected_deformation_Jacobian; + Number temperature, previous_temperature, temperature_time_rate; + Tensor<1, dim, Number> thermal_gradient; + + Number pressure; + SymmetricTensor<2, dim, Number> stress_deviator; + Tensor<1, dim, Number> heat_flux; + Number stored_heat_rate; + Number elastic_entropy; + Number mechanical_dissipation; + Number thermo_elastic_heating; + + Number time_increment; + + bool is_plastic; + Number pressure_tangent_modulus; + Number dK, dH, mu, delta_gamma; + SymmetricTensor<2, dim, Number> b_e_bar; + SymmetricTensor<2, dim, Number> heat_flux_tangent_moduli; + Number stored_heat_rate_tangent_modulus; + Number elastic_entropy_tangent_modulus; + Number mechanical_dissipation_tangent_modulus; + Number thermo_elastic_heating_tangent_modulus; + }; + + template + ConstitutiveModelRequest:: + ConstitutiveModelRequest(ConstitutiveModelUpdateFlags update_flags): + update_flags(update_flags) { + is_plastic = true; // not necessarily elastic + } + + template + bool ConstitutiveModelRequest::get_is_plastic() const { + return is_plastic; + } + + template + ConstitutiveModelRequest::~ConstitutiveModelRequest() { } + + template + void ConstitutiveModelRequest:: + set_deformation_gradient(const Tensor<2, dim, Number> &deformation_gradient) { + this->deformation_gradient = deformation_gradient; + } + + template + void ConstitutiveModelRequest:: + set_deformation_Jacobian(Number deformation_Jacobian) { + this->deformation_Jacobian = deformation_Jacobian; + } + + template + void ConstitutiveModelRequest:: + set_unprojected_deformation_Jacobian(Number unprojected_deformation_Jacobian) { + this->unprojected_deformation_Jacobian = unprojected_deformation_Jacobian; + } + + template + void ConstitutiveModelRequest:: + set_previous_deformation_Jacobian(Number previous_deformation_Jacobian) { + this->previous_deformation_Jacobian = previous_deformation_Jacobian; + } + + template + void ConstitutiveModelRequest:: + set_deformation_Jacobian_time_rate(Number deformation_Jacobian_time_rate) { + this->deformation_Jacobian_time_rate = deformation_Jacobian_time_rate; + } + + template + void ConstitutiveModelRequest:: + set_temperature(const Number temperature) { + this->temperature = temperature; + } + + template + void ConstitutiveModelRequest:: + set_previous_temperature(const Number previous_temperature) { + this->previous_temperature = previous_temperature; + } + + template + void ConstitutiveModelRequest:: + set_temperature_time_rate(const Number temperature_time_rate) { + this->temperature_time_rate = temperature_time_rate; + } + + template + void ConstitutiveModelRequest:: + set_thermal_gradient(const Tensor<1, dim, Number> &thermal_gradient) { + this->thermal_gradient = thermal_gradient; + } + + template + void ConstitutiveModelRequest:: + set_time_increment(const Number time_increment) { + this->time_increment = time_increment; + } + + template + Number ConstitutiveModelRequest::get_pressure() { + return pressure; + } + + template + Number + ConstitutiveModelRequest:: + get_pressure_tangent(const Number volume_change_increment) { + return pressure_tangent_modulus * volume_change_increment; + } + + template + SymmetricTensor<2, dim, Number> ConstitutiveModelRequest:: + get_stress_deviator() const { + return stress_deviator; + } + + template + SymmetricTensor<2, dim, Number> ConstitutiveModelRequest:: + get_stress_deviator_tangent(const Tensor<2, dim, Number> &strain_increment) const { + const Number twothirds = Constants::two_thirds(); + const auto tensor_b_e_bar = static_cast >(b_e_bar); + SymmetricTensor<2, dim, Number> d_b_e_bar = symmetrize(2 * strain_increment * tensor_b_e_bar); + SymmetricTensor<2, dim, Number> d_dev_b_e_bar = get_log_of_tensor_variation(b_e_bar, d_b_e_bar); + SymmetricTensor<2, dim, Number> d_trial_stress_dev = mu * d_dev_b_e_bar; + + // TODO ensure that all the debugging tests were removed + if (is_plastic) { + // Number mu_bar = Constants::one_third() * mu * trace(b_e_bar); + // Number d_mu_bar = Constants::one_third() * mu * trace(d_b_e_bar); + // Number norm_dev_b_e_bar = (deviator(b_e_bar)).norm(); + // SymmetricTensor<2, dim, Number> dev_b_e_direction = deviator(b_e_bar) / norm_dev_b_e_bar; + Number mu_bar = mu; + Number d_mu_bar = 0; + + const auto epsilon_e_bar = get_log_of_tensor(b_e_bar); + Number norm_dev_b_e_bar = (epsilon_e_bar).norm(); + SymmetricTensor<2, dim, Number> dev_b_e_direction = epsilon_e_bar / norm_dev_b_e_bar; + + SymmetricTensor<2, dim, Number> d_dev_b_e_direction = + (1.0 / norm_dev_b_e_bar) * (d_dev_b_e_bar - dev_b_e_direction * (dev_b_e_direction * d_dev_b_e_bar)); + Number d_delta_gamma = (dev_b_e_direction * d_trial_stress_dev - 2 * d_mu_bar * delta_gamma) / (2 * mu_bar + twothirds * (dK + dH)); + + return deviator(d_trial_stress_dev + - ( 2 * mu_bar * delta_gamma * d_dev_b_e_direction + + 2 * mu_bar * d_delta_gamma * dev_b_e_direction + + 2 * d_mu_bar * delta_gamma * dev_b_e_direction)); + } + + return deviator(d_trial_stress_dev); + } + + template + Tensor<1, dim, Number> + ConstitutiveModelRequest::get_heat_flux() const { + return heat_flux; + } + + template + Tensor<1, dim, Number> + ConstitutiveModelRequest:: + get_heat_flux_tangent(const Tensor<1, dim, Number> &thermal_gradient_increment) const { + return heat_flux_tangent_moduli * thermal_gradient_increment; + } + + template + Number + ConstitutiveModelRequest::get_stored_heat_rate() const { + return stored_heat_rate; + } + + template + Number ConstitutiveModelRequest:: + get_stored_heat_rate_tangent(const Number temperature_increment) const { + return stored_heat_rate_tangent_modulus * temperature_increment; + } + + template + Number ConstitutiveModelRequest:: + get_elastic_entropy() const { + return elastic_entropy; + } + + template + Number ConstitutiveModelRequest:: + get_elastic_entropy_tangent(const Number temperature_increment) const { + return elastic_entropy_tangent_modulus * time_increment; + } + + template + Number ConstitutiveModelRequest:: + get_mechanical_dissipation() const { + return mechanical_dissipation; + } + + template + Number ConstitutiveModelRequest:: + get_mechanical_dissipation_tangent(const Number temperature_increment) const { + return mechanical_dissipation_tangent_modulus * temperature_increment; + } + + template + Number ConstitutiveModelRequest:: + get_thermo_elastic_heating() const { + return thermo_elastic_heating; + } + + template + Number ConstitutiveModelRequest:: + get_thermo_elastic_heating_tangent(const Number temperature_increment) const { + return thermo_elastic_heating_tangent_modulus * temperature_increment; + } + + template + ConstitutiveModelUpdateFlags ConstitutiveModelRequest:: + get_update_flags() const { + return update_flags; + } + + template + Tensor<2, dim, Number> ConstitutiveModelRequest:: + get_deformation_gradient() const { + return deformation_gradient; + } + + template + Number ConstitutiveModelRequest:: + get_deformation_Jacobian() const { + return deformation_Jacobian; + } + + template + Number ConstitutiveModelRequest:: + get_unprojected_deformation_Jacobian() const { + return unprojected_deformation_Jacobian; + } + + template + Number ConstitutiveModelRequest:: + get_previous_deformation_Jacobian() const { + return previous_deformation_Jacobian; + } + + template + Number ConstitutiveModelRequest:: + get_deformation_Jacobian_time_rate() const { + return deformation_Jacobian_time_rate; + } + + template + Number ConstitutiveModelRequest:: + get_temperature() const { + return temperature; + } + + template + Number ConstitutiveModelRequest:: + get_previous_temperature() const { + return previous_temperature; + } + + template + Number ConstitutiveModelRequest:: + get_temperature_time_rate() const { + return temperature_time_rate; + } + + template + Tensor<1, dim, Number> ConstitutiveModelRequest:: + get_thermal_gradient() const { + return thermal_gradient; + } + + template + Number ConstitutiveModelRequest:: + get_time_increment() const { + return time_increment; + } + + template + void ConstitutiveModelRequest:: + set_pressure(Number pressure) { + this->pressure = pressure; + } + + template + void ConstitutiveModelRequest:: + set_stress_deviator(const SymmetricTensor<2, dim, Number> &stress_deviator) { + this->stress_deviator = stress_deviator; + } + + template + void ConstitutiveModelRequest:: + set_b_e_bar(const SymmetricTensor<2, dim, Number> &b_e_bar) { + this->b_e_bar = b_e_bar; + } + + template + void ConstitutiveModelRequest:: + set_mu(const Number mu) { + this->mu = mu; + } + + template + void ConstitutiveModelRequest:: + set_is_plastic(const bool is_plastic) { + this->is_plastic = is_plastic; + } + + template + void ConstitutiveModelRequest:: + set_delta_gamma(const Number delta_gamma) { + this->delta_gamma = delta_gamma; + } + + template + void ConstitutiveModelRequest:: + set_dK(const Number dK) { + this->dK = dK; + } + + template + void ConstitutiveModelRequest:: + set_dH(const Number dH) { + this->dH = dH; + } + + template + void ConstitutiveModelRequest:: + set_heat_flux(const Tensor<1, dim, Number> &heat_flux) { + this->heat_flux = heat_flux; + } + + template + void ConstitutiveModelRequest:: + set_stored_heat_rate(const Number stored_heat_rate) { + this->stored_heat_rate = stored_heat_rate; + } + + template + void ConstitutiveModelRequest:: + set_elastic_entropy(const Number elastic_entropy) { + this->elastic_entropy = elastic_entropy; + } + + template + void ConstitutiveModelRequest:: + set_mechanical_dissipation(const Number mechanical_dissipation) { + this->mechanical_dissipation = mechanical_dissipation; + } + + template + void ConstitutiveModelRequest:: + set_thermo_elastic_heating(const Number thermo_elastic_heating) { + this->thermo_elastic_heating = thermo_elastic_heating; + } + + template + void ConstitutiveModelRequest:: + set_pressure_tangent_modulus(const Number pressure_tangent_modulus) { + this->pressure_tangent_modulus = pressure_tangent_modulus; + } + + template + void ConstitutiveModelRequest:: + set_heat_flux_tangent_moduli(const SymmetricTensor<2, dim, Number> &heat_flux_tangent_modului) { + this->heat_flux_tangent_moduli = heat_flux_tangent_modului; + } + + template + void ConstitutiveModelRequest:: + set_stored_heat_rate_tangent_modulus(const Number stored_heat_rate_tangent_modulus) { + this->stored_heat_rate_tangent_modulus = stored_heat_rate_tangent_modulus; + } + + template + void ConstitutiveModelRequest:: + set_elastic_entropy_tangent_modulus(const Number elastic_entropy_tangent_modulus) { + this->elastic_entropy_tangent_modulus = elastic_entropy_tangent_modulus; + } + + template + void ConstitutiveModelRequest:: + set_mechanical_dissipation_tangent_modulus(const Number mechanicalDissipationTangentModulus) { + this->mechanical_dissipation_tangent_modulus = mechanicalDissipationTangentModulus; + } + + template + void ConstitutiveModelRequest:: + set_thermo_elastic_heating_tangent_modulus(const Number thermo_elastic_heating_tangent_modulus) { + this->thermo_elastic_heating_tangent_modulus = thermo_elastic_heating_tangent_modulus; + } + +} /* namespace PlasticityLab */ + +#endif /* CONSTITUTIVEMODELREQUEST_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/ConvectionBoundaryConditionApplier.h b/ALE_Finite_Strain_Plasticity/src/ConvectionBoundaryConditionApplier.h new file mode 100644 index 00000000..159b13df --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ConvectionBoundaryConditionApplier.h @@ -0,0 +1,80 @@ +/* + * ConvectionBoundaryConditionApplier.h + * + * Created on: 07 Oct 2017 + * Author: maien + */ + +#ifndef CONVECTIONBOUNDARYCONDITIONAPPLIER_H_ +#define CONVECTIONBOUNDARYCONDITIONAPPLIER_H_ + +namespace PlasticityLab { + + template + class ConvectionBoundaryConditionApplier { + public: + ConvectionBoundaryConditionApplier(); + ConvectionBoundaryConditionApplier( + int direction, + Number convection_coefficient = 1.0, + Number ambient_field_value = 0.0); + virtual ~ConvectionBoundaryConditionApplier(); + inline Number apply(const unsigned int direction, + const Number test_function_value, + const Number field_value, + const Number JxW) const; + inline Number apply_gradient( + const unsigned int direction, + const Number &test_gradient, + const Number &field_gradient, + const Number JxW) const; + private: + const unsigned int direction; + const Number convection_coefficient; + const Number ambient_field_value; + }; + + + template + ConvectionBoundaryConditionApplier:: + ConvectionBoundaryConditionApplier( + int direction, + Number convection_coefficient, + Number ambient_field_value) + : direction(direction), + convection_coefficient(convection_coefficient), + ambient_field_value(ambient_field_value) { + } + + + template + ConvectionBoundaryConditionApplier::~ConvectionBoundaryConditionApplier() { + } + + template + Number ConvectionBoundaryConditionApplier:: + apply(const unsigned int direction, + const Number test_function_value, + const Number field_value, + const Number JxW) const { + if (this->direction == direction) + return test_function_value * convection_coefficient * (field_value - ambient_field_value) * JxW; + return 0.0; + } + + template + Number ConvectionBoundaryConditionApplier::apply_gradient( + const unsigned int direction, + const Number &test_gradient, + const Number &field_gradient, + const Number JxW) const { + if (this->direction == direction) { + return convection_coefficient * (test_gradient * field_gradient) * JxW; + } + return 0; + } + + +} /* namespace PlasticityLab */ + +#endif /* CONVECTIONBOUNDARYCONDITIONAPPLIER_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/DoFSystem.h b/ALE_Finite_Strain_Plasticity/src/DoFSystem.h new file mode 100644 index 00000000..cee7b66b --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/DoFSystem.h @@ -0,0 +1,62 @@ +/* + * DoFSystem.h + * + * Created on: 05 May 2015 + * Author: maien + */ + +#ifndef DOFSYSTEM_H_ +#define DOFSYSTEM_H_ + +#include +#include + +#include "InterpolatoryConstraintApplier.h" +#include "BodyForceApplier.h" +#include "ConvectionBoundaryConditionApplier.h" +#include "mpi.h" +#include "utilities.h" + +using namespace dealii; + +namespace PlasticityLab { + + template + class DoFSystem { + public: + DoFSystem (const dealii::Triangulation &triangulation, + const dealii::Mapping &mapping); + + DoFHandler dof_handler; + + AffineConstraints nodal_constraints; + + IndexSet locally_owned_dofs; + IndexSet locally_relevant_dofs; + + void setup_dof_system (const FiniteElement &fe); + const dealii::Mapping &mapping; + + }; + + template + DoFSystem :: DoFSystem(const dealii::Triangulation &triangulation, + const dealii::Mapping &mapping) : + dof_handler(triangulation), + mapping(mapping) { + } + + template + void DoFSystem::setup_dof_system (const FiniteElement &fe) { + dof_handler.distribute_dofs(fe); + locally_owned_dofs = dof_handler.locally_owned_dofs(); + locally_relevant_dofs.clear(); + DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs); + + nodal_constraints.reinit(locally_relevant_dofs); + DoFTools::make_hanging_node_constraints (dof_handler, nodal_constraints); + } + +} /* namespace PlasticityLab */ + +#endif /* DOFSYSTEM_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/ExponentialHardeningElastoplasticMaterial.cpp b/ALE_Finite_Strain_Plasticity/src/ExponentialHardeningElastoplasticMaterial.cpp new file mode 100644 index 00000000..d0e61cc5 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ExponentialHardeningElastoplasticMaterial.cpp @@ -0,0 +1,234 @@ +/* + * ExponentialHardeningElastoplasticMaterial.cpp + * + * Created on: 10 Jul 2014 + * Author: cerecam + */ + + +#include +#include + +#include "ExponentialHardeningElastoplasticMaterial.h" +#include "utilities.h" + +namespace PlasticityLab { + + template + ExponentialHardeningElastoplasticMaterial:: + ExponentialHardeningElastoplasticMaterial + (const Number kappa, + const Number mu, + const Number K_0, + const Number K_infty, + const Number delta, + const Number H_bar, + const Number beta) : + kappa (kappa), + mu (mu), + K_0(K_0), + K_infty(K_infty), + delta(delta), + H_bar(H_bar), + beta(beta), + + stress_strain_tensor_kappa (kappa + * outer_product(unit_symmetric_tensor(), + unit_symmetric_tensor())), + stress_strain_tensor_mu (2 * mu + * (identity_tensor() + - outer_product(unit_symmetric_tensor(), + unit_symmetric_tensor()) / 3.0)) { + + } + + template + ExponentialHardeningElastoplasticMaterial:: + ~ExponentialHardeningElastoplasticMaterial() { + } + + template + std::vector ExponentialHardeningElastoplasticMaterial::get_state_parameters( + const point_index_t &point_index, + const Tensor<2, dim, Number> &reference_transformation) const { + throw NotImplementedException(); + } + + template + void ExponentialHardeningElastoplasticMaterial:: + set_state_parameters( + const point_index_t &point_index, + const std::vector &state_parameters, + const Tensor<2, dim, Number> &reference_transformation) { + throw NotImplementedException(); + } + + template + size_t ExponentialHardeningElastoplasticMaterial:: + get_material_parameter_count() const { + throw NotImplementedException(); + } + + + template + Number ExponentialHardeningElastoplasticMaterial::get_material_Jacobian(const point_index_t &point_index) const { + throw NotImplementedException(); + } + + template + dealii::SymmetricTensor<2, dim, Number> ExponentialHardeningElastoplasticMaterial::get_plastic_strain(const point_index_t &point_index) const { + throw NotImplementedException(); + } + + + template + void ExponentialHardeningElastoplasticMaterial:: + compute_constitutive_request(ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index) { + SymmetricTensor<2, dim, Number> plastic_strain = material_point_history[point_index].plastic_strain; + typename PointHistory::HardeningParameters + hardening_parameters = material_point_history[point_index].hardening_parameters; + + auto deformation_gradient = static_cast >(constitutive_request.get_deformation_gradient()); + SymmetricTensor<4, dim, Number> elastoplastic_tangent_moduli; + SymmetricTensor<2, dim, Number> deviator_strain_tensor = deviator(deformation_gradient); + + SymmetricTensor<2, dim, Number> dev_stress_trial = 2 * mu * (deviator_strain_tensor - plastic_strain); + SymmetricTensor<2, dim, Number> + ksi_trial = dev_stress_trial - hardening_parameters.kinematic_hardening; + + Number norm_ksi_trial = ksi_trial.norm(); + if (trial_yield_criterion( norm_ksi_trial, hardening_parameters.equivalent_plastic_strain ) > 0) { + Number delta_gamma, alpha_n_plus_1; + determine_delta_gamma(delta_gamma, alpha_n_plus_1, + norm_ksi_trial, + hardening_parameters.equivalent_plastic_strain, + 1e-10, 200); + SymmetricTensor<2, dim, Number> stress_flow_direction = ksi_trial / norm_ksi_trial; + + // 4. Update back stress, plastic strain and stress + const Number sqrt2thirds = sqrt((Number)2 / (Number)3); + Number H_alpha_n_plus_1, H_alpha_n, K_alpha_n_plus_1, K_alpha_n; + Number DH_alpha_n_plus_1, DK_alpha_n_plus_1; + exponential_hardening_values(K_alpha_n, H_alpha_n, hardening_parameters.equivalent_plastic_strain); + exponential_hardening_values(K_alpha_n_plus_1, H_alpha_n_plus_1, alpha_n_plus_1); + exponential_hardening_derivatives(DK_alpha_n_plus_1, DH_alpha_n_plus_1, alpha_n_plus_1); + if (update_material_point_history & constitutive_request.get_update_flags()) { + material_point_history[point_index].hardening_parameters.equivalent_plastic_strain = alpha_n_plus_1; + material_point_history[point_index].hardening_parameters.kinematic_hardening = + hardening_parameters.kinematic_hardening + + sqrt2thirds + * (H_alpha_n_plus_1 - H_alpha_n) + * stress_flow_direction; + material_point_history[point_index].plastic_strain = + plastic_strain + delta_gamma * stress_flow_direction; + } + + SymmetricTensor<2, dim, Number> + stress = kappa * trace(deformation_gradient) * unit_symmetric_tensor() + + dev_stress_trial + - 2 * mu * delta_gamma * stress_flow_direction; + + Number theta_n_plus_1 = 1 - 2 * mu * delta_gamma / norm_ksi_trial; + Number theta_bar_n_plus_1 = 1 / (1 + (DK_alpha_n_plus_1 + DH_alpha_n_plus_1) / (3 * mu)) + - (1 - theta_n_plus_1); + const SymmetricTensor<4, dim, Number> one_prod_one = + outer_product(unit_symmetric_tensor(), unit_symmetric_tensor()); + elastoplastic_tangent_moduli = kappa * one_prod_one + + 2 * mu * theta_n_plus_1 * (identity_tensor() - 1 / 3 * one_prod_one) + - 2 * mu * theta_bar_n_plus_1 * outer_product(stress_flow_direction, stress_flow_direction); + + // TODO change code such that request update flags are respected + constitutive_request.set_stress_deviator(stress); +// constitutiveRequest.setStressDeviatorTangentModuli(elastoplastic_tangent_moduli); + } /*if ( trial yield criterion test )*/ + else { + elastoplastic_tangent_moduli = stress_strain_tensor_kappa + stress_strain_tensor_mu; + SymmetricTensor<2, dim, Number> stress = (stress_strain_tensor_kappa + stress_strain_tensor_mu) * deformation_gradient; + constitutive_request.set_stress_deviator(stress); +// constitutiveRequest.setStressDeviatorTangentModuli(elastoplastic_tangent_moduli); + } + } + + template + void + ExponentialHardeningElastoplasticMaterial:: + setup_point_history (const point_index_t point_count) { + { + std::vector< PointHistory > tmp; + tmp.swap (material_point_history); + } + material_point_history.resize (point_count); + } + + template + inline void + ExponentialHardeningElastoplasticMaterial:: + determine_delta_gamma(Number &delta_gamma, Number &alpha_n_plus_1, + const Number norm_ksi_trial, + const Number alpha_n, + Number tol, unsigned int max_iter) const { + unsigned int k = 0; + const Number sqrt2thirds = sqrt((Number)2 / (Number)3); + Number g_of_gamma_k, Dg_of_gamma_k; + Number K_alpha_n, K_alpha_n_plus_1, H_alpha_n, H_alpha_n_plus_1; + Number DH_alpha_n_plus_1, DK_alpha_n_plus_1; + + delta_gamma = 0; + alpha_n_plus_1 = alpha_n; + + exponential_hardening_values(K_alpha_n, H_alpha_n, alpha_n); + + do { + k++; + exponential_hardening_values(K_alpha_n_plus_1, H_alpha_n_plus_1, alpha_n_plus_1); + g_of_gamma_k = -sqrt2thirds * K_alpha_n_plus_1 + norm_ksi_trial + - (2 * mu * delta_gamma + sqrt2thirds * (H_alpha_n_plus_1 - H_alpha_n)); + + exponential_hardening_derivatives(DK_alpha_n_plus_1, DH_alpha_n_plus_1, alpha_n_plus_1); + Dg_of_gamma_k = -2 * mu * (1 + (DH_alpha_n_plus_1 + DK_alpha_n_plus_1) / (3 * mu)); + + delta_gamma = delta_gamma - g_of_gamma_k / Dg_of_gamma_k; + alpha_n_plus_1 = alpha_n + sqrt2thirds * delta_gamma; + + } while (std::fabs(g_of_gamma_k) > tol && k < max_iter); + } + + template + inline void + ExponentialHardeningElastoplasticMaterial:: + exponential_hardening_values(Number &kinematic_hardening, + Number &isotropic_hardening, + const Number alpha) const { + Number h = K_infty - (K_infty - K_0) * exp(-delta * alpha) + H_bar * alpha; + kinematic_hardening = beta * h; + isotropic_hardening = (1 - beta) * h; + } + + template + inline void + ExponentialHardeningElastoplasticMaterial:: + exponential_hardening_derivatives(Number &D_kinematic_hardening, + Number &D_isotropic_hardening, + const Number alpha) const { + Number Dh = delta * (K_infty - K_0) * exp(-delta * alpha) + H_bar; + D_kinematic_hardening = beta * Dh; + D_isotropic_hardening = (1 - beta) * Dh; + } + + template + inline Number + ExponentialHardeningElastoplasticMaterial:: + trial_yield_criterion(const Number norm_ksi_trial, + const Number alpha) const { + Number H_alpha, K_alpha; + exponential_hardening_values(K_alpha, H_alpha, alpha); + const Number sqrt2thirds = sqrt((Number)2 / (Number)3); + Number trial_yield_criterion = norm_ksi_trial - sqrt2thirds * K_alpha; + return trial_yield_criterion; + } + + template class ExponentialHardeningElastoplasticMaterial<3, double>; + template class ExponentialHardeningElastoplasticMaterial<2, double>; + +} /* namespace PlasticityLab */ diff --git a/ALE_Finite_Strain_Plasticity/src/ExponentialHardeningElastoplasticMaterial.h b/ALE_Finite_Strain_Plasticity/src/ExponentialHardeningElastoplasticMaterial.h new file mode 100644 index 00000000..b97ca7fe --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ExponentialHardeningElastoplasticMaterial.h @@ -0,0 +1,88 @@ +/* + * ExponentialHardeningElastoplasticMaterial.h + * + * Created on: 10 Jul 2014 + * Author: cerecam + */ + +#ifndef EXPONENTIALHARDENINGMATERIAL_H_ +#define EXPONENTIALHARDENINGMATERIAL_H_ + +#include "PointHistory.h" +#include "Material.h" +#include "ConstitutiveModelRequest.h" + +using namespace dealii; + +namespace PlasticityLab { + + template + class ExponentialHardeningElastoplasticMaterial : public Material { + public: + ExponentialHardeningElastoplasticMaterial(const Number E, + const Number nu, + const Number K_0, + const Number K_infty, + const Number delta, + const Number H_bar, + const Number beta); + + virtual ~ExponentialHardeningElastoplasticMaterial(); + + void compute_constitutive_request( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index); + + Number get_material_Jacobian(const point_index_t &point_index) const; + dealii::SymmetricTensor<2, dim, Number> get_plastic_strain(const point_index_t &point_index) const; + + void setup_point_history (const point_index_t point_count); + + std::vector get_state_parameters( + const point_index_t &point_index, + const Tensor<2, dim, Number> &reference_transformation=unit_symmetric_tensor()) const; + + void set_state_parameters( + const point_index_t &point_index, + const std::vector &state_parameters, + const Tensor<2, dim, Number> &reference_transformation); + size_t get_material_parameter_count() const; + + private: + const Number kappa; + const Number mu; + + const Number K_0, K_infty, delta, H_bar; // hardening parameters (Simo & Hughes pp185) + const Number beta; // isotropic/kinematic hardening parameter + + + const SymmetricTensor<4, dim, Number> stress_strain_tensor_kappa; + const SymmetricTensor<4, dim, Number> stress_strain_tensor_mu; + + std::vector< PointHistory< dim, Number> > material_point_history; + + inline void + determine_delta_gamma(Number &delta_gamma, Number &alpha_n_plus_1, + const Number norm_ksi_trial, + const Number alpha_n, + Number tol, unsigned int max_iter) const; + + inline void + exponential_hardening_values(Number &kinematic_hardening, + Number &isotropic_hardening, + const Number alpha) const; + + inline void + exponential_hardening_derivatives(Number &D_kinematic_hardening, + Number &D_isotropic_hardening, + const Number alpha) const; + + inline Number + trial_yield_criterion(const Number norm_ksi_trial, + const Number alpha) const; + + }; + +} /* namespace PlasticityLab */ + +#endif /* EXPONENTIALHARDENINGMATERIAL_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/ExponentialHardeningThermoviscoplasticYieldLaw.h b/ALE_Finite_Strain_Plasticity/src/ExponentialHardeningThermoviscoplasticYieldLaw.h new file mode 100644 index 00000000..313c9c77 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ExponentialHardeningThermoviscoplasticYieldLaw.h @@ -0,0 +1,102 @@ +/* + * ExponentialHardeningThermoviscoplasticYieldLaw.h + * + * Created on: 22 Nov 2019 + * Author: maien + */ + +#ifndef EXPONENTIALHARDENINGTHERMOVISCOPLASTICYIELDLAW_H_ +#define EXPONENTIALHARDENINGTHERMOVISCOPLASTICYIELDLAW_H_ + +#include "Constants.h" + +namespace PlasticityLab { + + template + class ExponentialHardeningThermoviscoplasticYieldLaw { + public: + ExponentialHardeningThermoviscoplasticYieldLaw( + const Number K_0, + const Number K_infty, + const Number delta, + const Number H_bar, + const Number beta, + const Number flow_stress_softening, + const Number hardening_softening, + const Number reference_temperature=293.0) : + K_0(K_0), + K_infty(K_infty), + delta(delta), + H_bar(H_bar), + beta(beta), + flow_stress_softening(flow_stress_softening), + hardening_softening(hardening_softening), + reference_temperature(reference_temperature), + viscous_hardening_factor(0.0), + sqrt2thirds(Constants<3, Number>::sqrt2thirds()) {} + + Number hardening_values(Number &isotropic_hardening, + Number &kinematic_hardening, + const Number alpha, + const Number gamma, + const Number time_increment, + const Number temperature) const { + Number h = K_0 * (1 - std::min(softening_threshold, flow_stress_softening * (temperature - reference_temperature))) + + ((K_infty - K_0) * (1 - exp(-delta * alpha)) + H_bar * alpha) * (1 - std::min(softening_threshold, hardening_softening * (temperature - reference_temperature))) + + viscous_hardening_factor * sqrt2thirds * gamma / time_increment; + isotropic_hardening = beta * h; + kinematic_hardening = (1 - beta) * h; + return h; + } + + Number hardening_alpha_derivatives(Number &D_isotropic_hardening, + Number &D_kinematic_hardening, + const Number alpha, + const Number gamma, + const Number time_increment, + const Number temperature) const { + Number Dh = (delta * (K_infty - K_0) * exp(-delta * alpha) + H_bar) * (1 - std::min(softening_threshold, hardening_softening * (temperature - reference_temperature))) + + viscous_hardening_factor / time_increment; + D_isotropic_hardening = beta * Dh; + D_kinematic_hardening = (1 - beta) * Dh; + return Dh; + } + + Number hardening_temperature_derivatives(Number &D_isotropic_hardening, + Number &D_kinematic_hardening, + const Number alpha, + const Number gamma, + const Number time_increment, + const Number temperature) const { + Number Dh = (hardening_softening * (temperature - reference_temperature) < softening_threshold)? + -flow_stress_softening * K_0 + - hardening_softening * ((K_infty - K_0) * (1 - exp(-delta * alpha)) + H_bar * alpha) + : 0.0; + D_isotropic_hardening = beta * Dh; + D_kinematic_hardening = (1 - beta) * Dh; + return Dh; + } + + Number trial_yield_criterion(const Number norm_ksi_trial, + const Number alpha, + const Number gamma, + const Number time_increment, + const Number temperature) const { + Number K_alpha, H_alpha; + hardening_values(H_alpha, K_alpha, alpha, gamma, time_increment, temperature); + const Number trial_yield_criterion = norm_ksi_trial - sqrt2thirds * (H_alpha); + return trial_yield_criterion; + } + private: + const Number K_0, K_infty, delta, H_bar; // hardening parameters (Simo & Hughes pp185) + const Number beta; // isotropic/kinematic hardening parameter (1.0 for isotropic) + const Number flow_stress_softening, hardening_softening; // thermal softening parameters (Simo & Miehe 1992 pp74) + const Number reference_temperature; + const Number viscous_hardening_factor; + const Number sqrt2thirds; + const Number softening_threshold = 0.98; + }; + +} /* namespace PlasticityLab */ + +#endif /* EXPONENTIALHARDENINGTHERMOVISCOPLASTICYIELDLAW_H_ */ \ No newline at end of file diff --git a/ALE_Finite_Strain_Plasticity/src/IncrementInterpolationHandler.h b/ALE_Finite_Strain_Plasticity/src/IncrementInterpolationHandler.h new file mode 100644 index 00000000..ea3be862 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/IncrementInterpolationHandler.h @@ -0,0 +1,89 @@ +/* + * IncrementInterpolationHandler.h + * + * Created on: 25 Oct 2019 + * Author: maien + */ + +#ifndef INCREMENTINTERPOLATIONHANDLER_H_ +#define INCREMENTINTERPOLATIONHANDLER_H_ + + +using namespace dealii; + +namespace PlasticityLab { +template +class IncrementInterpolationHandler { +public: + IncrementInterpolationHandler( + Function *increment_interpolation_function, + bool do_interpolate, + ComponentMask interpolation_component_mask, + bool do_constrain, + ComponentMask constrain_component_mask, + types::boundary_id constrain_boundary_id, + Mapping &mapping) + : increment_interpolation_function(increment_interpolation_function), + do_interpolate(do_interpolate), + interpolation_component_mask(interpolation_component_mask), + do_constrain(do_constrain), + constrain_component_mask(constrain_component_mask), + constrain_boundary_id(constrain_boundary_id), + mapping(mapping) { } + + ~IncrementInterpolationHandler(){ + delete increment_interpolation_function; + } + + void advance_time(const Number delta_t); + + template + void distribute_step_constraints(VectorType &increment) const { + if(do_constrain) { + function_constraint.distribute(increment); + } + } + + template + void interpolate(VectorType &increment, const DoFSystem &dof_system) const { + if(do_interpolate) { + VectorTools::interpolate( + mapping, + dof_system.dof_handler, + *increment_interpolation_function, + increment, + interpolation_component_mask); + } + } + + void reinit_constraint_matrix(const DoFSystem &dof_system) { + if(do_constrain) { + function_constraint.reinit(dof_system.locally_relevant_dofs); + DoFTools::make_hanging_node_constraints(dof_system.dof_handler, function_constraint); + std::map< types::boundary_id, const Function< dim, Number > * > constraint_function_map; + constraint_function_map.insert(std::make_pair(constrain_boundary_id, increment_interpolation_function)); + dealii::VectorTools::interpolate_boundary_values(dof_system.mapping, dof_system.dof_handler, constraint_function_map, function_constraint, constrain_component_mask); + function_constraint.close(); + } + } + +private: + Function* increment_interpolation_function; + const bool do_interpolate; + ComponentMask interpolation_component_mask; + const bool do_constrain; + ComponentMask constrain_component_mask; + types::boundary_id constrain_boundary_id; + AffineConstraints function_constraint; + const Mapping &mapping; +}; + + +template +void IncrementInterpolationHandler::advance_time(const Number delta_t) { + increment_interpolation_function->advance_time(delta_t); +} + +} /* namespace PlasticityLab */ + +#endif /* INCREMENTINTERPOLATIONHANDLER_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/InterpolatoryConstraintApplier.h b/ALE_Finite_Strain_Plasticity/src/InterpolatoryConstraintApplier.h new file mode 100644 index 00000000..226afa0b --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/InterpolatoryConstraintApplier.h @@ -0,0 +1,81 @@ +/* + * InterpolatoryConstraintApplier.h + * + * Created on: 15 Jan 2015 + * Author: maien + */ + +#ifndef INTERPOLATORYCONSTRAINTAPPLIER_H_ +#define INTERPOLATORYCONSTRAINTAPPLIER_H_ + +#include +#include + +namespace PlasticityLab { + + template + class InterpolatoryConstraintApplier { + public: + InterpolatoryConstraintApplier(); + InterpolatoryConstraintApplier(const std::map< dealii::types::boundary_id, const dealii::Function< dim, Number > * > &constraintFunctionMap, + dealii::ComponentMask componentMask); + virtual ~InterpolatoryConstraintApplier(); + + void configure(std::map< dealii::types::boundary_id, const dealii::Function< dim, Number > * > constraintFunctionMap, + dealii::ComponentMask componentMask); + + void apply(const dealii::Mapping &mapping, + dealii::DoFHandler &doFHandler, + dealii::AffineConstraints &constraintMatrix, + bool useComponentMask = true) const; + + private: + std::map< dealii::types::boundary_id, const dealii::Function< dim, Number > * > constraintFunctionMap; + dealii::ComponentMask componentMask; + }; + + template + InterpolatoryConstraintApplier::InterpolatoryConstraintApplier() { + } + + template + InterpolatoryConstraintApplier::InterpolatoryConstraintApplier + (const std::map< dealii::types::boundary_id, const dealii::Function< dim, Number > * > &constraintFunctionMap, + dealii::ComponentMask componentMask): + constraintFunctionMap(constraintFunctionMap), + componentMask(componentMask) { + } + + template + InterpolatoryConstraintApplier::~InterpolatoryConstraintApplier() { + } + + template + void InterpolatoryConstraintApplier::configure + (std::map< dealii::types::boundary_id, const dealii::Function< dim, Number > * > constraintFunctionMap, + dealii::ComponentMask componentMask) { + this->constraintFunctionMap = std::map< dealii::types::boundary_id, const dealii::Function< dim, Number > * >(constraintFunctionMap); + this->componentMask = dealii::ComponentMask(componentMask); + } + + template + void InterpolatoryConstraintApplier::apply(const dealii::Mapping &mapping, + dealii::DoFHandler &doFHandler, + dealii::AffineConstraints &constraintMatrix, + bool useComponentMask) const { + if (useComponentMask) + dealii::VectorTools::interpolate_boundary_values(mapping, + doFHandler, + constraintFunctionMap, + constraintMatrix, + componentMask); + else + dealii::VectorTools::interpolate_boundary_values(mapping, + doFHandler, + constraintFunctionMap, + constraintMatrix); + } + +} /* namespace PlasticityLab */ + +#endif /* INTERPOLATORYCONSTRAINTAPPLIER_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/JohnsonCookThermoviscoplasticYieldLaw.h b/ALE_Finite_Strain_Plasticity/src/JohnsonCookThermoviscoplasticYieldLaw.h new file mode 100644 index 00000000..762fb4c0 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/JohnsonCookThermoviscoplasticYieldLaw.h @@ -0,0 +1,297 @@ +/* + * JohnsonCookThermoviscoplasticYieldLaw.h + * + * Created on: 22 Nov 2019 + * Author: maien + */ + +#ifndef JOHNSONCOOKTHERMOVISCOPLASTICYIELDLAW_H_ +#define JOHNSONCOOKTHERMOVISCOPLASTICYIELDLAW_H_ + +#include + +#include "Constants.h" + + +namespace PlasticityLab { + + template + class JohnsonCookThermoviscoplasticYieldLaw { + public: + JohnsonCookThermoviscoplasticYieldLaw( + const Number mu, + const Number A, + const Number B, + const Number C, + const Number m, + const Number n, + const Number melting_temperature, + const Number reference_strain_rate=1.0, + const Number reference_temperature=293.0, + const Number beta=1.0) : + mu(mu), + A(A), + B(B), + C(C), + m(m), + n(n), + melting_temperature(melting_temperature), + reference_strain_rate(reference_strain_rate), + reference_temperature(reference_temperature), + beta(beta), + sqrt2thirds(Constants<2, Number>::sqrt2thirds()), + exp_one_half(std::exp(0.5)) {} + + Number hardening_values(Number &isotropic_hardening, + Number &kinematic_hardening, + const Number alpha, + const Number gamma, + const Number time_increment, + const Number temperature) const { + if(use_Carreau_viscous_law) { + const Number creep_strain_rate_factor = std::pow(1-std::max(0., std::min(1., (temperature - reference_temperature)/(melting_temperature - reference_temperature))), 1.5); + const Number minimum_strain_rate = creep_strain_rate_factor * epsilon_dot_0; + const Number strain_rate = std::max(sqrt2thirds*gamma/time_increment, minimum_strain_rate); + const Number softened_quasistatic_elastoplastic_stress = get_elastoplastic_factor(alpha) * get_softening_factor(temperature); + const Number Carreau_viscocity = get_Carreau_viscocity(strain_rate, softened_quasistatic_elastoplastic_stress); + const Number h = 3 * Carreau_viscocity * strain_rate; + isotropic_hardening = beta * h; + kinematic_hardening = (1 - beta) * h; + return h; + } else { + const Number h = + get_elastoplastic_factor(alpha) + * get_viscosity_factor(gamma, time_increment) + * get_softening_factor(temperature) + + viscosity_regularization_factor * sqrt2thirds * gamma/time_increment; + isotropic_hardening = beta * h; + kinematic_hardening = (1 - beta) * h; + return h; + } + } + + Number hardening_alpha_derivatives(Number &D_isotropic_hardening, + Number &D_kinematic_hardening, + const Number alpha, + const Number gamma, + const Number time_increment, + const Number temperature) const { + if(use_Carreau_viscous_law) { + const Number creep_strain_rate_factor = std::pow(1-std::max(0., std::min(1., (temperature - reference_temperature)/(melting_temperature - reference_temperature))), 1.5); + const Number minimum_strain_rate = creep_strain_rate_factor * epsilon_dot_0; + const Number strain_rate = std::max(sqrt2thirds*gamma/time_increment, minimum_strain_rate); + const Number softened_quasistatic_elastoplastic_stress = get_elastoplastic_factor(alpha) * get_softening_factor(temperature); + const Number Carreau_viscocity = get_Carreau_viscocity(strain_rate, softened_quasistatic_elastoplastic_stress); + const Number strain_rate_tangent = strain_rate > minimum_strain_rate? 1.0/time_increment : 0; + const Number stress_tangent = + get_elastoplastic_factor_tangent(alpha) * get_softening_factor(temperature); + Number Carreau_viscocity_strain_rate_tangent, Carreau_viscocity_stress_tangent; + get_Carreau_viscocity_tangents( + strain_rate, softened_quasistatic_elastoplastic_stress, + Carreau_viscocity_strain_rate_tangent, + Carreau_viscocity_stress_tangent); + // const Number Dh = + // 3 * Carreau_viscocity * strain_rate > softened_quasistatic_elastoplastic_stress? + // 3 * Carreau_viscocity * strain_rate_tangent + // + 3 * Carreau_viscocity_stress_tangent * stress_tangent * strain_rate + // + 3 * Carreau_viscocity_strain_rate_tangent * strain_rate_tangent * strain_rate + // : 0; + const Number Dh = + 3 * Carreau_viscocity * strain_rate_tangent + + 3 * Carreau_viscocity_stress_tangent * stress_tangent * strain_rate + + 3 * Carreau_viscocity_strain_rate_tangent * strain_rate_tangent * strain_rate; + D_isotropic_hardening = beta * Dh; + D_kinematic_hardening = (1.0 - beta) * Dh; + return Dh; + } else { + const Number Dh = + get_elastoplastic_factor_tangent(alpha) + * get_viscosity_factor(gamma, time_increment) + * get_softening_factor(temperature) + + get_elastoplastic_factor(alpha) + * get_viscosity_factor_tangent(gamma, time_increment) + * get_softening_factor(temperature) + + viscosity_regularization_factor/time_increment; + D_isotropic_hardening = beta * Dh; + D_kinematic_hardening = (1.0 - beta) * Dh; + return Dh; + } + } + + Number hardening_temperature_derivatives(Number &D_isotropic_hardening, + Number &D_kinematic_hardening, + const Number alpha, + const Number gamma, + const Number time_increment, + const Number temperature) const { + if(use_Carreau_viscous_law) { + const Number creep_strain_rate_factor = std::pow(1-std::max(0., std::min(1., (temperature - reference_temperature)/(melting_temperature - reference_temperature))), 1.5); + const Number minimum_strain_rate = creep_strain_rate_factor * epsilon_dot_0; + const Number strain_rate = std::max(sqrt2thirds*gamma/time_increment, minimum_strain_rate); + const Number softened_quasistatic_elastoplastic_stress = get_elastoplastic_factor(alpha) * get_softening_factor(temperature); + const Number Carreau_viscocity = get_Carreau_viscocity(strain_rate, softened_quasistatic_elastoplastic_stress); + const Number stress_temperature_tangent = + get_elastoplastic_factor(alpha) * get_softening_factor_tangent(temperature); + Number Carreau_viscocity_strain_rate_tangent, Carreau_viscocity_stress_tangent; + get_Carreau_viscocity_tangents( + strain_rate, softened_quasistatic_elastoplastic_stress, + Carreau_viscocity_strain_rate_tangent, + Carreau_viscocity_stress_tangent); + const Number Dh = 3 * Carreau_viscocity_stress_tangent * stress_temperature_tangent * strain_rate; + D_isotropic_hardening = beta * Dh; + D_kinematic_hardening = (1 - beta) * Dh; + return Dh; + } else { + Number Dh = + get_elastoplastic_factor(alpha) + * get_viscosity_factor(gamma, time_increment) + * get_softening_factor_tangent(temperature); + D_isotropic_hardening = beta * Dh; + D_kinematic_hardening = (1 - beta) * Dh; + return Dh; + } + } + + Number trial_yield_criterion(const Number norm_ksi_trial, + const Number alpha, + const Number gamma, + const Number time_increment, + const Number temperature) const { + Number K_alpha, H_alpha; + hardening_values(H_alpha, K_alpha, alpha, gamma, time_increment, temperature); + const Number trial_yield_criterion = norm_ksi_trial - sqrt2thirds * (H_alpha); + return trial_yield_criterion; + } + + Number get_elastoplastic_factor(const Number alpha) const { + if(alpha > max_strain) { + return A + B * std::pow(max_strain, n); + } + if(alpha >= eps) { + return A + B * std::pow(alpha, n); + } + return A + B * alpha/eps * std::pow(eps, n); + } + + Number get_viscosity_factor(const Number gamma, const Number time_increment) const { + Number slope, intercept; + get_small_hardening_fit(slope, intercept, time_increment); + if(gamma >= intercept) { + return 1.0 + C * std::log(sqrt2thirds*gamma/(time_increment*reference_strain_rate)); + } else if (gamma < 0.0) { + return 1.0 - C * slope * sqrt2thirds * gamma * gamma; + } + return 1.0 + C * slope * sqrt2thirds * gamma * gamma; + } + + Number get_softening_factor(const Number temperature) const { + if(temperature > reference_temperature) { + if(temperature < melting_temperature) { + return (1.0 + softening_threshold - std::pow((temperature - reference_temperature)/(melting_temperature - reference_temperature), m)); + } else { + return 0.0 + softening_threshold; + } + } + return 1.0 + softening_threshold; + } + + Number get_elastoplastic_factor_tangent(const Number alpha) const { + if(alpha > max_strain) { + return 0; + } + if(alpha >= eps) { + return B * n * std::pow(alpha, n-1.0); + } + return B * 1.0/eps * std::pow(eps, n); + } + + Number get_viscosity_factor_tangent(const Number gamma, const Number time_increment) const { + Number slope, intercept; + get_small_hardening_fit(slope, intercept, time_increment); + if(gamma >= intercept) { + return C / (sqrt2thirds * gamma); + } else if (gamma < 0.0) { + return -2 * C * slope * gamma; + } + return 2 * C * slope * gamma; + } + + Number get_softening_factor_tangent(const Number temperature) const { + if(temperature > reference_temperature) { + if(temperature < melting_temperature) { + return (-m/(melting_temperature - reference_temperature)) + * std::pow((temperature - reference_temperature)/(melting_temperature - reference_temperature), m-1.0); + } else { + return 0.0; + } + } + return 0.0; + } + + void get_small_hardening_fit(Number &slope, Number &intercept, const Number time_increment) const { + // the log factor is annoying when below 1.0. Replace it by a parabula till it behaves. + const Number log_factor = 1./(time_increment*reference_strain_rate); + intercept = exp_one_half/(sqrt2thirds * log_factor); + slope = 1./(2*intercept*intercept*sqrt2thirds); + } + + Number get_Carreau_viscocity(Number strain_rate, Number sigma_0_theta) const { + if(sigma_0_theta <= 0) { + return mu_infty; + } + const Number g_sigma_epsilon_dot = std::pow(sigma_0_theta/(3*epsilon_dot_0*mu_0), (n_C/(1-n_C))) * (strain_rate/epsilon_dot_0); + return std::pow(1 + std::pow(g_sigma_epsilon_dot, 2), ((1-n_C)/(2*n_C))) * (mu_0 - mu_infty) + mu_infty; + } + + void get_Carreau_viscocity_tangents( + Number strain_rate, + Number sigma_0_theta, + Number &Carreau_viscocity_strain_rate_tangent, + Number &Carreau_viscocity_stress_tangent) const { + if(sigma_0_theta <= 0) { + Carreau_viscocity_strain_rate_tangent = 0; + Carreau_viscocity_stress_tangent = 0; + return; + } + const Number g_sigma_epsilon_dot = std::pow(sigma_0_theta/(3*epsilon_dot_0*mu_0), (n_C/(1-n_C))) * (strain_rate/epsilon_dot_0); + const Number g_sigma_epsilon_dot_strain_rate_tangent = std::pow(sigma_0_theta/(3*epsilon_dot_0*mu_0), (n_C/(1-n_C))) * (1/epsilon_dot_0); + const Number g_sigma_epsilon_dot_stress_tangent = + (n_C / (1-n_C)) * std::pow(sigma_0_theta/(3*epsilon_dot_0*mu_0), ((2*n_C-1)/(1-n_C))) * (strain_rate/epsilon_dot_0) * (1/(3 * epsilon_dot_0 * mu_0)); + const Number Carreau_viscocity_g_tangent = + ((1-n_C)/(2*n_C)) * std::pow(1 + std::pow(g_sigma_epsilon_dot, 2), ((1-3*n_C)/(2*n_C))) * (2*g_sigma_epsilon_dot) * (mu_0 - mu_infty); + + Carreau_viscocity_strain_rate_tangent = Carreau_viscocity_g_tangent * g_sigma_epsilon_dot_strain_rate_tangent; + Carreau_viscocity_stress_tangent = Carreau_viscocity_g_tangent * g_sigma_epsilon_dot_stress_tangent; + } + + private: + const Number mu; + const Number A; + const Number B; + const Number C; + const Number m; + const Number n; + const Number melting_temperature; + const Number reference_strain_rate; + const Number reference_temperature; + const Number beta; + const Number sqrt2thirds; + const Number exp_one_half; + + const Number eps = std::pow(B/mu, 1.0/(1.0-n)); + const Number softening_threshold = 0.0; + const Number viscosity_regularization_factor = 0; + const Number max_strain = std::numeric_limits::max(); + + // Carreau fluid parameters + const bool use_Carreau_viscous_law = false; + const Number epsilon_dot_0 = 1; + const Number n_C = 3; + const Number mu_0 = 1e18; + const Number mu_infty = 1e-4; + + }; + +} /* namespace PlasticityLab */ + +#endif /* JOHNSONCOOKTHERMOVISCOPLASTICYIELDLAW_H_ */ \ No newline at end of file diff --git a/ALE_Finite_Strain_Plasticity/src/LBCSystem.h b/ALE_Finite_Strain_Plasticity/src/LBCSystem.h new file mode 100644 index 00000000..1381cdb6 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/LBCSystem.h @@ -0,0 +1,114 @@ +/* + * LBCSystem.h + * + * Created on: 08 Oct 2019 + * Author: maien + */ + +#ifndef LBCSYSTEM_H_ +#define LBCSYSTEM_H_ + +#include + +#include "InterpolatoryConstraintApplier.h" +#include "BodyForceApplier.h" +#include "ConvectionBoundaryConditionApplier.h" +#include "IncrementInterpolationHandler.h" +#include "utilities.h" +#include "DoFSystem.h" +#include "BoundaryUnidirectionalPenaltySpec.h" + +using namespace dealii; +using namespace Functions; + +namespace PlasticityLab { + +template +class LBCSystem { +public: + LBCSystem(): zero_function(components){} + ~LBCSystem() { + for(auto increment_interpolation_handler: increment_interpolation_handlers) { + delete increment_interpolation_handler; + } + for(auto initial_velocity_interpolation_handler: initial_velocity_interpolation_handlers) { + delete initial_velocity_interpolation_handler; + } + for(auto initial_deformation_interpolation_handler: initial_deformation_interpolation_handlers) { + delete initial_deformation_interpolation_handler; + } + for(auto boundary_unidirectional_penalty_spec: boundary_unidirectional_penalty_specs) { + delete boundary_unidirectional_penalty_spec; + } + } + + void apply_constraints(DoFSystem &dof_system) const; + + void clear(); + + std::vector< BodyForceApplier > bodyLoadAppliers; + std::vector< std::pair > > boundaryLoadAppliers; + std::vector< std::pair > > convection_BC_appliers; + std::vector< InterpolatoryConstraintApplier > interpolatoryConstraintAppliers; + std::vector>> no_normal_flux_constraints; + std::vector*> increment_interpolation_handlers; + std::vector*> initial_velocity_interpolation_handlers; + std::vector*> initial_deformation_interpolation_handlers; + std::vector*> boundary_unidirectional_penalty_specs; + + ZeroFunction zero_function; +}; + + +template +void LBCSystem::apply_constraints(DoFSystem &dof_system) const { + for (auto constraintApplier = interpolatoryConstraintAppliers.cbegin(); + constraintApplier != interpolatoryConstraintAppliers.end(); + ++constraintApplier) { + constraintApplier->apply(dof_system.mapping, dof_system.dof_handler, dof_system.nodal_constraints); + } + + for (auto no_normal_flux_constraint : no_normal_flux_constraints) { + VectorTools::compute_no_normal_flux_constraints( + dof_system.dof_handler, + no_normal_flux_constraint.first, + no_normal_flux_constraint.second, + dof_system.nodal_constraints, + dof_system.mapping); + } + + dof_system.nodal_constraints.close(); +} + + +template +void LBCSystem::clear() { + for(auto increment_interpolation_handler: increment_interpolation_handlers) { + delete increment_interpolation_handler; + } + for(auto initial_velocity_interpolation_handler: initial_velocity_interpolation_handlers) { + delete initial_velocity_interpolation_handler; + } + for(auto initial_deformation_interpolation_handler: initial_deformation_interpolation_handlers) { + delete initial_deformation_interpolation_handler; + } + for(auto boundary_unidirectional_penalty_spec: boundary_unidirectional_penalty_specs) { + delete boundary_unidirectional_penalty_spec; + } + + bodyLoadAppliers.clear(); + boundaryLoadAppliers.clear(); + convection_BC_appliers.clear(); + interpolatoryConstraintAppliers.clear(); + no_normal_flux_constraints.clear(); + increment_interpolation_handlers.clear(); + initial_velocity_interpolation_handlers.clear(); + initial_deformation_interpolation_handlers.clear(); + boundary_unidirectional_penalty_specs.clear(); + +} + + +} /* namespace PlasticityLab */ + +#endif /* LBCSYSTEM_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/Material.h b/ALE_Finite_Strain_Plasticity/src/Material.h new file mode 100644 index 00000000..318880d3 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/Material.h @@ -0,0 +1,58 @@ +/* + * Material.h + * + * Created on: 05 Jan 2015 + * Author: maien + */ + +#ifndef MATERIAL_H_ +#define MATERIAL_H_ + +using namespace dealii; + +#include "ConstitutiveModelRequest.h" +#include + +namespace PlasticityLab { + + typedef size_t point_index_t; + + template + class Material { + public: + virtual ~Material() = 0; + + virtual void compute_constitutive_request( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index) = 0; + + virtual Number get_material_Jacobian(const point_index_t &point_index) const = 0; + virtual dealii::SymmetricTensor<2, dim, Number> get_plastic_strain(const point_index_t &point_index) const = 0; + + virtual void setup_point_history(const point_index_t point_count) = 0; + + virtual std::vector get_state_parameters( + const point_index_t &point_index, + const Tensor<2, dim, Number> &reference_transformation=unit_symmetric_tensor()) const = 0; + + virtual void set_state_parameters( + const point_index_t &point_index, + const std::vector &state_parameters, + const Tensor<2, dim, Number> &reference_transformation) = 0; + virtual size_t get_material_parameter_count() const = 0; + + }; + + template + inline Material::~Material() { + } + + class MaterialDomainException: public std::runtime_error { + public: + MaterialDomainException(); + MaterialDomainException(std::string s): std::runtime_error(s) {}; + }; + +} /* namespace PlasticityLab */ + +#endif /* MATERIAL_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/MixedFEProjector.h b/ALE_Finite_Strain_Plasticity/src/MixedFEProjector.h new file mode 100644 index 00000000..1fcad00e --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/MixedFEProjector.h @@ -0,0 +1,99 @@ +/* + * MixedFEProjector.h + * + * Created on: 21 Jul 2015 + * Author: maien + */ + +#ifndef MIXEDFEPROJECTOR_H_ +#define MIXEDFEPROJECTOR_H_ + +#include + +#include +#include + +#include + +#include "utilities.h" + +template +class MixedFEProjector { + public: + MixedFEProjector(); + MixedFEProjector( + const unsigned int mixed_dofs_per_cell, + const dealii::FEValues &mixed_fe_values); + virtual ~MixedFEProjector(); + + template + void project( + std::vector *coefficients_of_mixed_dofs, + const std::vector &values_at_q_points) const; + + private: + unsigned int n_q_points; + unsigned int mixed_dofs_per_cell; + std::vector > M_inv_ksi; +}; + +template +MixedFEProjector::MixedFEProjector(): + n_q_points(0), + mixed_dofs_per_cell(0), + M_inv_ksi(0) { + +} + +template +MixedFEProjector::MixedFEProjector( + const unsigned int mixed_dofs_per_cell, + const dealii::FEValues &mixed_fe_values) + : n_q_points (mixed_fe_values.get_quadrature().size()), + mixed_dofs_per_cell (mixed_dofs_per_cell), + M_inv_ksi (n_q_points, std::vector(mixed_dofs_per_cell)) { + dealii::FullMatrix M_matrix(mixed_dofs_per_cell, mixed_dofs_per_cell), + M_inv(mixed_dofs_per_cell, mixed_dofs_per_cell); + std::vector > ksi(n_q_points, dealii::Vector(mixed_dofs_per_cell)); + + M_matrix = 0; + for (unsigned int q_point = 0; q_point < n_q_points; + ++q_point) { + // Prep to compute mixed primary variables (Simo & Miehe 1992) + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + const Number i_value = mixed_fe_values.shape_value (i, q_point); + for (unsigned int j = 0; j < mixed_dofs_per_cell; ++j) { + const Number j_value = mixed_fe_values.shape_value (j, q_point); + M_matrix(i, j) += i_value * j_value * mixed_fe_values.quadrature_point(q_point)[0] * mixed_fe_values.JxW(q_point); + } + ksi.at(q_point)[i] = i_value * mixed_fe_values.quadrature_point(q_point)[0] * mixed_fe_values.JxW(q_point); + } + } + + M_inv.invert(M_matrix); + + for (unsigned int q_point = 0; q_point < n_q_points; + ++q_point) { + dealii::Vector M_inv_ksi_at_q_point(mixed_dofs_per_cell); + M_inv.vmult(M_inv_ksi_at_q_point, ksi.at(q_point), false); + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) + M_inv_ksi[q_point][i] = M_inv_ksi_at_q_point(i); + } +} + +template +MixedFEProjector::~MixedFEProjector() {} + +template +template +void MixedFEProjector::project( + std::vector *coefficients_of_mixed_dofs, + const std::vector &values_at_q_points) const { + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + coefficients_of_mixed_dofs->at(i) = M_inv_ksi[0][i] * values_at_q_points[0]; + for (unsigned int q_point = 1; q_point < n_q_points; ++q_point) + coefficients_of_mixed_dofs->at(i) += M_inv_ksi[q_point][i] * values_at_q_points[q_point]; + } +} + +#endif /* MIXEDFEPROJECTOR_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/NewtonStepSystem.h b/ALE_Finite_Strain_Plasticity/src/NewtonStepSystem.h new file mode 100644 index 00000000..142de36b --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/NewtonStepSystem.h @@ -0,0 +1,135 @@ +/* + * NewtonStepSystem.h + * + * Created on: 05 May 2015 + * Author: maien + */ + +#ifndef NEWTONSTEPSYSTEM_H_ +#define NEWTONSTEPSYSTEM_H_ + + +#include +#include +#include + +#include "DoFSystem.h" +#include "Constants.h" + +using namespace dealii; + +namespace PlasticityLab { + + class NewtonStepSystem { + public: + + template + void setup(const DoFSystemType &dof_system) { + TrilinosWrappers::SparsityPattern sparsity_pattern( + dof_system.locally_owned_dofs, + mpi_communicator); + + DoFTools::make_sparsity_pattern( + dof_system.dof_handler, sparsity_pattern, + dof_system.nodal_constraints, + false, + Utilities::MPI::this_mpi_process(mpi_communicator)); + + sparsity_pattern.compress(); + Newton_step_matrix.reinit(sparsity_pattern); + Newton_step_solution.reinit( + dof_system.locally_owned_dofs, + mpi_communicator); + current_increment.reinit( + dof_system.locally_relevant_dofs, + mpi_communicator); + Newton_step_residual.reinit( + dof_system.locally_owned_dofs, + mpi_communicator); + previous_deformation.reinit( + dof_system.locally_relevant_dofs, + mpi_communicator); + + previous_time_derivative.reinit( + dof_system.locally_relevant_dofs, + mpi_communicator); + previous_second_time_derivative.reinit( + dof_system.locally_relevant_dofs, + mpi_communicator); + + _locally_owned_previous_time_derivative.reinit( + dof_system.locally_owned_dofs, + mpi_communicator); + _locally_owned_previous_second_time_derivative.reinit( + dof_system.locally_owned_dofs, + mpi_communicator); + } + + template + void update_matrix_constraints(const DoFSystemType &dof_system) { + TrilinosWrappers::SparsityPattern sparsity_pattern( + dof_system.locally_owned_dofs, + mpi_communicator); + + DoFTools::make_sparsity_pattern( + dof_system.dof_handler, sparsity_pattern, + dof_system.nodal_constraints, + false, + Utilities::MPI::this_mpi_process(mpi_communicator)); + + sparsity_pattern.compress(); + Newton_step_matrix.reinit(sparsity_pattern); + } + + void advance_time(double delta_t, double rho_infty, const bool reset_increment=true) { + { + double alpha_m, alpha_f, gamma, beta; + get_generalized_alpha_method_params( + &alpha_m, &alpha_f, &gamma, &beta, rho_infty); + + _locally_owned_previous_time_derivative = previous_time_derivative; + _locally_owned_previous_second_time_derivative = previous_second_time_derivative; + + const TrilinosWrappers::MPI::Vector previous_second_time_derivative_backup(_locally_owned_previous_second_time_derivative); + + _locally_owned_previous_second_time_derivative = current_increment; + _locally_owned_previous_second_time_derivative.add( + -delta_t, + _locally_owned_previous_time_derivative, + -delta_t*delta_t*(0.5-beta), + previous_second_time_derivative_backup); + _locally_owned_previous_second_time_derivative *= (1./(beta*delta_t*delta_t)); + _locally_owned_previous_time_derivative.add( + delta_t*(1.-gamma), + previous_second_time_derivative_backup, + delta_t*gamma, + _locally_owned_previous_second_time_derivative); + + + previous_time_derivative = _locally_owned_previous_time_derivative; + previous_second_time_derivative = _locally_owned_previous_second_time_derivative; + + } + previous_deformation += current_increment; + if(reset_increment) { + current_increment = 0; + } + } + + TrilinosWrappers::SparseMatrix Newton_step_matrix; + TrilinosWrappers::MPI::Vector previous_deformation; + TrilinosWrappers::MPI::Vector current_increment; + TrilinosWrappers::MPI::Vector Newton_step_solution; + TrilinosWrappers::MPI::Vector Newton_step_residual; + + TrilinosWrappers::MPI::Vector previous_time_derivative; + TrilinosWrappers::MPI::Vector previous_second_time_derivative; + + TrilinosWrappers::MPI::Vector _locally_owned_previous_time_derivative; + TrilinosWrappers::MPI::Vector _locally_owned_previous_second_time_derivative; + + }; + +} /* namespace PlasticityLab */ + +#endif /* NEWTONSTEPSYSTEM_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/PlasticityLabProg.cpp b/ALE_Finite_Strain_Plasticity/src/PlasticityLabProg.cpp new file mode 100644 index 00000000..a08027a1 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/PlasticityLabProg.cpp @@ -0,0 +1,3627 @@ +/* + * PlasticityLabProg.cpp + * + * Created on: 09 Jul 2014 + * Author: cerecam + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "TimeRateUpdateFlags.h" +#include "TimeRateRequest.h" + +#include "PlasticityLabProg.h" +#include "PlasticityLabProgDrivers.cpp" + +#include "ReferencePoint.h" +#include "RemappedPoint.h" + +using namespace dealii; +using std::endl; + +namespace PlasticityLab { + template + PlasticityLabProg::PlasticityLabProg( + Material &material) : + mpi_communicator(MPI_COMM_WORLD), + pcout(std::cout, + (Utilities::MPI::this_mpi_process(mpi_communicator) == 0)), + order(1), + mech_fe(FE_Q(order), dim, FE_Q(order), 2), + therm_fe(order), + mixed_var_fe(order-1), + mesh_motion_fe(FE_Q(order), dim), + mapping (order), + triangulation(mpi_communicator), + mech_dof_system(triangulation, mapping), + therm_dof_system (triangulation, mapping), + mixed_fe_dof_system(triangulation, mapping), + mesh_motion_dof_system(triangulation, mapping), + quadrature_formula(order+1), + face_quadrature_formula(order+1), + material(material) { } + + + template + PlasticityLabProg::~PlasticityLabProg() { + + } + + template + template + void PlasticityLabProg::setup_material_data( + TriangulationType &triangulation, + MaterialType &material) { + const unsigned int num_cells = triangulation.n_active_cells(); + triangulation.clear_user_data(); + material.setup_point_history(num_cells * quadrature_formula.size()); + unsigned int history_index = 0; + for (typename Triangulation::active_cell_iterator + cell = triangulation.begin_active(); + cell != triangulation.end(); ++cell) { + cell->set_user_index (history_index); + history_index += quadrature_formula.size(); + } + } + + template + void PlasticityLabProg::setup_material_area_factors( + const DoFSystem &mesh_motion_dof_system, + std::unordered_map> &material_area_factors) { + + FEFaceValues fe_face_values ( + mapping, + mesh_motion_fe, + face_quadrature_formula, + update_normal_vectors); + const unsigned int n_face_q_points = face_quadrature_formula.size(); + + for (auto cell = mesh_motion_dof_system.dof_handler.begin_active(); + cell != mesh_motion_dof_system.dof_handler.end(); + ++cell) { + if (cell->is_locally_owned()) { + for (unsigned int face = 0; face < GeometryInfo::faces_per_cell; ++face) { + if(cell->at_boundary(face)) { + fe_face_values.reinit(cell, face); + + for (unsigned int q_point = 0; q_point < n_face_q_points; q_point++) { + const unsigned int cell_index = cell->user_index() / quadrature_formula.size(); + const unsigned int surface_point_key = + cell_index * GeometryInfo::faces_per_cell * n_face_q_points + + face * n_face_q_points + + q_point; + material_area_factors[surface_point_key] = postprocess_tensor_dimension(fe_face_values.normal_vector(q_point), 0); + } + } + } + } + } + } + + template + void PlasticityLabProg::update_material_area_factors( + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + std::unordered_map> &material_area_factors) { + + FEFaceValues fe_face_values ( + mapping, + mesh_motion_fe, + face_quadrature_formula, + update_values | update_gradients | update_quadrature_points); + + const unsigned int n_face_q_points = face_quadrature_formula.size(); + + const FEValuesExtractors::Vector displacements (0); + + std::vector< Tensor<1, dim, Number> > mesh_motion_value_increments(n_face_q_points); + std::vector< Tensor<2, dim, Number> > mesh_motion_gradient_increments(n_face_q_points); + + for (auto cell = mesh_motion_dof_system.dof_handler.begin_active(); + cell != mesh_motion_dof_system.dof_handler.end(); + ++cell) { + if (cell->is_locally_owned()) { + for (unsigned int face = 0; face < GeometryInfo::faces_per_cell; ++face) { + if(cell->at_boundary(face)) { + fe_face_values.reinit(cell, face); + + fe_face_values[displacements].get_function_gradients( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_gradient_increments); + + fe_face_values[displacements].get_function_values( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_value_increments); + + for (unsigned int q_point = 0; q_point < n_face_q_points; q_point++) { + const unsigned int cell_index = cell->user_index() / quadrature_formula.size(); + const unsigned int surface_point_key = + cell_index * GeometryInfo::faces_per_cell * n_face_q_points + + face * n_face_q_points + + q_point; + + const auto mesh_motion_gradient = get_deformation_gradient( + -mesh_motion_gradient_increments[q_point], + -mesh_motion_value_increments[q_point][0] + /fe_face_values.quadrature_point(q_point)[0]); + + material_area_factors[surface_point_key] = std::pow(determinant(mesh_motion_gradient), -1) + * transpose(mesh_motion_gradient) + * material_area_factors[surface_point_key]; + } + } + } + } + } + } + + template + template + void PlasticityLabProg::setup_mixed_fe_projection_data( + const TriangulationType &triangulation, + std::vector< MixedFEProjector > &MixedFeProjectors, + const FiniteElement &MixedFE, + const Quadrature &quadrature_formula) { + + FEValues mixed_fe_values( + mapping, + MixedFE, + quadrature_formula, + update_values | update_quadrature_points | update_JxW_values); + + const unsigned int num_cells = triangulation.n_active_cells(), + n_q_points = quadrature_formula.size(), + mixed_dofs_per_cell = MixedFE.dofs_per_cell; + MixedFeProjectors.clear(); + MixedFeProjectors.resize(num_cells); + for (typename Triangulation::active_cell_iterator + cell = triangulation.begin_active(); + cell != triangulation.end(); ++cell) { + mixed_fe_values.reinit(cell); + MixedFeProjectors.at(cell->user_index() / n_q_points) = + MixedFEProjector(mixed_dofs_per_cell, + mixed_fe_values); + } + } + + template + void PlasticityLabProg::remap_material_state_variables( + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const NewtonStepSystem &mechanical_nonlinear_system, + const DoFSystem &mechanical_dof_system, + const DoFSystem &mixed_fe_dof_system, + const std::vector< MixedFEProjector > &mixed_fe_projector, + Material &material, + std::unordered_map> &remapped_deformation_gradients) { + + const unsigned int n_q_points = quadrature_formula.size(); + const unsigned int dofs_per_cell = mesh_motion_fe.dofs_per_cell; + const unsigned int mixed_dofs_per_cell = mixed_fe_dof_system.dof_handler.get_fe().dofs_per_cell; + + FEValues mesh_motion_fe_values( + mapping, + mesh_motion_fe, + quadrature_formula, + update_values | update_gradients | update_quadrature_points | update_jacobians | update_JxW_values); + + FEValues mechanical_fe_values( + mapping, + mech_fe, + quadrature_formula, + update_values | update_gradients); + + FEValues mixed_fe_values( + mapping, + mixed_fe_dof_system.dof_handler.get_fe(), + quadrature_formula, + update_values); + + std::vector< Tensor<1, dim, Number> > mesh_motion_value_increments(n_q_points); + std::vector< Tensor<2, dim, Number> > mesh_motion_gradient_increments(n_q_points); + + std::vector< Tensor<1, dim, Number> > previous_deformation_values(n_q_points); + std::vector< Tensor<2, dim, Number> > previous_deformation_gradients(n_q_points); + std::vector< Tensor<1, dim, Number> > previous_deformation_value_at_remapped_point(1); + std::vector< Tensor<2, dim, Number> > previous_deformation_gradient_at_remapped_point(1); + + const unsigned int material_parameter_count = material.get_material_parameter_count(); + + const FEValuesExtractors::Vector displacements(0); + const FEValuesExtractors::Scalar temperature (0); + + std::vector> reference_points; + std::vector> remapped_point_positions; + + for (auto cell = mesh_motion_dof_system.dof_handler.begin_active(); + cell != mesh_motion_dof_system.dof_handler.end(); + ++cell) { + if (cell->is_locally_owned()) { + mesh_motion_fe_values.reinit(cell); + + mesh_motion_fe_values[displacements].get_function_values( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_value_increments); + + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + const point_index_t quadrature_point_index = cell->user_index() + q_point; + const Point reference_point_position = mesh_motion_fe_values.quadrature_point(q_point); + const Point remapped_point_position = reference_point_position - mesh_motion_value_increments[q_point]; + + ReferencePoint reference_point; + reference_point.mesh_motion_cell = cell; + reference_point.q_point = q_point; + reference_point.reference_point = reference_point_position; + reference_point.remapped_point = remapped_point_position; + + reference_points.push_back(reference_point); + remapped_point_positions.push_back(remapped_point_position); + + } + + } + } + + MPI_Barrier(mpi_communicator); + + MPI_Datatype PointType; + MPI_Type_contiguous(dim, MPI_DOUBLE, &PointType); + MPI_Type_commit(&PointType); + std::vector displs; + std::vector< Point> received_remapped_positions; + std::vector> remapped_points; + int nprocesses, this_process; + int num_reference_points = reference_points.size(); + MPI_Comm_size(mpi_communicator, &nprocesses); + std::vector reference_point_counts(nprocesses); + MPI_Allgather( + &num_reference_points, + 1, MPI_INT, + &reference_point_counts[0], + 1, MPI_INT, + mpi_communicator); + MPI_Comm_rank(mpi_communicator, &this_process); + displs.resize(nprocesses); + displs[0] = 0; + for (int i = 1; i < nprocesses; ++i) { + displs[i] = displs[i - 1] + reference_point_counts[i - 1]; + } + + const unsigned int count_received_reference_points = displs[nprocesses - 1] + reference_point_counts[nprocesses - 1]; + received_remapped_positions.resize(count_received_reference_points); + remapped_points.resize(count_received_reference_points); + std::vector this_process_owns_remapped_point(count_received_reference_points); + + MPI_Allgatherv( + &remapped_point_positions[0], + num_reference_points, + PointType, + &received_remapped_positions[0], + &reference_point_counts[0], + &displs[0], + PointType, + mpi_communicator); + + MPI_Barrier(mpi_communicator); + + for(unsigned int received_point_id=0; received_point_id < count_received_reference_points; received_point_id++) { + auto point = received_remapped_positions[received_point_id]; + auto cell_and_point = GridTools::find_active_cell_around_point( + mapping, + mesh_motion_dof_system.dof_handler, + point); + auto cell = cell_and_point.first; + auto unit_cell_point = cell_and_point.second; + // here, we're assuming that `find_active_cell_around_point` returns the same + // cell and point when called with different dof_handlers + auto mechanical_cell_and_point = GridTools::find_active_cell_around_point( + mapping, + mechanical_dof_system.dof_handler, + point); + auto mechanical_cell = mechanical_cell_and_point.first; + auto mixed_fe_cell_and_point = GridTools::find_active_cell_around_point( + mapping, + mixed_fe_dof_system.dof_handler, + point); + auto mixed_fe_cell = mixed_fe_cell_and_point.first; + + remapped_points[received_point_id].remapped_point = point; + remapped_points[received_point_id].mesh_motion_cell = cell; + remapped_points[received_point_id].unit_cell_point = unit_cell_point; + remapped_points[received_point_id].field_cell = mechanical_cell; + remapped_points[received_point_id].mixed_fe_cell = mixed_fe_cell; + this_process_owns_remapped_point[received_point_id] = cell.state() == IteratorState::valid && cell->is_locally_owned()? 1 : 0; + } + + MPI_Barrier(mpi_communicator); + + std::vector remapped_point_candidates(num_reference_points * nprocesses); + for (int process = 0; process < nprocesses; ++process) { + if (reference_point_counts[process] > 0) + MPI_Gather( + &this_process_owns_remapped_point[displs[process]], + reference_point_counts[process], + MPI_C_BOOL, + &remapped_point_candidates[0], + reference_point_counts[process], + MPI_C_BOOL, + process, + mpi_communicator); + } + + std::vector remapped_point_owning_process(num_reference_points); + + for (int i = 0; i < num_reference_points; ++i) { + remapped_point_owning_process[i] = 0; + for (int j = 1; j < nprocesses; ++j) { + if (remapped_point_candidates[j * num_reference_points + i] == 1) { + remapped_point_owning_process[i] = j; + continue; + } + } + } + + std::vector> mapping_remapped_points; + std::vector mapping_reference_point_owning_process; + std::vector mapping_reference_point_index_at_remote_process; + + // This should really be a vector, but addresses of individual elements of + // vector cannot be taken. It's a template specialization to save space + std::vector remote_remapped_point_is_accepted(num_reference_points * nprocesses); + std::vector local_remapped_point_is_accepted(count_received_reference_points); + for (int i = 0; i < num_reference_points; ++i) { + for (unsigned int j = 0; j < static_cast(nprocesses); ++j) { + remote_remapped_point_is_accepted[j * num_reference_points + i] = (remapped_point_owning_process[i] == j) ? 1 : 0; + } + } + + MPI_Barrier(mpi_communicator); + + for (int process = 0; process < nprocesses; ++process) { + if (reference_point_counts[process] > 0) { + MPI_Scatter( + &remote_remapped_point_is_accepted[0], + reference_point_counts[process], + MPI_C_BOOL, + &local_remapped_point_is_accepted[displs[process]], + reference_point_counts[process], + MPI_C_BOOL, + process, + mpi_communicator); + } + } + + std::vector mapping_remote_reference_point_counts(nprocesses, 0); + for (int process = 0; process < nprocesses; ++process) { + for (int i = 0; i < reference_point_counts[process]; ++i) { + if (local_remapped_point_is_accepted[displs[process] + i]) { + RemappedPoint accepted_remapped_point = remapped_points[displs[process] + i]; + + mapping_remapped_points.push_back(accepted_remapped_point); + mapping_reference_point_owning_process.push_back(process); + mapping_reference_point_index_at_remote_process.push_back(i); + ++mapping_remote_reference_point_counts[process]; + } + } + } + + MPI_Barrier(mpi_communicator); + + std::vector mapping_remote_remapped_point_counts(nprocesses); + for (int i = 0; i < nprocesses; ++i) { + MPI_Scatter( + &mapping_remote_reference_point_counts[0], + 1, MPI_UNSIGNED, + &mapping_remote_remapped_point_counts[i], + 1, MPI_UNSIGNED, + i, mpi_communicator); + } + + { + std::vector > local_state_parameter_groups(nprocesses); + std::vector > remote_state_parameter_groups(nprocesses); + + std::vector > local_deformation_gradient_groups(nprocesses); + std::vector > remote_deformation_gradient_groups(nprocesses); + + for (int i = 0; i < nprocesses; ++i) { + local_state_parameter_groups.at(i).resize(material_parameter_count * mapping_remote_reference_point_counts.at(i)); + remote_state_parameter_groups.at(i).resize(material_parameter_count * mapping_remote_remapped_point_counts.at(i)); + + local_deformation_gradient_groups.at(i).resize((dim+1) * (dim+1) * mapping_remote_reference_point_counts.at(i)); + remote_deformation_gradient_groups.at(i).resize((dim+1) * (dim+1) * mapping_remote_remapped_point_counts.at(i)); + } + + std::vector next_to_process(nprocesses, 0); + for (unsigned int i = 0; i < mapping_remapped_points.size(); ++i) { + const unsigned int group = mapping_reference_point_owning_process.at(i); + const RemappedPoint remapped_point = mapping_remapped_points.at(i); + + Quadrature remapped_point_quadrature( + std::vector> (1, remapped_point.unit_cell_point)); + + FEValues remapped_point_fe_values( + mapping, + mesh_motion_fe, + remapped_point_quadrature, + update_values | update_gradients | update_quadrature_points); + + FEValues remapped_point_mechanical_fe_values( + mapping, + mech_fe, + remapped_point_quadrature, + update_values | update_gradients); + + FEValues remapped_point_mixed_fe_values( + mapping, + mixed_fe_dof_system.dof_handler.get_fe(), + remapped_point_quadrature, + update_values); + + remapped_point_fe_values.reinit(remapped_point.mesh_motion_cell); + mesh_motion_fe_values.reinit(remapped_point.mesh_motion_cell); + + remapped_point_mechanical_fe_values.reinit(remapped_point.field_cell); + mechanical_fe_values.reinit(remapped_point.field_cell); + + remapped_point_mixed_fe_values.reinit(remapped_point.mixed_fe_cell); + + mesh_motion_fe_values[displacements].get_function_gradients( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_gradient_increments); + + mesh_motion_fe_values[displacements].get_function_values( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_value_increments); + + mechanical_fe_values[displacements].get_function_gradients( + mechanical_nonlinear_system.previous_deformation, + previous_deformation_gradients); + + mechanical_fe_values[displacements].get_function_values( + mechanical_nonlinear_system.previous_deformation, + previous_deformation_values); + + remapped_point_mechanical_fe_values[displacements].get_function_gradients( + mechanical_nonlinear_system.previous_deformation, + previous_deformation_gradient_at_remapped_point); + + remapped_point_mechanical_fe_values[displacements].get_function_values( + mechanical_nonlinear_system.previous_deformation, + previous_deformation_value_at_remapped_point); + + std::vector< std::vector > material_parameters_at_q_points( + material_parameter_count, + std::vector(n_q_points)); + + for(unsigned int q_point=0; q_pointuser_index() + q_point; + + const auto deformation_gradient = + get_deformation_gradient( + previous_deformation_gradients[q_point], + previous_deformation_values[q_point][0]/mesh_motion_fe_values.quadrature_point(q_point)[0]); + + std::vector state_parameters = material.get_state_parameters(quadrature_point_index, /*deformation_gradient*/unit_symmetric_tensor()); + + for(unsigned int parameter_index=0; parameter_index > projected_material_parameters_coefficients( + material_parameter_count, + std::vector(mixed_dofs_per_cell)); + + const unsigned int cell_index = remapped_point.mesh_motion_cell->user_index() / n_q_points; + for(unsigned int parameter_index=0; parameter_index mixed_values (mixed_dofs_per_cell); + for (unsigned int mixed_dof = 0; mixed_dof < mixed_dofs_per_cell; ++mixed_dof) { + mixed_values(mixed_dof) = remapped_point_mixed_fe_values.shape_value(mixed_dof, 0); + } + + std::vector projected_state_parameters(material_parameter_count, 0); + for(unsigned int parameter_index=0; parameter_index previous_deformation_gradient = + get_deformation_gradient( + previous_deformation_gradient_at_remapped_point[0], + previous_deformation_value_at_remapped_point[0][0]/remapped_point_fe_values.quadrature_point(0)[0]); + + for(unsigned int dim_i=0; dim_i requests_vector(2 * nprocesses * request_array_size); + + for (int i = 0; i < nprocesses; ++i) { + MPI_Isend( + &local_state_parameter_groups.at(i)[0], + material_parameter_count * mapping_remote_reference_point_counts.at(i), + MPI_DOUBLE, i, MATERIAL_STATE_PARAMETER, + mpi_communicator, + &requests_vector[i + nprocesses * material_state_parameter_requests_offset]); + } + + for (int i = 0; i < nprocesses; ++i) { + MPI_Isend( + &local_deformation_gradient_groups.at(i)[0], + (dim+1) * (dim+1) * mapping_remote_reference_point_counts.at(i), + MPI_DOUBLE, i, REMAPPED_DEFORMATION_GRADIENT, + mpi_communicator, + &requests_vector[i + nprocesses * remapped_deformation_gradient_requests_offset]); + } + + for (int i = 0; i < nprocesses; ++i) { + const unsigned int row_start = i + nprocesses * request_array_size; + + MPI_Irecv( + &remote_state_parameter_groups.at(i)[0], + material_parameter_count * mapping_remote_remapped_point_counts.at(i), + MPI_DOUBLE, i, MATERIAL_STATE_PARAMETER, + mpi_communicator, + &requests_vector[row_start + nprocesses * material_state_parameter_requests_offset]); + + MPI_Irecv( + &remote_deformation_gradient_groups.at(i)[0], + (dim+1) * (dim+1) * mapping_remote_remapped_point_counts.at(i), + MPI_DOUBLE, i, REMAPPED_DEFORMATION_GRADIENT, + mpi_communicator, + &requests_vector[row_start + nprocesses * remapped_deformation_gradient_requests_offset]); + + } + + std::vector statuses_vector(2 * request_array_size * nprocesses); + MPI_Waitall( + 2 * request_array_size * nprocesses, + &requests_vector[0], + &statuses_vector[0]); + + next_to_process.clear(); + next_to_process.resize(nprocesses, 0); + for (unsigned int i = 0; i < reference_points.size(); ++i) { + unsigned int group = remapped_point_owning_process.at(i); + + ReferencePoint &reference_point = reference_points[i]; + + mesh_motion_fe_values.reinit(reference_point.mesh_motion_cell); + + std::vector remapped_state_parameters(material_parameter_count); + for(unsigned int state_index=0; state_index previous_deformation_gradient; + for(unsigned int dim_i=0; dim_iuser_index() + reference_point.q_point; + material.set_state_parameters(quadrature_point_index, remapped_state_parameters, /*previous_deformation_gradient **/ /*mesh_motion_gradient*/unit_symmetric_tensor()); + remapped_deformation_gradients[quadrature_point_index] = previous_deformation_gradient; + + ++next_to_process.at(group); + } + + } + } + + template + void PlasticityLabProg::remap_thermal_field( + NewtonStepSystem &thermal_nonlinear_system, + const DoFSystem &thermal_dof_system, + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system) { + + const Quadrature thermal_fe_support_point_quadrature(therm_fe.get_unit_support_points()); + + const unsigned int n_q_points = thermal_fe_support_point_quadrature.size(); + const unsigned int dofs_per_cell = mesh_motion_fe.dofs_per_cell; + const unsigned int thermal_dofs_per_cell = therm_fe.dofs_per_cell; + + FEValues mesh_motion_fe_values( + mapping, + mesh_motion_fe, + thermal_fe_support_point_quadrature, + update_values | update_quadrature_points); + + FEValues thermal_fe_values( + mapping, + therm_fe, + thermal_fe_support_point_quadrature, + update_values | update_quadrature_points); + + std::vector< Number > previous_temperatures(1); + std::vector< Tensor<1, dim, Number> > mesh_motion_value_increments(n_q_points); + std::vector< Tensor<2, dim, Number> > mesh_motion_gradient_increments(n_q_points); + + const FEValuesExtractors::Vector displacements(0); + const FEValuesExtractors::Scalar temperature (0); + + std::vector> reference_points; + std::vector> remapped_point_positions; + + auto cell = mesh_motion_dof_system.dof_handler.begin_active(); + auto thermal_cell = thermal_dof_system.dof_handler.begin_active(); + for (; cell != mesh_motion_dof_system.dof_handler.end(); ++cell, ++thermal_cell) { + if (cell->is_locally_owned()) { + mesh_motion_fe_values.reinit(cell); + + mesh_motion_fe_values[displacements].get_function_values( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_value_increments); + + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + const Point reference_point_position = mesh_motion_fe_values.quadrature_point(q_point); + const Point remapped_point_position = reference_point_position - mesh_motion_value_increments[q_point]; + + ReferencePoint reference_point; + reference_point.mesh_motion_cell = cell; + reference_point.field_cell = thermal_cell; + reference_point.q_point = q_point; + reference_point.reference_point = reference_point_position; + reference_point.remapped_point = remapped_point_position; + + reference_points.push_back(reference_point); + remapped_point_positions.push_back(remapped_point_position); + + } + + } + } + + MPI_Datatype PointType; + MPI_Type_contiguous(dim, MPI_DOUBLE, &PointType); + MPI_Type_commit(&PointType); + std::vector displs; + std::vector< Point> received_remapped_positions; + std::vector> thermal_points; + int nprocesses, this_process; + int num_reference_points = reference_points.size(); + MPI_Comm_size(mpi_communicator, &nprocesses); + std::vector reference_point_counts(nprocesses); + MPI_Allgather( + &num_reference_points, + 1, MPI_INT, + &reference_point_counts[0], + 1, MPI_INT, + mpi_communicator); + MPI_Comm_rank(mpi_communicator, &this_process); + displs.resize(nprocesses); + displs[0] = 0; + for (int i = 1; i < nprocesses; ++i) { + displs[i] = displs[i - 1] + reference_point_counts[i - 1]; + } + + const unsigned int count_received_reference_points = displs[nprocesses - 1] + reference_point_counts[nprocesses - 1]; + received_remapped_positions.resize(count_received_reference_points); + thermal_points.resize(count_received_reference_points); + std::vector this_process_owns_remapped_point(count_received_reference_points); + std::vector this_process_owns_thermal_point(count_received_reference_points); + + MPI_Allgatherv( + &remapped_point_positions[0], + num_reference_points, + PointType, + &received_remapped_positions[0], + &reference_point_counts[0], + &displs[0], + PointType, + mpi_communicator); + + + for(unsigned int received_point_id=0; received_point_id < count_received_reference_points; received_point_id++) { + auto point = received_remapped_positions[received_point_id]; + auto thermal_cell_and_point = GridTools::find_active_cell_around_point( + mapping, + thermal_dof_system.dof_handler, + point); + auto thermal_cell = thermal_cell_and_point.first; + auto thermal_unit_cell_point = thermal_cell_and_point.second; + thermal_points[received_point_id].field_cell = thermal_cell; + thermal_points[received_point_id].unit_cell_point = thermal_unit_cell_point; + thermal_points[received_point_id].remapped_point = point; + this_process_owns_thermal_point[received_point_id] = thermal_cell.state() == IteratorState::valid && thermal_cell->is_locally_owned()? 1 : 0; + } + + std::vector thermal_point_candidates(num_reference_points * nprocesses); + for (int process = 0; process < nprocesses; ++process) { + if (reference_point_counts[process] > 0) + MPI_Gather( + &this_process_owns_thermal_point[displs[process]], + reference_point_counts[process], + MPI_C_BOOL, + &thermal_point_candidates[0], + reference_point_counts[process], + MPI_C_BOOL, + process, + mpi_communicator); + } + + std::vector thermal_point_owning_process(num_reference_points); + for (int i = 0; i < num_reference_points; ++i) { + thermal_point_owning_process[i] = 0; + for (int j = 1; j < nprocesses; ++j) { + if (thermal_point_candidates[j * num_reference_points + i] == 1) { + thermal_point_owning_process[i] = j; + continue; + } + } + } + + std::vector> mapping_thermal_points; + std::vector thermal_reference_point_owning_process; + std::vector thermal_reference_point_index_at_remote_process; + + // This should really be a vector, but addresses of individual elements of + // vector cannot be taken. It's a template specialization to save space + std::vector remote_thermal_point_is_accepted(num_reference_points * nprocesses); + std::vector local_thermal_point_is_accepted(count_received_reference_points); + for (int i = 0; i < num_reference_points; ++i) { + for (unsigned int j = 0; j < static_cast(nprocesses); ++j) { + remote_thermal_point_is_accepted[j * num_reference_points + i] = (thermal_point_owning_process[i] == j) ? 1 : 0; + } + } + + for (int process = 0; process < nprocesses; ++process) { + if (reference_point_counts[process] > 0) { + MPI_Scatter( + &remote_thermal_point_is_accepted[0], + reference_point_counts[process], + MPI_C_BOOL, + &local_thermal_point_is_accepted[displs[process]], + reference_point_counts[process], + MPI_C_BOOL, + process, + mpi_communicator); + } + } + + std::vector thermal_remote_reference_point_counts(nprocesses, 0); + for (int process = 0; process < nprocesses; ++process) { + for (int i = 0; i < reference_point_counts[process]; ++i) { + if (local_thermal_point_is_accepted[displs[process] + i]) { + RemappedPoint accepted_thermal_point = thermal_points[displs[process] + i]; + + mapping_thermal_points.push_back(accepted_thermal_point); + thermal_reference_point_owning_process.push_back(process); + thermal_reference_point_index_at_remote_process.push_back(i); + ++thermal_remote_reference_point_counts[process]; + } + } + } + + MPI_Barrier(mpi_communicator); + + std::vector thermal_remote_remapped_point_counts(nprocesses); + for (int i = 0; i < nprocesses; ++i) { + MPI_Scatter( + &thermal_remote_reference_point_counts[0], + 1, MPI_UNSIGNED, + &thermal_remote_remapped_point_counts[i], + 1, MPI_UNSIGNED, + i, mpi_communicator); + } + + + + { + std::vector > local_previous_temperature_groups(nprocesses); + std::vector > remote_previous_temperature_groups(nprocesses); + + for (int i = 0; i < nprocesses; ++i) { + local_previous_temperature_groups.at(i).resize(thermal_remote_reference_point_counts.at(i)); + remote_previous_temperature_groups.at(i).resize(thermal_remote_remapped_point_counts.at(i)); + } + + std::vector next_to_process(nprocesses, 0); + for (unsigned int i = 0; i < mapping_thermal_points.size(); ++i) { + const unsigned int group = thermal_reference_point_owning_process.at(i); + const RemappedPoint thermal_point = mapping_thermal_points.at(i); + + Quadrature thermal_point_quadrature( + std::vector> (1, thermal_point.unit_cell_point)); + + FEValues thermal_point_fe_values( + mapping, + therm_fe, + thermal_point_quadrature, + update_values); + + thermal_point_fe_values.reinit(thermal_point.field_cell); + + thermal_point_fe_values[temperature].get_function_values( + thermal_nonlinear_system.previous_deformation, + previous_temperatures); + + local_previous_temperature_groups.at(group).at(next_to_process.at(group)) = previous_temperatures[0]; + + ++next_to_process.at(group); + } + + + + enum MessageFlag { + PREVIOUS_TEMPERATURE + }; + + const unsigned int + previous_temperature_requests_offset = 0, + request_array_size = 1; + + std::vector requests_vector(2 * nprocesses * request_array_size); + + for (int i = 0; i < nprocesses; ++i) { + MPI_Isend( + &local_previous_temperature_groups.at(i)[0], + thermal_remote_reference_point_counts.at(i), + MPI_DOUBLE, i, PREVIOUS_TEMPERATURE, + mpi_communicator, + &requests_vector[i + nprocesses * previous_temperature_requests_offset]); + } + + for (int i = 0; i < nprocesses; ++i) { + const unsigned int row_start = i + nprocesses * request_array_size; + + MPI_Irecv( + &remote_previous_temperature_groups.at(i)[0], + thermal_remote_remapped_point_counts.at(i), + MPI_DOUBLE, i, PREVIOUS_TEMPERATURE, + mpi_communicator, + &requests_vector[row_start + nprocesses * previous_temperature_requests_offset]); + + } + + std::vector statuses_vector(2 * request_array_size * nprocesses); + MPI_Waitall( + 2 * request_array_size * nprocesses, + &requests_vector[0], + &statuses_vector[0]); + + TrilinosWrappers::SparsityPattern sparsity_pattern( + thermal_dof_system.locally_owned_dofs, + mpi_communicator); + + DoFTools::make_sparsity_pattern( + thermal_dof_system.dof_handler, sparsity_pattern, + AffineConstraints(), + false, + Utilities::MPI::this_mpi_process(mpi_communicator)); + sparsity_pattern.compress(); + + TrilinosWrappers::SparseMatrix projection_matrix(sparsity_pattern); + TrilinosWrappers::MPI::Vector projection_residual(thermal_dof_system.locally_owned_dofs, mpi_communicator); + + projection_matrix = 0; + projection_residual = 0; + + projection_matrix = 0; + projection_residual = 0; + FullMatrix cell_matrix(thermal_dofs_per_cell, thermal_dofs_per_cell); + Vector cell_residual(thermal_dofs_per_cell); + next_to_process.clear(); + next_to_process.resize(nprocesses, 0); + for (unsigned int i = 0; i < reference_points.size(); ++i) { + unsigned int group = thermal_point_owning_process.at(i); + + cell_matrix = 0; + cell_residual = 0; + + ReferencePoint &reference_point = reference_points[i]; + + thermal_fe_values.reinit(reference_point.field_cell); + + const Number remapped_previous_temperature = remote_previous_temperature_groups.at(group).at(next_to_process.at(group)); + for(unsigned int dof_i=0; dof_i local_dof_indices(thermal_dofs_per_cell); + reference_point.field_cell->get_dof_indices(local_dof_indices); + + projection_residual.add(local_dof_indices, cell_residual); + for(unsigned int dof_i=0; dof_i > constant_modes; + DoFTools::extract_constant_modes(thermal_dof_system.dof_handler, ComponentMask(), constant_modes); + + TrilinosWrappers::PreconditionAMG::AdditionalData additional_data; + additional_data.constant_modes = constant_modes; + additional_data.elliptic = true; + additional_data.n_cycles = 1; + additional_data.w_cycle = false; + additional_data.output_details = false; + additional_data.smoother_sweeps = 2; + additional_data.aggregation_threshold = 1e-2; + preconditioner.initialize(projection_matrix, additional_data); + + TrilinosWrappers::MPI::Vector tmp(thermal_dof_system.locally_owned_dofs, mpi_communicator); + const Number relative_accuracy = 1e-08; + const Number solver_tolerance = relative_accuracy + * projection_matrix.residual(tmp, thermal_nonlinear_system.Newton_step_solution, + projection_residual); + SolverControl solver_control(projection_matrix.m(), + solver_tolerance); + + SolverBicgstab solver(solver_control); + + thermal_nonlinear_system.Newton_step_solution = 0; + + solver.solve(projection_matrix, thermal_nonlinear_system.Newton_step_solution, + projection_residual, preconditioner); + + thermal_nonlinear_system.previous_deformation = thermal_nonlinear_system.Newton_step_solution; + + } + + } + + + template + void PlasticityLabProg::remap_mechanical_fields( + NewtonStepSystem &mechanical_nonlinear_system, + const DoFSystem &mechanical_dof_system, + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system) { + + const Quadrature mechanical_fe_support_point_quadrature(mech_fe.base_element(0).get_unit_support_points()); + + const unsigned int n_q_points = mechanical_fe_support_point_quadrature.size(); + const unsigned int dofs_per_cell = mesh_motion_fe.dofs_per_cell; + const unsigned int mechanical_dofs_per_cell = mech_fe.dofs_per_cell; + + FEValues mesh_motion_fe_values( + mapping, + mesh_motion_fe, + mechanical_fe_support_point_quadrature, + update_values | update_quadrature_points); + + FEValues mechanical_fe_values( + mapping, + mech_fe, + mechanical_fe_support_point_quadrature, + update_values | update_quadrature_points); + + std::vector< Tensor<1, dim, Number> > previous_remapped_deformations(1); + std::vector< Tensor<1, dim, Number> > previous_remapped_velocity(1); + std::vector< Tensor<1, dim, Number> > previous_remapped_second_time_rate(1); + std::vector< Number > previous_remapped_twist_deformations(1); + std::vector< Number > previous_remapped_twist_velocity(1); + std::vector< Number > previous_remapped_twist_second_time_rate(1); + std::vector< Tensor<1, dim, Number> > mesh_motion_value_increments(n_q_points); + std::vector< Tensor<2, dim, Number> > mesh_motion_gradient_increments(n_q_points); + + const FEValuesExtractors::Vector displacements(0); + const FEValuesExtractors::Scalar angular_velocities(dim); + + std::vector> reference_points; + std::vector> remapped_point_positions; + std::unordered_map quadrature_point_reference_point_id; + auto cell = mesh_motion_dof_system.dof_handler.begin_active(); + auto mechanical_cell = mechanical_dof_system.dof_handler.begin_active(); + for (; cell != mesh_motion_dof_system.dof_handler.end(); ++cell, ++mechanical_cell) { + if (cell->is_locally_owned()) { + mesh_motion_fe_values.reinit(cell); + + mesh_motion_fe_values[displacements].get_function_values( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_value_increments); + + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + const Point reference_point_position = mesh_motion_fe_values.quadrature_point(q_point); + const Point remapped_point_position = reference_point_position - mesh_motion_value_increments[q_point]; + + ReferencePoint reference_point; + reference_point.mesh_motion_cell = cell; + reference_point.field_cell = mechanical_cell; + reference_point.q_point = q_point; + reference_point.reference_point = reference_point_position; + reference_point.remapped_point = remapped_point_position; + + reference_points.push_back(reference_point); + remapped_point_positions.push_back(remapped_point_position); + + const point_index_t quadrature_point_index = cell->user_index() + q_point; + quadrature_point_reference_point_id[quadrature_point_index] = reference_points.size() - 1; + + } + + } + } + + MPI_Datatype PointType; + MPI_Type_contiguous(dim, MPI_DOUBLE, &PointType); + MPI_Type_commit(&PointType); + std::vector displs; + std::vector< Point> received_remapped_positions; + std::vector> remapped_points; + int nprocesses, this_process; + int num_reference_points = reference_points.size(); + MPI_Comm_size(mpi_communicator, &nprocesses); + std::vector reference_point_counts(nprocesses); + MPI_Allgather( + &num_reference_points, + 1, MPI_INT, + &reference_point_counts[0], + 1, MPI_INT, + mpi_communicator); + MPI_Comm_rank(mpi_communicator, &this_process); + displs.resize(nprocesses); + displs[0] = 0; + for (int i = 1; i < nprocesses; ++i) { + displs[i] = displs[i - 1] + reference_point_counts[i - 1]; + } + + const unsigned int count_received_reference_points = displs[nprocesses - 1] + reference_point_counts[nprocesses - 1]; + received_remapped_positions.resize(count_received_reference_points); + remapped_points.resize(count_received_reference_points); + std::vector this_process_owns_remapped_point(count_received_reference_points); + + MPI_Allgatherv( + &remapped_point_positions[0], + num_reference_points, + PointType, + &received_remapped_positions[0], + &reference_point_counts[0], + &displs[0], + PointType, + mpi_communicator); + + + for(unsigned int received_point_id=0; received_point_id < count_received_reference_points; received_point_id++) { + auto point = received_remapped_positions[received_point_id]; + auto remapped_cell_and_point = GridTools::find_active_cell_around_point( + mapping, + mechanical_dof_system.dof_handler, + point); + auto mechanical_cell = remapped_cell_and_point.first; + auto mechanical_unit_cell_point = remapped_cell_and_point.second; + remapped_points[received_point_id].field_cell = mechanical_cell; + remapped_points[received_point_id].unit_cell_point = mechanical_unit_cell_point; + remapped_points[received_point_id].remapped_point = point; + this_process_owns_remapped_point[received_point_id] = mechanical_cell.state() == IteratorState::valid && mechanical_cell->is_locally_owned()? 1 : 0; + } + + std::vector remapped_point_candidates(num_reference_points * nprocesses); + for (int process = 0; process < nprocesses; ++process) { + if (reference_point_counts[process] > 0) + MPI_Gather( + &this_process_owns_remapped_point[displs[process]], + reference_point_counts[process], + MPI_C_BOOL, + &remapped_point_candidates[0], + reference_point_counts[process], + MPI_C_BOOL, + process, + mpi_communicator); + } + + std::vector remapped_point_owning_process(num_reference_points); + for (int i = 0; i < num_reference_points; ++i) { + remapped_point_owning_process[i] = 0; + for (int j = 1; j < nprocesses; ++j) { + if (remapped_point_candidates[j * num_reference_points + i] == 1) { + remapped_point_owning_process[i] = j; + continue; + } + } + } + + std::vector> mapping_remapped_points; + std::vector reference_point_owning_process; + std::vector reference_point_index_at_remote_process; + + // This should really be a vector, but addresses of individual elements of + // vector cannot be taken. It's a template specialization to save space + std::vector remote_remapped_point_is_accepted(num_reference_points * nprocesses); + std::vector local_remapped_point_is_accepted(count_received_reference_points); + for (int i = 0; i < num_reference_points; ++i) { + for (unsigned int j = 0; j < static_cast(nprocesses); ++j) { + remote_remapped_point_is_accepted[j * num_reference_points + i] = (remapped_point_owning_process[i] == j) ? 1 : 0; + } + } + + for (int process = 0; process < nprocesses; ++process) { + if (reference_point_counts[process] > 0) { + MPI_Scatter( + &remote_remapped_point_is_accepted[0], + reference_point_counts[process], + MPI_C_BOOL, + &local_remapped_point_is_accepted[displs[process]], + reference_point_counts[process], + MPI_C_BOOL, + process, + mpi_communicator); + } + } + + std::vector remote_reference_point_counts(nprocesses, 0); + for (int process = 0; process < nprocesses; ++process) { + for (int i = 0; i < reference_point_counts[process]; ++i) { + if (local_remapped_point_is_accepted[displs[process] + i]) { + RemappedPoint accepted_remapped_point = remapped_points[displs[process] + i]; + + mapping_remapped_points.push_back(accepted_remapped_point); + reference_point_owning_process.push_back(process); + reference_point_index_at_remote_process.push_back(i); + ++remote_reference_point_counts[process]; + } + } + } + + MPI_Barrier(mpi_communicator); + + std::vector remote_remapped_point_counts(nprocesses); + for (int i = 0; i < nprocesses; ++i) { + MPI_Scatter( + &remote_reference_point_counts[0], + 1, MPI_UNSIGNED, + &remote_remapped_point_counts[i], + 1, MPI_UNSIGNED, + i, mpi_communicator); + } + + std::vector > local_previous_deformation_groups(nprocesses); + std::vector > local_previous_velocity_groups(nprocesses); + std::vector > local_previous_second_time_rate_groups(nprocesses); + std::vector > remote_previous_deformation_groups(nprocesses); + std::vector > remote_previous_velocity_groups(nprocesses); + std::vector > remote_previous_second_time_rate_groups(nprocesses); + + for (int i = 0; i < nprocesses; ++i) { + local_previous_deformation_groups.at(i).resize((dim+1) * remote_reference_point_counts.at(i)); + local_previous_velocity_groups.at(i).resize((dim+1) * remote_reference_point_counts.at(i)); + local_previous_second_time_rate_groups.at(i).resize((dim+1) * remote_reference_point_counts.at(i)); + remote_previous_deformation_groups.at(i).resize((dim+1) * remote_remapped_point_counts.at(i)); + remote_previous_velocity_groups.at(i).resize((dim+1) * remote_remapped_point_counts.at(i)); + remote_previous_second_time_rate_groups.at(i).resize((dim+1) * remote_remapped_point_counts.at(i)); + } + + std::vector next_to_process(nprocesses, 0); + for (unsigned int i = 0; i < mapping_remapped_points.size(); ++i) { + const unsigned int group = reference_point_owning_process.at(i); + const RemappedPoint remapped_point = mapping_remapped_points.at(i); + + Quadrature remapped_point_quadrature( + std::vector> (1, remapped_point.unit_cell_point)); + + FEValues remapped_point_fe_values( + mapping, + mech_fe, + remapped_point_quadrature, + update_values); + + remapped_point_fe_values.reinit(remapped_point.field_cell); + + remapped_point_fe_values[displacements].get_function_values( + mechanical_nonlinear_system.previous_deformation, + previous_remapped_deformations); + + remapped_point_fe_values[displacements].get_function_values( + mechanical_nonlinear_system.previous_time_derivative, + previous_remapped_velocity); + + remapped_point_fe_values[displacements].get_function_values( + mechanical_nonlinear_system.previous_second_time_derivative, + previous_remapped_second_time_rate); + + remapped_point_fe_values[angular_velocities].get_function_values( + mechanical_nonlinear_system.previous_deformation, + previous_remapped_twist_deformations); + + remapped_point_fe_values[angular_velocities].get_function_values( + mechanical_nonlinear_system.previous_time_derivative, + previous_remapped_twist_velocity); + + remapped_point_fe_values[angular_velocities].get_function_values( + mechanical_nonlinear_system.previous_second_time_derivative, + previous_remapped_twist_second_time_rate); + + for(unsigned int dim_i=0; dim_i requests_vector(2 * nprocesses * request_array_size); + + for (int i = 0; i < nprocesses; ++i) { + MPI_Isend( + &local_previous_deformation_groups.at(i)[0], + (dim+1) * remote_reference_point_counts.at(i), + MPI_DOUBLE, i, PREVIOUS_DEFORMATION, + mpi_communicator, + &requests_vector[i + nprocesses * previous_deformation_requests_offset]); + + MPI_Isend( + &local_previous_velocity_groups.at(i)[0], + (dim+1) * remote_reference_point_counts.at(i), + MPI_DOUBLE, i, PREVIOUS_VELOCITY, + mpi_communicator, + &requests_vector[i + nprocesses * previous_velocity_requests_offset]); + + MPI_Isend( + &local_previous_second_time_rate_groups.at(i)[0], + (dim+1) * remote_reference_point_counts.at(i), + MPI_DOUBLE, i, PREVIOUS_SECOND_TIME_RATE, + mpi_communicator, + &requests_vector[i + nprocesses * previous_second_time_rate_requests_offset]); + } + + for (int i = 0; i < nprocesses; ++i) { + const unsigned int row_start = i + nprocesses * request_array_size; + + MPI_Irecv( + &remote_previous_deformation_groups.at(i)[0], + (dim+1) * remote_remapped_point_counts.at(i), + MPI_DOUBLE, i, PREVIOUS_DEFORMATION, + mpi_communicator, + &requests_vector[row_start + nprocesses * previous_deformation_requests_offset]); + + MPI_Irecv( + &remote_previous_velocity_groups.at(i)[0], + (dim+1) * remote_remapped_point_counts.at(i), + MPI_DOUBLE, i, PREVIOUS_VELOCITY, + mpi_communicator, + &requests_vector[row_start + nprocesses * previous_velocity_requests_offset]); + + MPI_Irecv( + &remote_previous_second_time_rate_groups.at(i)[0], + (dim+1) * remote_remapped_point_counts.at(i), + MPI_DOUBLE, i, PREVIOUS_SECOND_TIME_RATE, + mpi_communicator, + &requests_vector[row_start + nprocesses * previous_second_time_rate_requests_offset]); + + } + + std::vector statuses_vector(2 * request_array_size * nprocesses); + MPI_Waitall( + 2 * request_array_size * nprocesses, + &requests_vector[0], + &statuses_vector[0]); + + TrilinosWrappers::SparsityPattern sparsity_pattern( + mechanical_dof_system.locally_owned_dofs, + mpi_communicator); + + DoFTools::make_sparsity_pattern( + mechanical_dof_system.dof_handler, sparsity_pattern, + AffineConstraints(), + false, + Utilities::MPI::this_mpi_process(mpi_communicator)); + sparsity_pattern.compress(); + + TrilinosWrappers::SparseMatrix projection_matrix(sparsity_pattern); + TrilinosWrappers::MPI::Vector projection_residual(mechanical_dof_system.locally_owned_dofs, mpi_communicator); + TrilinosWrappers::MPI::Vector projection_velocity_residual(mechanical_dof_system.locally_owned_dofs, mpi_communicator); + TrilinosWrappers::MPI::Vector projection_second_time_rate_residual(mechanical_dof_system.locally_owned_dofs, mpi_communicator); + TrilinosWrappers::MPI::Vector projection_solution(mechanical_dof_system.locally_owned_dofs, mpi_communicator); + + projection_matrix = 0; + projection_residual = 0; + projection_velocity_residual = 0; + projection_second_time_rate_residual = 0; + + FullMatrix cell_matrix(mechanical_dofs_per_cell, mechanical_dofs_per_cell); + Vector cell_residual(mechanical_dofs_per_cell); + Vector cell_velocity_residual(mechanical_dofs_per_cell); + Vector cell_second_time_rate_residual(mechanical_dofs_per_cell); + + next_to_process.clear(); + next_to_process.resize(nprocesses, 0); + for (unsigned int i = 0; i < reference_points.size(); ++i) { + unsigned int group = remapped_point_owning_process.at(i); + + cell_matrix = 0; + cell_residual = 0; + cell_velocity_residual = 0; + cell_second_time_rate_residual = 0; + + ReferencePoint &reference_point = reference_points[i]; + + mechanical_fe_values.reinit(reference_point.field_cell); + + Tensor<1, dim, Number> remapped_previous_deformation; + Tensor<1, dim, Number> remapped_previous_velocity; + Tensor<1, dim, Number> remapped_previous_second_time_rate; + + for(unsigned int dim_i=0; dim_i local_dof_indices(mechanical_dofs_per_cell); + reference_point.field_cell->get_dof_indices(local_dof_indices); + projection_residual.add(local_dof_indices, cell_residual); + projection_velocity_residual.add(local_dof_indices, cell_velocity_residual); + projection_second_time_rate_residual.add(local_dof_indices, cell_second_time_rate_residual); + for(unsigned int dof_i=0; dof_i > constant_modes; + DoFTools::extract_constant_modes(mechanical_dof_system.dof_handler, ComponentMask(), constant_modes); + + TrilinosWrappers::PreconditionAMG::AdditionalData additional_data; + additional_data.constant_modes = constant_modes; + additional_data.elliptic = true; + additional_data.n_cycles = 1; + additional_data.w_cycle = false; + additional_data.output_details = false; + additional_data.smoother_sweeps = 2; + additional_data.aggregation_threshold = 1e-2; + preconditioner.initialize(projection_matrix, additional_data); + + TrilinosWrappers::MPI::Vector tmp(mechanical_dof_system.locally_owned_dofs, mpi_communicator); + const Number relative_accuracy = 1e-08; + const Number solver_tolerance = relative_accuracy + * projection_matrix.residual(tmp, projection_solution, + projection_residual); + SolverControl solver_control(projection_matrix.m(), + solver_tolerance); + + SolverBicgstab solver(solver_control); + + projection_solution = 0; + + solver.solve(projection_matrix, projection_solution, + projection_residual, preconditioner); + + mechanical_nonlinear_system.previous_deformation = projection_solution; + + projection_solution = 0; + solver.solve(projection_matrix, projection_solution, + projection_velocity_residual, preconditioner); + mechanical_nonlinear_system.previous_time_derivative = projection_solution; + + projection_solution = 0; + solver.solve(projection_matrix, projection_solution, + projection_second_time_rate_residual, preconditioner); + mechanical_nonlinear_system.previous_second_time_derivative = projection_solution; + + } + + + template + void PlasticityLabProg::assemble_mechanical_system( + NewtonStepSystem &Newton_system, + const DoFSystem &mechanical_dof_system, + const LBCSystem &mechanical_lbc_system, + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const NewtonStepSystem &thermal_Newton_system, + const DoFSystem &thermal_dof_system, + const DoFSystem &mixed_fe_dof_system, + Material &material, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const bool fill_system_matrix, + const bool update_material_state) { + FEValues fe_values( + mapping, + mech_fe, + quadrature_formula, + update_values | update_quadrature_points | update_gradients | update_JxW_values); + + FEFaceValues fe_face_values( + mapping, + mech_fe, + face_quadrature_formula, + update_values | update_quadrature_points | update_normal_vectors | update_JxW_values); + + FEValues fe_therm_values( + mapping, + therm_fe, + quadrature_formula, + update_values); + + FEValues mesh_motion_fe_values( + mapping, + mesh_motion_fe, + quadrature_formula, + update_values | update_gradients); + + FEValues mixed_fe_values( + mapping, + mixed_var_fe, + quadrature_formula, + update_values); + + const unsigned int dofs_per_cell = mech_fe.dofs_per_cell; + const unsigned int n_q_points = quadrature_formula.size(); + const unsigned int mixed_dofs_per_cell = mixed_var_fe.dofs_per_cell; + const unsigned int n_face_q_points = face_quadrature_formula.size(); + + std::vector< Tensor<2, dim, Number> > current_displacement_gradients(n_q_points); + std::vector< Tensor<2, dim, Number> > displacement_gradient_increments(n_q_points); + + std::vector< Tensor<1, dim, Number> > current_displacement_values(n_q_points); + std::vector< Tensor<1, dim, Number> > displacement_value_increments(n_q_points); + + std::vector< Tensor<2, dim, Number> > displacement_gradient_previous_time_rates(n_q_points); + std::vector< Tensor<2, dim, Number> > displacement_gradient_previous_second_time_rates(n_q_points); + + std::vector< Tensor<1, dim, Number> > displacement_increments(n_q_points); + std::vector< Tensor<1, dim, Number> > displacement_previous_time_rates(n_q_points); + std::vector< Tensor<1, dim, Number> > displacement_previous_second_time_rates(n_q_points); + + std::vector< Tensor<1, dim, Number> > angular_velocity_gradient_increments(n_q_points); + std::vector< Tensor<1, dim, Number> > angular_velocity_gradient_previous_time_rates(n_q_points); + std::vector< Tensor<1, dim, Number> > angular_velocity_gradient_previous_second_time_rates(n_q_points); + + std::vector< Tensor<1, dim, Number> > mesh_motion_value_increments(n_q_points); + std::vector< Tensor<2, dim, Number> > mesh_motion_gradient_increments(n_q_points); + + std::vector< Number > angular_velocity_increments(n_q_points); + std::vector< Number > angular_velocity_previous_time_rates(n_q_points); + std::vector< Number > angular_velocity_previous_second_time_rates(n_q_points); + + std::vector< Number > current_temperature_values(n_q_points); + std::vector< Number > updated_temperature_increments(n_q_points); + std::vector< Number > updated_temperature_values(n_q_points); + + std::vector< Tensor<1, dim, Number> > face_displacement_value_increments(n_face_q_points); + + std::vector< Number > deformation_jacobians(n_q_points); + std::vector< Number > previous_deformation_jacobian(n_q_points); + std::vector< std::vector > strain_divergences( + dofs_per_cell, + std::vector(n_q_points)); + std::vector< std::vector > jacobian_tangents( + dofs_per_cell, + std::vector(n_q_points)); + + std::vector< std::vector< std::vector < Number> > > strain_divergence_tangents( + dofs_per_cell, + std::vector< std::vector< Number> >( + dofs_per_cell, + std::vector(n_q_points))); + + std::vector projected_temperature_coefficients(mixed_dofs_per_cell); + std::vector projected_Jacobian_coefficients(mixed_dofs_per_cell); + std::vector projected_previous_temperature_coefficients(mixed_dofs_per_cell); + std::vector projected_previous_Jacobian_coefficients(mixed_dofs_per_cell); + std::vector > projected_strain_divergence_coefficients( + dofs_per_cell, + std::vector(mixed_dofs_per_cell)); + std::vector > projected_jacobian_tangent_coefficients( + dofs_per_cell, + std::vector(mixed_dofs_per_cell)); + std::vector > > projected_strain_divergence_tangent_coefficients( + dofs_per_cell, std::vector< std::vector< Number> >( + dofs_per_cell, + std::vector(mixed_dofs_per_cell))); + + std::vector projected_strain_divergence(dofs_per_cell); + std::vector projected_jacobian_tangent(dofs_per_cell); + std::vector > projected_strain_divergence_tangent( + dofs_per_cell, + std::vector(dofs_per_cell)); + + FullMatrix cell_matrix(dofs_per_cell, dofs_per_cell); + Vector cell_residual(dofs_per_cell); + + Vector mixed_values (mixed_dofs_per_cell); + + const FEValuesExtractors::Vector displacements (0); + const FEValuesExtractors::Scalar angular_velocity(dim); + const FEValuesExtractors::Scalar temperature (0); + + Newton_system.Newton_step_matrix = 0; + Newton_system.Newton_step_residual = 0; + + double alpha_m, alpha_f, gamma, beta; + get_generalized_alpha_method_params( + &alpha_m, &alpha_f, &gamma, &beta, rho_infty); + + const Number d_second_time_rate_d_increment = (1./(beta*time_increment*time_increment)); + const Number d_time_rate_d_increment = gamma/(beta*time_increment); + + bool kinematic_domains_are_valid = true; // innocent until proven guilty + + auto cell = mechanical_dof_system.dof_handler.begin_active(); + auto endc = mechanical_dof_system.dof_handler.end(); + auto thermal_cell = thermal_dof_system.dof_handler.begin_active(); + auto mesh_motion_cell = mesh_motion_dof_system.dof_handler.begin_active(); + auto mixed_fe_cell = mixed_fe_dof_system.dof_handler.begin_active(); + for (; cell != endc; ++cell, ++thermal_cell, ++mesh_motion_cell, ++mixed_fe_cell) { + if (cell->is_locally_owned()) { + cell_matrix = 0; + cell_residual = 0; + + fe_values.reinit (cell); + fe_therm_values.reinit (thermal_cell); + mixed_fe_values.reinit (mixed_fe_cell); + mesh_motion_fe_values.reinit (mesh_motion_cell); + + fe_values[displacements].get_function_gradients( + Newton_system.current_increment, + displacement_gradient_increments); + + fe_values[displacements].get_function_gradients( + Newton_system.previous_deformation, + current_displacement_gradients); + + fe_values[displacements].get_function_values( + Newton_system.current_increment, + displacement_value_increments); + + fe_values[displacements].get_function_values( + Newton_system.previous_deformation, + current_displacement_values); + + fe_values[displacements].get_function_gradients( + Newton_system.previous_time_derivative, + displacement_gradient_previous_time_rates); + + fe_values[displacements].get_function_gradients( + Newton_system.previous_second_time_derivative, + displacement_gradient_previous_second_time_rates); + + fe_values[displacements].get_function_values( + Newton_system.current_increment, + displacement_increments); + + fe_values[displacements].get_function_values( + Newton_system.previous_time_derivative, + displacement_previous_time_rates); + + fe_values[displacements].get_function_values( + Newton_system.previous_second_time_derivative, + displacement_previous_second_time_rates); + + // Angular velocity + fe_values[angular_velocity].get_function_gradients( + Newton_system.current_increment, + angular_velocity_gradient_increments); + + fe_values[angular_velocity].get_function_gradients( + Newton_system.previous_time_derivative, + angular_velocity_gradient_previous_time_rates); + + fe_values[angular_velocity].get_function_gradients( + Newton_system.previous_second_time_derivative, + angular_velocity_gradient_previous_second_time_rates); + + fe_values[angular_velocity].get_function_values( + Newton_system.current_increment, + angular_velocity_increments); + + fe_values[angular_velocity].get_function_values( + Newton_system.previous_time_derivative, + angular_velocity_previous_time_rates); + + fe_values[angular_velocity].get_function_values( + Newton_system.previous_second_time_derivative, + angular_velocity_previous_second_time_rates); + + // mesh motion + mesh_motion_fe_values[displacements].get_function_gradients( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_gradient_increments); + + mesh_motion_fe_values[displacements].get_function_gradients( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_gradient_increments); + + // temperature + fe_therm_values[temperature].get_function_values ( + thermal_Newton_system.previous_deformation, + current_temperature_values); + fe_therm_values[temperature].get_function_values ( + thermal_Newton_system.current_increment, + updated_temperature_increments); + + // get vectors for projection onto mixed fe values + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + const point_index_t quadrature_point_index = cell->user_index() + q_point; + updated_temperature_values.at(q_point) = + current_temperature_values.at(q_point) + + updated_temperature_increments.at(q_point); + + const auto current_F = get_deformation_gradient( + current_displacement_gradients[q_point], + current_displacement_values[q_point][0]/fe_values.quadrature_point(q_point)[0] + ); + const Number material_Jacobian = material.get_material_Jacobian(quadrature_point_index) / determinant(current_F); + + const auto mesh_motion_gradient = get_deformation_gradient( + -mesh_motion_gradient_increments[q_point], + -mesh_motion_value_increments[q_point][0]/fe_values.quadrature_point(q_point)[0]); + + const Tensor<2, dim+1, Number> updated_F = get_deformation_gradient( + current_displacement_gradients[q_point] + displacement_gradient_increments[q_point], + (current_displacement_values[q_point][0] + displacement_value_increments[q_point][0]) + /fe_values.quadrature_point(q_point)[0] + ); + + + const Number Jacobian = material_Jacobian * determinant(updated_F); + deformation_jacobians.at(q_point) = Jacobian; + previous_deformation_jacobian.at(q_point) = material_Jacobian * determinant(current_F); + + const auto inv_updated_F = invert(updated_F); + std::vector> rate_gradients(dofs_per_cell); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + rate_gradients[i] = postprocess_tensor_dimension( + fe_values[displacements].gradient(i, q_point), + fe_values[displacements].value(i, q_point)[0]/fe_values.quadrature_point(q_point)[0]) * inv_updated_F; + } + + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + const Number strain_divergence_i = trace(rate_gradients[i]); + strain_divergences[i].at(q_point) = Jacobian * strain_divergence_i; + if (fill_system_matrix) { + jacobian_tangents[i].at(q_point) = Jacobian * strain_divergence_i; + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + strain_divergence_tangents[i][j].at(q_point) = + Jacobian + * (trace(rate_gradients[i]) * trace(rate_gradients[j]) + - trace(rate_gradients[i] * rate_gradients[j])); + } + } + } + } + + const unsigned int cell_index = cell->user_index() / n_q_points; + + mixed_fe_projector[cell_index].project( + &projected_temperature_coefficients, + updated_temperature_values); + mixed_fe_projector[cell_index].project( + &projected_Jacobian_coefficients, + deformation_jacobians); + mixed_fe_projector[cell_index].project( + &projected_previous_Jacobian_coefficients, + previous_deformation_jacobian); + mixed_fe_projector[cell_index].project( + &projected_previous_temperature_coefficients, + current_temperature_values); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + mixed_fe_projector[cell_index].project( + &projected_strain_divergence_coefficients[i], + strain_divergences[i]); + if (fill_system_matrix) { + mixed_fe_projector[cell_index].project( + &projected_jacobian_tangent_coefficients[i], + jacobian_tangents[i]); + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + mixed_fe_projector[cell_index].project( + &projected_strain_divergence_tangent_coefficients[i][j], + strain_divergence_tangents[i][j]); + } + } + } + + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + ConstitutiveModelUpdateFlags materialUpdateFlags = + (update_pressure | update_stress_deviator); + + if (fill_system_matrix) { + materialUpdateFlags |= + (update_pressure_tangent | update_stress_deviator_tangent); + } + + ConstitutiveModelRequest previous_constitutive_request(materialUpdateFlags); + + if (update_material_state) { + materialUpdateFlags |= update_material_point_history; + } + + const point_index_t quadrature_point_index = cell->user_index() + q_point; + ConstitutiveModelRequest constitutive_request(materialUpdateFlags); + + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + mixed_values(i) = mixed_fe_values.shape_value(i, q_point); + } + + const Number radius = fe_values.quadrature_point(q_point)[0]; + const auto current_F = get_deformation_gradient( + current_displacement_gradients[q_point], + current_displacement_values[q_point][0]/radius + ); + + const auto mesh_motion_gradient = get_deformation_gradient( + -mesh_motion_gradient_increments[q_point], + -mesh_motion_value_increments[q_point][0]/radius); + + const Tensor<2, dim+1, Number> updated_F = get_deformation_gradient( + current_displacement_gradients[q_point] + displacement_gradient_increments[q_point], + (current_displacement_values[q_point][0] + displacement_value_increments[q_point][0])/radius); + + const Number material_Jacobian = material.get_material_Jacobian(quadrature_point_index) / determinant(current_F); + const Number mesh_motion_Jacobian = determinant(mesh_motion_gradient); + + const auto inv_updated_F = invert(updated_F); + const Number Jacobian = determinant(updated_F) * material_Jacobian; + const Number previous_Jacobian = determinant(current_F) * material_Jacobian; + + + const Number DENSITY = 8.96e-9; + + const Tensor<1, dim+1, Number> displacement_increment = postprocess_tensor_dimension(displacement_increments[q_point]); + const Tensor<1, dim+1, Number> displacement_previous_time_rate = postprocess_tensor_dimension(displacement_previous_time_rates[q_point]); + const Tensor<1, dim+1, Number> displacement_previous_second_time_rate = postprocess_tensor_dimension(displacement_previous_second_time_rates[q_point]); + const Tensor<2, dim+1, Number> displacement_gradient_previous_time_rate = postprocess_tensor_dimension( + displacement_gradient_previous_time_rates[q_point], displacement_previous_time_rates[q_point][0]/radius); + const Tensor<2, dim+1, Number> displacement_gradient_previous_second_time_rate = postprocess_tensor_dimension( + displacement_gradient_previous_second_time_rates[q_point], displacement_previous_second_time_rates[q_point][0]/radius); + + const Tensor<1, dim+1, Number> uc_increment = scalar_to_angular_tensor(angular_velocity_increments[q_point]); + const Tensor<1, dim+1, Number> vc_n = scalar_to_angular_tensor(angular_velocity_previous_time_rates[q_point]); + const Tensor<1, dim+1, Number> d_vc_d_t_n = scalar_to_angular_tensor(angular_velocity_previous_second_time_rates[q_point]); + + const Tensor<1, dim+1, Number> d2_x_dt_2_n_plus_1 = + (1./(beta*time_increment*time_increment)) + * (displacement_increment + - time_increment * displacement_previous_time_rate + - time_increment * time_increment * (0.5-beta) * displacement_previous_second_time_rate); + + const Tensor<1, dim+1, Number> d_x_dt_n_plus_1 = + displacement_previous_time_rate + time_increment * ((1-gamma) * displacement_previous_second_time_rate + gamma * d2_x_dt_2_n_plus_1); + + const Tensor<2, dim+1, Number> Grad_d_2_x_d_t_2_n_plus_1 = + (1./(beta*time_increment*time_increment)) + * (postprocess_tensor_dimension( + displacement_gradient_increments[q_point], + displacement_value_increments[q_point][0]/radius) + - time_increment * displacement_gradient_previous_time_rate + - time_increment * time_increment * (0.5-beta) * displacement_gradient_previous_second_time_rate); + + const Tensor<2, dim+1, Number> Grad_d_x_d_t_n_plus_1 = + displacement_gradient_previous_time_rate + + time_increment * ( + (1.-gamma) * displacement_gradient_previous_second_time_rate + + gamma * Grad_d_2_x_d_t_2_n_plus_1); + + const Tensor<1, dim+1, Number> d_vc_d_t_n_plus_1 = + (1./(beta*time_increment*time_increment)) + * (uc_increment + - time_increment * vc_n + - time_increment * time_increment * (0.5-beta) * d_vc_d_t_n); + + const Tensor<1, dim+1, Number> vc_n_plus_1 = + vc_n + time_increment * ((1-gamma) * d_vc_d_t_n + gamma * d_vc_d_t_n_plus_1); + + const Number thR_increment = angular_velocity_increments[q_point]; + const Number d_thR_d_t_n = angular_velocity_previous_time_rates[q_point]; + const Number d2_thR_d_t2_n = angular_velocity_previous_second_time_rates[q_point]; + + const Number d2_thR_d_t2_n_plus_1 = + (1./(beta*time_increment*time_increment)) + * (thR_increment + - time_increment * d_thR_d_t_n + - time_increment * time_increment * (0.5-beta) * d2_thR_d_t2_n); + + const Number d_thR_d_t_n_plus_1 = + d_thR_d_t_n + time_increment * ((1-gamma) * d2_thR_d_t2_n + gamma * d2_thR_d_t2_n_plus_1); + + const Number one_plus_r_over_R_n = 1.0 + current_displacement_values[q_point][0]/radius; + const Number one_plus_r_over_R_n_plus_1 = 1.0 + (current_displacement_values[q_point][0] + displacement_value_increments[q_point][0])/radius; + const Number d_r_d_t_n_over_R = displacement_previous_time_rate[0] / radius; + const Number d_r_d_t_n_plus_one_over_R = d_x_dt_n_plus_1[0] / radius; + + Tensor<1, dim+1, Number> e_hat_R; + e_hat_R[0] = 1; + + const Tensor<1, dim+1, Number> acceleration_n_plus_1 = + d2_x_dt_2_n_plus_1 + + scalar_to_angular_tensor( + d_r_d_t_n_plus_one_over_R * d_thR_d_t_n_plus_1 + + one_plus_r_over_R_n_plus_1 * d2_thR_d_t2_n_plus_1) + - (1.0/radius) * one_plus_r_over_R_n_plus_1 * std::pow(d_thR_d_t_n_plus_1, 2) * e_hat_R; + + const Tensor<1, dim+1, Number> acceleration_n = + displacement_previous_second_time_rate + + scalar_to_angular_tensor( + d_r_d_t_n_over_R * d_thR_d_t_n + + one_plus_r_over_R_n * d2_thR_d_t2_n) + - (1.0/radius) * one_plus_r_over_R_n * std::pow(d_thR_d_t_n, 2) * e_hat_R; + + const Tensor<1, dim+1, Number> acceleration_n_plus_1_minus_alpha_m = + alpha_m * acceleration_n + (1-alpha_m) * acceleration_n_plus_1; + + Tensor<2, dim+1, Number> acceleration_n_plus_1_minus_alpha_m_tangent_modulus; + for(unsigned int i=0; i> rate_gradients(dofs_per_cell); + std::vector> angular_rate_gradients(dofs_per_cell); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + rate_gradients[i] = + postprocess_tensor_dimension( + fe_values[displacements].gradient(i, q_point), + fe_values[displacements].value(i, q_point)[0]/radius) * inv_updated_F; + angular_rate_gradients[i] = + order_1_tensor_to_angular_gradient( + fe_values[angular_velocity].gradient(i, q_point), + -fe_values[angular_velocity].value(i, q_point)/radius); + } + + const Tensor<2, dim+1, Number> d_X_prime_d_X = deformation_gradient_from_angular_displacement_gradient( + -angular_velocity_increments[q_point], + -angular_velocity_gradient_increments[q_point], + radius + ); + + const Tensor<2, dim+1, Number> rotation_to_X_prime_frame = rotation_tensor_to_transform_B_e( + -angular_velocity_increments[q_point], + radius + ); + + const Tensor<2, dim+1, Number> inv_d_X_prime_d_X = invert(d_X_prime_d_X); + + const auto f_m_n_plus_1 = inv_d_X_prime_d_X * rotation_to_X_prime_frame; + + // std::cout << "f_r: " << inv_d_X_prime_d_X << std::endl; + // std::cout << "R: " << previous_elastic_deformation_transformation_tensor << std::endl; + // std::cout << "f_m_n+1: " << f_m_n_plus_1 << std::endl; + + Number projected_jacobian = 0; + Number projected_previous_jacobian = 0; + Number projected_temperature = 0; + Number projected_previous_temperature = 0; + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + projected_jacobian += + mixed_values(i) * projected_Jacobian_coefficients.at(i); + projected_previous_jacobian += + mixed_values(i) * projected_previous_Jacobian_coefficients.at(i); + projected_temperature += + mixed_values(i) * projected_temperature_coefficients.at(i); + projected_previous_temperature += + mixed_values(i) * projected_previous_temperature_coefficients.at(i); + } + + const auto unnormalized_deformation_gradient_increment = updated_F * f_m_n_plus_1 * invert(current_F); + + const auto deformation_gradient_increment = + std::pow(determinant(unnormalized_deformation_gradient_increment), + -Constants::one_third()) * unnormalized_deformation_gradient_increment; + + if(std::abs(determinant(deformation_gradient_increment)-1.0) > 1e-8) + std::cout << "determinant(deformation_gradient_increment): " << determinant(deformation_gradient_increment) << std::endl; + + if(false && std::isnan(deformation_gradient_increment.norm())) { + std::cout << "deformation_gradient_increment is nan: " << deformation_gradient_increment << std::endl; + std::cout << "Jacobian: " << Jacobian + << "\nf_m_n_plus_1: " << f_m_n_plus_1 + << "\ndet(f_m_n_plus_1): " << determinant(f_m_n_plus_1) + << "\nprevious_Jacobian: " << previous_Jacobian + << "\nupdated_F: " << updated_F + << "\ncurrent_F: " << current_F + << "\ninvert(current_F): " << invert(current_F) + << std::endl; + } + + constitutive_request.set_deformation_Jacobian(projected_jacobian); + constitutive_request.set_unprojected_deformation_Jacobian(determinant(updated_F) * material_Jacobian); + constitutive_request.set_temperature(projected_temperature); + constitutive_request.set_deformation_gradient(deformation_gradient_increment); + constitutive_request.set_time_increment(time_increment); + + try { + material.compute_constitutive_request(constitutive_request, + quadrature_point_index); + } catch (const MaterialDomainException &exc) { + // std::cerr << "projected_jacobian: " << projected_jacobian + // << "\ndeformation_gradient_increment: " << deformation_gradient_increment + // << "\nupdated_F: " << updated_F + // << "\nf_m_n_plus_1: " << f_m_n_plus_1 + // << "\ncurrent_F: " << current_F + // << "\ninvert(current_F): " << invert(current_F) + // << "\nJacobian: " << Jacobian + // << "\ndeterminant(f_m_n_plus_1): " << determinant(f_m_n_plus_1) + // << "\nprevious_Jacobian: " << previous_Jacobian + // << "\n-------------------\n" + // << std::endl; + // std::cerr << exc.what() << std::endl; + kinematic_domains_are_valid = false; + continue; + } + + previous_constitutive_request.set_deformation_Jacobian(projected_previous_jacobian); + previous_constitutive_request.set_temperature(projected_previous_temperature); + previous_constitutive_request.set_deformation_gradient(unit_symmetric_tensor()); + previous_constitutive_request.set_time_increment(time_increment); + previous_constitutive_request.set_is_plastic(false); // the elastic strain is known, no need for predictor-corrector procedure + + material.compute_constitutive_request(previous_constitutive_request, + quadrature_point_index); + + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + projected_strain_divergence[j] = + mixed_values(0) * projected_strain_divergence_coefficients[j][0]; + if (fill_system_matrix) { + projected_jacobian_tangent[j] = + mixed_values(0) * projected_jacobian_tangent_coefficients[j][0]; + for (unsigned int k = 0; k < dofs_per_cell; ++k) { + projected_strain_divergence_tangent[j][k] = + mixed_values(0) + * projected_strain_divergence_tangent_coefficients[j][k][0]; + } + } + } + + for (unsigned int i = 1; i < mixed_dofs_per_cell; ++i) { + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + projected_strain_divergence[j] += + mixed_values(i) * projected_strain_divergence_coefficients[j][i]; + if (fill_system_matrix) { + projected_jacobian_tangent[j] += + mixed_values(i) * projected_jacobian_tangent_coefficients[j][i]; + for (unsigned int k = 0; k < dofs_per_cell; ++k) { + projected_strain_divergence_tangent[j][k] += + mixed_values(i) + * projected_strain_divergence_tangent_coefficients[j][k][i]; + } + } + } + } + + const Number RJxW = radius / material_Jacobian * fe_values.JxW(q_point); + + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + const auto strain_i = symmetrize(rate_gradients[i] + angular_rate_gradients[i] * inv_updated_F); + + // stress deviator term + const SymmetricTensor<2, dim+1, Number> stress_deviator = + alpha_f * previous_constitutive_request.get_stress_deviator() + + (1-alpha_f) * constitutive_request.get_stress_deviator(); + const Number pressure = + alpha_f * previous_constitutive_request.get_pressure() + + (1-alpha_f) * constitutive_request.get_pressure(); + cell_residual(i) += strain_i * stress_deviator * RJxW; + + // pressure term + cell_residual(i) += + (projected_strain_divergence.at(i)) * pressure * RJxW; + + // body force term + const unsigned int + component_i = mech_fe.system_to_component_index(i).first; + for ( typename std::vector >::const_iterator + bodyForceApplier = mechanical_lbc_system.bodyLoadAppliers.begin(); + bodyForceApplier != mechanical_lbc_system.bodyLoadAppliers.end(); + ++bodyForceApplier) { + cell_residual(i) += + bodyForceApplier->apply( + component_i, + fe_values.shape_value (i, q_point), + RJxW); + } + + // inertial term + cell_residual(i) += + (postprocess_tensor_dimension(fe_values[displacements].value(i, q_point)) + scalar_to_angular_tensor(fe_values[angular_velocity].value(i, q_point))) + * DENSITY + * acceleration_n_plus_1_minus_alpha_m * RJxW; + } + + if (fill_system_matrix) { + std::vector > stress_deviator_tangents(dofs_per_cell); + std::vector pressure_tangents(dofs_per_cell); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + + const Tensor<2, dim+1, Number> d_X_prime_d_X_variation = + deformation_gradient_from_angular_displacement_gradient_variations( + -angular_velocity_increments[q_point], + -angular_velocity_gradient_increments[q_point], + radius, + -fe_values[angular_velocity].value(i, q_point), + -fe_values[angular_velocity].gradient(i, q_point) + ); + + const Tensor<2, dim+1, Number> rotation_to_X_prime_frame_variation = rotation_tensor_variation_to_transform_B_e( + -angular_velocity_increments[q_point], + -fe_values[angular_velocity].value(i, q_point), + radius + ); + + const auto f_m_n_plus_1_variation_inv_f_m_n_plus_1 = + (- inv_d_X_prime_d_X * d_X_prime_d_X_variation * inv_d_X_prime_d_X * rotation_to_X_prime_frame + + inv_d_X_prime_d_X * rotation_to_X_prime_frame_variation) * invert(f_m_n_plus_1); + + stress_deviator_tangents[i] = (1-alpha_f) * constitutive_request.get_stress_deviator_tangent( + rate_gradients[i] + - Constants::one_third() + * trace(rate_gradients[i]) + * unit_symmetric_tensor() + + updated_F * f_m_n_plus_1_variation_inv_f_m_n_plus_1 * inv_updated_F + - Constants::one_third() + * trace(f_m_n_plus_1_variation_inv_f_m_n_plus_1) + * unit_symmetric_tensor()); + + pressure_tangents[i] = (1-alpha_f) * constitutive_request.get_pressure_tangent( + projected_jacobian_tangent[i]); + } + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + // stress tangent + const Number f_int_dev_tau = symmetrize(rate_gradients[i] + angular_rate_gradients[i] * inv_updated_F) * stress_deviator_tangents[j]; + cell_matrix(i, j) += (f_int_dev_tau) * RJxW; + // pressure_tangent + const Number f_int_pressure = + projected_strain_divergence.at(i) + * pressure_tangents[j]; + cell_matrix(i, j) += (f_int_pressure) * RJxW; + // geometric_tangent + const Tensor<2, dim+1, Number> grad_ui_grad_uj = (rate_gradients[i] + angular_rate_gradients[i] * inv_updated_F) * rate_gradients[j]; + const SymmetricTensor<2, dim+1, Number> sym_grad_ui_grad_uj = symmetrize(grad_ui_grad_uj); + const Number f_int_geom = + projected_strain_divergence_tangent[i][j] + * constitutive_request.get_pressure() + - sym_grad_ui_grad_uj + * constitutive_request.get_stress_deviator(); + cell_matrix(i, j) += (f_int_geom) * RJxW; + + // inertial tangent + cell_matrix(i, j) += + (postprocess_tensor_dimension(fe_values[displacements].value(i, q_point)) + + scalar_to_angular_tensor(fe_values[angular_velocity].value(i, q_point))) + * DENSITY + * (acceleration_n_plus_1_minus_alpha_m_tangent_modulus + * (postprocess_tensor_dimension(fe_values[displacements].value(j, q_point)) + + scalar_to_angular_tensor(fe_values[angular_velocity].value(j, q_point)))) + * RJxW; + } + } + } + } + + for (unsigned int face = 0; face < GeometryInfo::faces_per_cell; ++face) { + for (auto boundaryForceSpec: mechanical_lbc_system.boundaryLoadAppliers) { + if (cell->face(face)->boundary_id() == boundaryForceSpec.first) { + fe_face_values.reinit(cell, face); + for (unsigned int q_point = 0; q_point < n_face_q_points; ++q_point) { + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + const unsigned int component_i = mech_fe.system_to_component_index(i).first; + cell_residual(i) += + boundaryForceSpec.second.apply( + component_i, + fe_face_values.shape_value(i, q_point), + fe_face_values.quadrature_point(q_point)[0] * fe_face_values.JxW(q_point)); + } + } + } + } + + for(const auto boundary_unidirectional_penalty_spec: mechanical_lbc_system.boundary_unidirectional_penalty_specs) { + if (cell->face(face)->boundary_id() == boundary_unidirectional_penalty_spec->get_boundary_id()) { + const Number reference_displacement_increment = boundary_unidirectional_penalty_spec->get_reference_displacement_increment(); + const Number residual_force = boundary_unidirectional_penalty_spec->get_residual_force(); + const Number quadratic_spring_factor = boundary_unidirectional_penalty_spec->get_quadratic_spring_factor(); + + fe_face_values.reinit(cell, face); + fe_face_values[displacements].get_function_values( + Newton_system.current_increment, + face_displacement_value_increments); + for (unsigned int q_point = 0; q_point < n_face_q_points; ++q_point) { + const Tensor<1, dim, Number> surface_normal = fe_face_values.normal_vector(q_point); + const Number surface_displacement = face_displacement_value_increments[q_point] * surface_normal; + const Number surface_force = + -residual_force + + surface_displacement < -reference_displacement_increment? + 0 : + -0.5 * quadratic_spring_factor * std::pow(surface_displacement + reference_displacement_increment, 2); + const Number surface_force_tangent_modulus = + surface_displacement < -reference_displacement_increment? + 0 : + -quadratic_spring_factor * (surface_displacement + reference_displacement_increment); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + cell_residual(i) -= + fe_face_values[displacements].value(i, q_point) + * surface_force * surface_normal + * fe_face_values.quadrature_point(q_point)[0] * fe_face_values.JxW(q_point); + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + cell_matrix(i, j) -= + fe_face_values[displacements].value(i, q_point) + * surface_force_tangent_modulus * (fe_face_values[displacements].value(j, q_point) * surface_normal) * surface_normal + * fe_face_values.quadrature_point(q_point)[0] * fe_face_values.JxW(q_point); + } + } + } + } + } + } + + // const Number relative_symmetry_norm2 = cell_matrix.relative_symmetry_norm2(); + // if(relative_symmetry_norm2 > 1e-8) + // std::cout << "relative_symmetry_norm2: " << cell_matrix.relative_symmetry_norm2() << std::endl; + + std::vector local_dof_indices (dofs_per_cell); + cell->get_dof_indices (local_dof_indices); + if (fill_system_matrix) { + mechanical_dof_system.nodal_constraints.distribute_local_to_global( + cell_matrix, + cell_residual, + local_dof_indices, + Newton_system.Newton_step_matrix, + Newton_system.Newton_step_residual, + true); + } else { + mechanical_dof_system.nodal_constraints.distribute_local_to_global( + cell_residual, local_dof_indices, + Newton_system.Newton_step_residual); + } + } /* if cell is locally owned */ + } /*for (; cell!=endc; ++cell)*/ + + const unsigned short local_domain_is_valid = kinematic_domains_are_valid ? 1 : 0; + unsigned short all_kinematic_domains_are_valid; + + // did any of the processes fail to assemble? + MPI_Allreduce( + &local_domain_is_valid, + &all_kinematic_domains_are_valid, 1, MPI_UNSIGNED_SHORT, + MPI_MIN, mpi_communicator); + + if (all_kinematic_domains_are_valid < 1) { + throw std::runtime_error("The domain is not valid..."); + } + + if (fill_system_matrix) { + Newton_system.Newton_step_matrix.compress(VectorOperation::add); + } + Newton_system.Newton_step_residual.compress(VectorOperation::add); + + } /*PlasticityLabProg::assemble_mechanical_system()*/ + + + template + void PlasticityLabProg::assemble_thermal_system( + NewtonStepSystem &Newton_system, + NewtonStepSystem &mechanical_nonlinear_system, + const DoFSystem &thermal_dof_system, + const LBCSystem &thermal_lbc_system, + const DoFSystem &mechanical_dof_system, + const DoFSystem &mixed_fe_dof_system, + Material &material, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const std::unordered_map> &material_area_factors, + const bool fill_system_matrix) { + + FEValues fe_values( + mapping, + therm_fe, + quadrature_formula, + update_values | update_quadrature_points | update_gradients | update_JxW_values); + + FEFaceValues fe_face_values( + mapping, + therm_fe, + face_quadrature_formula, + update_values + | update_quadrature_points + | update_JxW_values); + + FEValues fe_mech_values( + mapping, + mech_fe, + quadrature_formula, + update_values | update_quadrature_points | update_gradients); + + FEFaceValues mech_fe_face_values( + mapping, + mech_fe, + face_quadrature_formula, + update_values + | update_gradients + | update_quadrature_points + | update_normal_vectors + | update_JxW_values); + + FEValues mixed_fe_values( + mapping, + mixed_var_fe, + quadrature_formula, + update_values); + + const unsigned int dofs_per_cell = therm_fe.dofs_per_cell; + const unsigned int n_q_points = quadrature_formula.size(); + const unsigned int n_face_q_points = face_quadrature_formula.size(); + const unsigned int mixed_dofs_per_cell = mixed_var_fe.dofs_per_cell; + + FullMatrix cell_matrix (dofs_per_cell, dofs_per_cell); + Vector cell_residual (dofs_per_cell); + + Vector mixed_values (mixed_dofs_per_cell); + std::vector weighted_updated_J_vec(mixed_dofs_per_cell), + weighted_current_J_vec(mixed_dofs_per_cell), + weighted_previous_J_vec(mixed_dofs_per_cell), + weighted_updated_theta_vec(mixed_dofs_per_cell), + weighted_previous_theta_vec(mixed_dofs_per_cell), + weighted_J_time_rate_vec(mixed_dofs_per_cell); + std::vector< std::vector > weighted_shape_values( + dofs_per_cell, + std::vector(mixed_dofs_per_cell) ); + + std::vector qp_updated_J_values(n_q_points), + qp_previous_J_values(n_q_points), + qp_updated_theta_values(n_q_points), + qp_previous_theta_values(n_q_points), + qp_J_time_rates(n_q_points); + std::vector > qp_shape_values( + dofs_per_cell, + std::vector(n_q_points)); + + std::vector< Tensor<1, dim, Number> > thermal_gradient_increment(n_q_points), + current_thermal_gradient(n_q_points); + + std::vector< Number > current_temperature_values(n_q_points), + temperature_values_increment(n_q_points); + + std::vector< Number > current_face_temperature_values(n_face_q_points), + face_temperature_values_increment(n_face_q_points); + + std::vector< Tensor<2, dim, Number> > current_displacement_gradients(n_q_points), + displacement_gradient_increments(n_q_points); + std::vector< Tensor<1, dim, Number> > current_displacement_values(n_q_points), + displacement_value_increments(n_q_points); + + std::vector< Tensor<1, dim, Number> > current_angular_velocity_gradients(n_q_points), + angular_velocity_gradient_increments(n_q_points), + angular_velocity_gradient_previous_time_rates(n_q_points); + + std::vector< Number > angular_velocity_increments(n_q_points), + current_angular_velocities(n_q_points), + angular_velocity_previous_time_rates(n_q_points); + + std::vector< Tensor<2, dim, Number> > current_face_displacement_gradients(n_face_q_points); + std::vector< Tensor<2, dim, Number> > face_displacement_gradient_increments(n_face_q_points); + + std::vector< Tensor<1, dim, Number> > current_face_displacement_values(n_face_q_points); + std::vector< Tensor<1, dim, Number> > face_displacement_value_increments(n_face_q_points); + + const FEValuesExtractors::Scalar temperature (0); + const FEValuesExtractors::Vector displacements (0); + const FEValuesExtractors::Scalar angular_velocity(dim); + Newton_system.Newton_step_matrix = 0; + Newton_system.Newton_step_residual = 0; + Newton_system.Newton_step_matrix.compress(VectorOperation::insert); + Newton_system.Newton_step_residual.compress(VectorOperation::insert); + + auto cell = thermal_dof_system.dof_handler.begin_active(); + auto endc = thermal_dof_system.dof_handler.end(); + auto mechanical_cell = mechanical_dof_system.dof_handler.begin_active(); + auto mixed_fe_cell = mixed_fe_dof_system.dof_handler.begin_active(); + for (; cell != endc; ++cell, ++mechanical_cell, ++mixed_fe_cell) { + if (cell->is_locally_owned()) { + cell_matrix = 0; + cell_residual = 0; + + fe_values.reinit (cell); + fe_mech_values.reinit (mechanical_cell); + mixed_fe_values.reinit (mixed_fe_cell); + + fe_values[temperature].get_function_gradients( + Newton_system.current_increment, + thermal_gradient_increment); + + fe_values[temperature].get_function_gradients( + Newton_system.previous_deformation, + current_thermal_gradient); + + fe_values[temperature].get_function_values( + Newton_system.current_increment, + temperature_values_increment); + + fe_values[temperature].get_function_values( + Newton_system.previous_deformation, + current_temperature_values); + + fe_mech_values[displacements].get_function_gradients( + mechanical_nonlinear_system.current_increment, + displacement_gradient_increments); + + fe_mech_values[displacements].get_function_gradients( + mechanical_nonlinear_system.previous_deformation, + current_displacement_gradients); + + fe_mech_values[displacements].get_function_values( + mechanical_nonlinear_system.current_increment, + displacement_value_increments); + + fe_mech_values[displacements].get_function_values( + mechanical_nonlinear_system.previous_deformation, + current_displacement_values); + + // Angular velocity + fe_mech_values[angular_velocity].get_function_gradients( + mechanical_nonlinear_system.current_increment, + angular_velocity_gradient_increments); + + fe_mech_values[angular_velocity].get_function_values( + mechanical_nonlinear_system.current_increment, + angular_velocity_increments); + + // get vectors for projection onto mixed fe values + for (unsigned int q_point = 0; q_point < n_q_points; + ++q_point) { + + const Number radius = fe_mech_values.quadrature_point(q_point)[0]; + + const auto previous_F = get_deformation_gradient( + current_displacement_gradients[q_point], + current_displacement_values[q_point][0]/radius); + + const auto updated_F = get_deformation_gradient( + current_displacement_gradients[q_point] + displacement_gradient_increments[q_point], + (current_displacement_values[q_point][0] + displacement_value_increments[q_point][0])/radius); + + const auto deformation_gradient_increment = postprocess_tensor_dimension( + displacement_gradient_increments[q_point], + displacement_value_increments[q_point][0]/radius); + + const point_index_t quadrature_point_index = cell->user_index() + q_point; + const Number material_Jacobian = material.get_material_Jacobian(quadrature_point_index) / determinant(previous_F); + + const Number Jacobian = material_Jacobian * determinant(updated_F); + const Number previous_Jacobian = material_Jacobian * determinant(previous_F); + + qp_previous_J_values.at(q_point) = previous_Jacobian; + qp_updated_J_values.at(q_point) = Jacobian; + qp_J_time_rates.at(q_point) = Jacobian * trace(deformation_gradient_increment * invert(updated_F)) / time_increment; + + qp_previous_theta_values.at(q_point) = current_temperature_values.at(q_point); + qp_updated_theta_values.at(q_point) = current_temperature_values.at(q_point) + temperature_values_increment.at(q_point); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + qp_shape_values.at(i).at(q_point) = fe_values[temperature].value(i, q_point); + } + } + + const unsigned int cell_index = cell->user_index() / n_q_points; + + mixed_fe_projector[cell_index].project( + &weighted_updated_J_vec, + qp_updated_J_values); + mixed_fe_projector[cell_index].project( + &weighted_J_time_rate_vec, + qp_J_time_rates); + mixed_fe_projector[cell_index].project( + &weighted_updated_theta_vec, + qp_updated_theta_values); + mixed_fe_projector[cell_index].project( + &weighted_previous_J_vec, + qp_previous_J_values); + mixed_fe_projector[cell_index].project( + &weighted_previous_theta_vec, + qp_previous_theta_values); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + mixed_fe_projector[cell_index].project( + &weighted_shape_values.at(i), + qp_shape_values.at(i)); + } + + for (unsigned int q_point = 0; q_point < n_q_points; + ++q_point) { + const ConstitutiveModelUpdateFlags material_update_flags = + fill_system_matrix ? + (update_heat_flux | update_heat_flux_tangent + | update_mechanical_dissipation + | update_mechanical_dissipation_tangent + | update_stored_heat | update_stored_heat_tangent) + : + (update_heat_flux | update_mechanical_dissipation + | update_stored_heat); + + const ConstitutiveModelUpdateFlags heating_update_flags = + fill_system_matrix ? + (update_thermoelastic_heating + | update_thermoelastic_heating_tangent) + : + (update_thermoelastic_heating); + + point_index_t quadrature_point_index = cell->user_index() + q_point; + ConstitutiveModelRequest constitutive_request(material_update_flags); + ConstitutiveModelRequest heating_request(heating_update_flags); + + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + mixed_values(i) = mixed_fe_values.shape_value(i, q_point); + } + + Number projected_updated_J = 0; + Number projected_previous_J = 0; + Number projected_updated_theta = 0; + Number projected_previous_theta = 0; + Number projected_J_time_rate = 0; + Vector projected_shape_values(dofs_per_cell); + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + projected_updated_J += + mixed_values(i) * weighted_updated_J_vec.at(i); + projected_J_time_rate += + mixed_values(i) * weighted_J_time_rate_vec.at(i); + projected_updated_theta += + mixed_values(i) * weighted_updated_theta_vec.at(i); + projected_previous_J += + mixed_values(i) * weighted_previous_J_vec.at(i); + projected_previous_theta += + mixed_values(i) * weighted_previous_theta_vec.at(i); + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + projected_shape_values(j) += + mixed_values(i) * weighted_shape_values.at(j).at(i); + } + } + + const Number d_theta_dt_n_plus_1 = temperature_values_increment[q_point] / time_increment; + + const Number d_theta_dt_tangent = 1.0 / time_increment; + + heating_request.set_deformation_Jacobian(projected_updated_J); + heating_request.set_deformation_Jacobian_time_rate(projected_J_time_rate); + heating_request.set_temperature(projected_updated_theta); + heating_request.set_previous_deformation_Jacobian(projected_previous_J); + heating_request.set_previous_temperature(projected_previous_theta); + heating_request.set_time_increment(time_increment); + + const auto current_F = get_deformation_gradient( + current_displacement_gradients[q_point], + current_displacement_values[q_point][0]/fe_mech_values.quadrature_point(q_point)[0] + ); + const auto updated_F = get_deformation_gradient( + current_displacement_gradients[q_point] + + displacement_gradient_increments[q_point], + (current_displacement_values[q_point][0] + + displacement_value_increments[q_point][0])/fe_mech_values.quadrature_point(q_point)[0]); + + const auto inv_updated_F = invert(updated_F); + const Number material_Jacobian = material.get_material_Jacobian(quadrature_point_index) / determinant(current_F); + const Number previous_Jacobian = determinant(current_F) * material_Jacobian; + const Number Jacobian = determinant(updated_F) * material_Jacobian; + + const Number radius = fe_values.quadrature_point(q_point)[0]; + + const Tensor<2, dim+1, Number> d_X_prime_d_X = deformation_gradient_from_angular_displacement_gradient( + -angular_velocity_increments[q_point], + -angular_velocity_gradient_increments[q_point], + radius + ); + + const Tensor<2, dim+1, Number> rotation_to_X_prime_frame = rotation_tensor_to_transform_B_e( + -angular_velocity_increments[q_point], + radius + ); + + const Tensor<2, dim+1, Number> inv_d_X_prime_d_X = invert(d_X_prime_d_X); + + const auto f_m_n_plus_1 = inv_d_X_prime_d_X * rotation_to_X_prime_frame; + + // std::cout << "f_r: " << inv_d_X_prime_d_X << std::endl; + // std::cout << "R: " << previous_elastic_deformation_transformation_tensor << std::endl; + // std::cout << "f_m_n+1: " << f_m_n_plus_1 << std::endl; + + const auto unnormalized_deformation_gradient_increment = updated_F * f_m_n_plus_1 * invert(current_F); + + const auto deformation_gradient_increment = + std::pow(determinant(unnormalized_deformation_gradient_increment), + -Constants::one_third()) * unnormalized_deformation_gradient_increment; + + const Number previous_temperature = current_temperature_values[q_point]; + const Number updated_temperature = previous_temperature + temperature_values_increment[q_point]; + const auto thermal_gradient = + postprocess_tensor_dimension(current_thermal_gradient[q_point] + thermal_gradient_increment[q_point]) * inv_updated_F; + + constitutive_request.set_deformation_gradient(deformation_gradient_increment); + constitutive_request.set_temperature_time_rate(d_theta_dt_n_plus_1); + constitutive_request.set_temperature(updated_temperature); + constitutive_request.set_thermal_gradient(thermal_gradient); + constitutive_request.set_time_increment(time_increment); + + material.compute_constitutive_request( + constitutive_request, + quadrature_point_index); + material.compute_constitutive_request( + heating_request, + quadrature_point_index); + + std::vector> rate_gradients(dofs_per_cell); + std::vector rate_temperatures(dofs_per_cell); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + rate_gradients[i] = postprocess_tensor_dimension(fe_values[temperature].gradient(i, q_point)) * inv_updated_F; + rate_temperatures[i] =fe_values[temperature].value(i, q_point); + } + + const Number RJxW = fe_values.quadrature_point(q_point)[0] / material_Jacobian * fe_values.JxW(q_point); + + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + + // heat flux term + const auto heat_flux = constitutive_request.get_heat_flux(); + cell_residual(i) += rate_gradients[i] + * heat_flux + * RJxW; + + // stored heat term + cell_residual(i) += rate_temperatures[i] + * constitutive_request.get_stored_heat_rate() + * RJxW; + + // mechanical dissipation term + cell_residual(i) -= rate_temperatures[i] + * constitutive_request.get_mechanical_dissipation() + * RJxW; + + // elastoplastic heating term + cell_residual(i) += (projected_shape_values(i)) + * heating_request.get_thermo_elastic_heating() + * RJxW; + + for ( typename std::vector >::const_iterator + bodyHeatSourceApplier = thermal_lbc_system.bodyLoadAppliers.cbegin(); + bodyHeatSourceApplier != thermal_lbc_system.bodyLoadAppliers.cend(); + ++bodyHeatSourceApplier) { + cell_residual(i) += bodyHeatSourceApplier->apply( + 0, rate_temperatures[i], + fe_values.quadrature_point(q_point)[0] * fe_values.JxW(q_point)); + } + } + + if (fill_system_matrix) { + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + + // heat flux tangent + const Number f_int_q = + rate_gradients[i] + * constitutive_request.get_heat_flux_tangent(rate_gradients[j]); + cell_matrix(i, j) += f_int_q * RJxW; + + // stored heat rate tangent + const Number f_int_cThetaDot = + rate_temperatures[i] + * constitutive_request.get_stored_heat_rate_tangent(d_theta_dt_tangent*rate_temperatures[j]); + cell_matrix(i, j) += f_int_cThetaDot * RJxW; + + // mechanical dissipation tangent + const Number f_int_mech_dissipation = + rate_temperatures[i] + * constitutive_request.get_mechanical_dissipation_tangent(rate_temperatures[j]); + cell_matrix(i, j) -= f_int_mech_dissipation * RJxW; + + // elastoplastic heating tangent + const Number f_int_elastoplastic_heating = + (projected_shape_values(i)) + * heating_request.get_thermo_elastic_heating_tangent(projected_shape_values(j)); + cell_matrix(i, j) += f_int_elastoplastic_heating * RJxW; + } + } + } + } + + for (unsigned int face = 0; face < GeometryInfo::faces_per_cell; ++face) { + fe_face_values.reinit(cell, face); + mech_fe_face_values.reinit(mechanical_cell, face); + + fe_face_values[temperature].get_function_values( + Newton_system.previous_deformation, + current_face_temperature_values); + fe_face_values[temperature].get_function_values( + Newton_system.current_increment, + face_temperature_values_increment); + + mech_fe_face_values[displacements].get_function_gradients( + mechanical_nonlinear_system.previous_deformation, + current_face_displacement_gradients); + mech_fe_face_values[displacements].get_function_gradients( + mechanical_nonlinear_system.current_increment, + face_displacement_gradient_increments); + + mech_fe_face_values[displacements].get_function_values( + mechanical_nonlinear_system.previous_deformation, + current_face_displacement_values); + mech_fe_face_values[displacements].get_function_values( + mechanical_nonlinear_system.current_increment, + face_displacement_value_increments); + + + for ( typename std::vector > >::const_iterator + boundaryHeatSource = thermal_lbc_system.boundaryLoadAppliers.cbegin(); + boundaryHeatSource != thermal_lbc_system.boundaryLoadAppliers.cend(); + ++boundaryHeatSource) { + if (cell->face(face)->boundary_id() == boundaryHeatSource->first) { + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + for (unsigned int q_point = 0; + q_point < face_quadrature_formula.size(); + ++q_point) { + + + const auto updated_F = get_deformation_gradient( + current_face_displacement_gradients[q_point] + + face_displacement_gradient_increments[q_point], + (current_face_displacement_values[q_point][0] + + face_displacement_value_increments[q_point][0])/fe_mech_values.quadrature_point(q_point)[0]); + + + const Number J = determinant(updated_F); + const Tensor<2, dim+1, Number> inv_deformation_gradient = invert(updated_F); + const Tensor<1, dim+1, Number> reference_normal = postprocess_tensor_dimension(mech_fe_face_values.normal_vector(q_point), 0); + const Tensor<1, dim+1, Number> F_inv_transpose_N = transpose(inv_deformation_gradient) * reference_normal; + const Number norm_F_inv_transpose_N = (F_inv_transpose_N).norm(); + + cell_residual(i) += + boundaryHeatSource->second.apply( + 0, + fe_face_values.shape_value(i, q_point), + norm_F_inv_transpose_N * J * + fe_face_values.quadrature_point(q_point)[0] * fe_face_values.JxW(q_point)); + } + } + } + } + + for ( typename std::vector > >::const_iterator + convectionBC = thermal_lbc_system.convection_BC_appliers.cbegin(); + convectionBC != thermal_lbc_system.convection_BC_appliers.cend(); + ++convectionBC) { + if (cell->face(face)->boundary_id() == convectionBC->first) { + for (unsigned int q_point = 0; + q_point < face_quadrature_formula.size(); + ++q_point) { + + const unsigned int cell_index = cell->user_index() / quadrature_formula.size(); + const unsigned int surface_point_key = + cell_index * GeometryInfo::faces_per_cell * n_face_q_points + + face * n_face_q_points + + q_point; + + const auto updated_F = get_deformation_gradient( + current_face_displacement_gradients[q_point] + + face_displacement_gradient_increments[q_point], + (current_face_displacement_values[q_point][0] + + face_displacement_value_increments[q_point][0])/fe_mech_values.quadrature_point(q_point)[0]); + + const Number J = determinant(updated_F); + const Tensor<2, dim+1, Number> inv_deformation_gradient = invert(updated_F); + const Tensor<1, dim+1, Number> reference_normal = postprocess_tensor_dimension(mech_fe_face_values.normal_vector(q_point), 0); + const Tensor<1, dim+1, Number> F_inv_transpose_N = transpose(inv_deformation_gradient) * reference_normal; + const Number norm_F_inv_transpose_N = (F_inv_transpose_N).norm(); + + const Number RJxW = fe_face_values.quadrature_point(q_point)[0] / material_area_factors.at(surface_point_key).norm() * fe_face_values.JxW(q_point); + + const Number updated_face_temperature_value = + current_face_temperature_values[q_point] + + face_temperature_values_increment[q_point]; + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + cell_residual(i) += + convectionBC->second.apply( + 0, + fe_face_values.shape_value(i, q_point), + updated_face_temperature_value, + RJxW); + if (fill_system_matrix) { + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + cell_matrix(i, j) += + convectionBC->second.apply_gradient( + 0, + fe_face_values.shape_value(i, q_point), + fe_face_values.shape_value(j, q_point), + RJxW); + } + } + } + } + } + } + } + + + std::vector local_dof_indices (dofs_per_cell); + cell->get_dof_indices (local_dof_indices); + if (fill_system_matrix) { + thermal_dof_system.nodal_constraints.distribute_local_to_global( + cell_matrix, + cell_residual, + local_dof_indices, + Newton_system.Newton_step_matrix, + Newton_system.Newton_step_residual, + true); + } else { + thermal_dof_system.nodal_constraints.distribute_local_to_global( + cell_residual, local_dof_indices, + Newton_system.Newton_step_residual); + } + } /*for (; cell!=endc; ++cell) if(cell->is_locally_owned())*/ + } + + if (fill_system_matrix) Newton_system.Newton_step_matrix.compress(VectorOperation::add); + Newton_system.Newton_step_residual.compress(VectorOperation::add); + } + + template + void PlasticityLabProg::assemble_mesh_motion_system( + NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const LBCSystem &mesh_motion_lbc_system, + const NewtonStepSystem &deformation_nonlinear_system, + const DoFSystem &deformation_dof_system, + const DoFSystem &mixed_fe_dof_system, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const bool fill_system_matrix) { + + + const Number mesh_motion_mu = 1.0; + const Number mesh_motion_kappa = 5.0; + const Number cell_jacobian_exponent = -0.0; + + + FEValues deformation_fe_values( + mapping, + mech_fe, + quadrature_formula, + update_values | update_gradients); + + FEValues mesh_motion_fe_values( + mapping, + mesh_motion_fe, + quadrature_formula, + update_values | update_gradients | update_quadrature_points | + update_jacobians | update_JxW_values); + + FEValues mixed_fe_values( + mapping, + mixed_var_fe, + quadrature_formula, + update_values); + + const unsigned int dofs_per_cell = mesh_motion_fe.dofs_per_cell; + const unsigned int n_q_points = quadrature_formula.size(); + const unsigned int mixed_dofs_per_cell = mixed_var_fe.dofs_per_cell; + + std::vector< Tensor<2, dim, Number> > mesh_motion_gradient_increments(n_q_points); + std::vector< Tensor<1, dim, Number> > mesh_motion_value_increments(n_q_points); + + std::vector< Tensor<2, dim, Number> > current_deformation_gradients(n_q_points); + std::vector< Tensor<2, dim, Number> > deformation_gradient_increments(n_q_points); + + std::vector< Tensor<1, dim, Number> > current_deformation_values(n_q_points); + std::vector< Tensor<1, dim, Number> > deformation_value_increments(n_q_points); + + std::vector< Number > mesh_motion_jacobians(n_q_points); + std::vector< std::vector > strain_divergences(dofs_per_cell, std::vector(n_q_points)); + std::vector< std::vector > jacobian_tangents(dofs_per_cell, std::vector(n_q_points)); + + std::vector< std::vector< std::vector < Number> > > strain_divergence_tangents( + dofs_per_cell, + std::vector< std::vector< Number> >(dofs_per_cell,std::vector(n_q_points))); + + std::vector projected_Jacobian_coefficients(mixed_dofs_per_cell); + std::vector > projected_strain_divergence_coefficients( + dofs_per_cell, + std::vector(mixed_dofs_per_cell)); + std::vector > projected_jacobian_tangent_coefficients( + dofs_per_cell, + std::vector(mixed_dofs_per_cell)); + std::vector > > projected_strain_divergence_tangent_coefficients( + dofs_per_cell, std::vector< std::vector< Number> >( + dofs_per_cell, + std::vector(mixed_dofs_per_cell))); + + std::vector projected_strain_divergence(dofs_per_cell); + std::vector projected_jacobian_tangent(dofs_per_cell); + std::vector > projected_strain_divergence_tangent(dofs_per_cell, std::vector(dofs_per_cell)); + + FullMatrix cell_matrix(dofs_per_cell, dofs_per_cell); + Vector cell_residual(dofs_per_cell); + + Vector mixed_values (mixed_dofs_per_cell); + + const FEValuesExtractors::Vector displacements (0); + const FEValuesExtractors::Scalar angular_velocity(dim); + const FEValuesExtractors::Scalar temperature (0); + + mesh_motion_nonlinear_system.Newton_step_matrix = 0; + mesh_motion_nonlinear_system.Newton_step_residual = 0; + + bool kinematic_domains_are_valid = true; // innocent until proven guilty + + auto cell = mesh_motion_dof_system.dof_handler.begin_active(); + auto endc = mesh_motion_dof_system.dof_handler.end(); + auto deformation_cell = deformation_dof_system.dof_handler.begin_active(); + auto mixed_fe_cell = mixed_fe_dof_system.dof_handler.begin_active(); + + for (; cell != endc; ++cell, ++deformation_cell, ++mixed_fe_cell) { + if (cell->is_locally_owned()) { + + cell_matrix = 0; + cell_residual = 0; + + mesh_motion_fe_values.reinit (cell); + deformation_fe_values.reinit (deformation_cell); + mixed_fe_values.reinit (mixed_fe_cell); + + deformation_fe_values[displacements].get_function_gradients( + deformation_nonlinear_system.previous_deformation, + current_deformation_gradients); + + deformation_fe_values[displacements].get_function_gradients( + deformation_nonlinear_system.current_increment, + deformation_gradient_increments); + + deformation_fe_values[displacements].get_function_values( + deformation_nonlinear_system.previous_deformation, + current_deformation_values); + + deformation_fe_values[displacements].get_function_values( + deformation_nonlinear_system.current_increment, + deformation_value_increments); + + mesh_motion_fe_values[displacements].get_function_gradients( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_gradient_increments); + + mesh_motion_fe_values[displacements].get_function_values( + mesh_motion_nonlinear_system.current_increment, + mesh_motion_value_increments); + + // get vectors for projection onto mixed fe values + for (unsigned int q_point = 0; q_point < n_q_points; + ++q_point) { + + const auto mesh_motion_gradient = get_deformation_gradient( + -mesh_motion_gradient_increments[q_point], + -mesh_motion_value_increments[q_point][0]/mesh_motion_fe_values.quadrature_point(q_point)[0]); + + const Number Jacobian = determinant(mesh_motion_gradient); + mesh_motion_jacobians.at(q_point) = Jacobian; + + const auto inv_mesh_motion_gradient = invert(mesh_motion_gradient); + std::vector> rate_gradients(dofs_per_cell); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + rate_gradients[i] = postprocess_tensor_dimension( + -mesh_motion_fe_values[displacements].gradient(i, q_point), + -mesh_motion_fe_values[displacements].value(i, q_point)[0] + /mesh_motion_fe_values.quadrature_point(q_point)[0]) * inv_mesh_motion_gradient; + } + + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + const Number strain_divergence_i = trace(rate_gradients[i]); + strain_divergences[i].at(q_point) = Jacobian * strain_divergence_i; + if (fill_system_matrix) { + jacobian_tangents[i].at(q_point) = Jacobian * strain_divergence_i; + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + strain_divergence_tangents[i][j].at(q_point) = Jacobian * (trace(rate_gradients[i]) * trace(rate_gradients[j]) - trace(rate_gradients[i] * rate_gradients[j])); + } + } + } + } + + const unsigned int cell_index = cell->user_index() / n_q_points; + + mixed_fe_projector[cell_index].project( + &projected_Jacobian_coefficients, + mesh_motion_jacobians); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + mixed_fe_projector[cell_index].project( + &projected_strain_divergence_coefficients[i], + strain_divergences[i]); + if (fill_system_matrix) { + mixed_fe_projector[cell_index].project( + &projected_jacobian_tangent_coefficients[i], + jacobian_tangents[i]); + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + mixed_fe_projector[cell_index].project( + &projected_strain_divergence_tangent_coefficients[i][j], + strain_divergence_tangents[i][j]); + } + } + } + + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + + const point_index_t quadrature_point_index = cell->user_index() + q_point; + + const Number cell_jacobian = determinant(static_cast>(mesh_motion_fe_values.jacobian(q_point))); + + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + mixed_values(i) = mixed_fe_values.shape_value(i, q_point); + } + + const auto mesh_motion_gradient = get_deformation_gradient( + -mesh_motion_gradient_increments[q_point], + -mesh_motion_value_increments[q_point][0]/mesh_motion_fe_values.quadrature_point(q_point)[0]); + + const auto deformation_gradient = get_deformation_gradient( + current_deformation_gradients[q_point] + deformation_gradient_increments[q_point], + (current_deformation_values[q_point][0] + deformation_value_increments[q_point][0]) + / mesh_motion_fe_values.quadrature_point(q_point)[0]); + + const auto inv_mesh_motion_gradient = invert(mesh_motion_gradient); + const auto inv_deformation_gradient = invert(deformation_gradient); + + const Number deformation_Jacobian = determinant(deformation_gradient); + const Number mesh_motion_Jacobian = determinant(mesh_motion_gradient); + + Number projected_jacobian = 0; + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + projected_jacobian += + mixed_values(i) * projected_Jacobian_coefficients.at(i); + } + + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + projected_strain_divergence[j] = + mixed_values(0) * projected_strain_divergence_coefficients[j][0]; + if (fill_system_matrix) { + projected_jacobian_tangent[j] = + mixed_values(0) * projected_jacobian_tangent_coefficients[j][0]; + for (unsigned int k = 0; k < dofs_per_cell; ++k) { + projected_strain_divergence_tangent[j][k] = + mixed_values(0) + * projected_strain_divergence_tangent_coefficients[j][k][0]; + } + } + } + + for (unsigned int i = 1; i < mixed_dofs_per_cell; ++i) { + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + projected_strain_divergence[j] += + mixed_values(i) * projected_strain_divergence_coefficients[j][i]; + if (fill_system_matrix) { + projected_jacobian_tangent[j] += + mixed_values(i) * projected_jacobian_tangent_coefficients[j][i]; + for (unsigned int k = 0; k < dofs_per_cell; ++k) { + projected_strain_divergence_tangent[j][k] += + mixed_values(i) + * projected_strain_divergence_tangent_coefficients[j][k][i]; + } + } + } + } + + std::vector> rate_gradients(dofs_per_cell); + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + rate_gradients[i] = postprocess_tensor_dimension( + -mesh_motion_fe_values[displacements].gradient(i, q_point), + -mesh_motion_fe_values[displacements].value(i, q_point)[0] + /mesh_motion_fe_values.quadrature_point(q_point)[0]) * inv_mesh_motion_gradient; + } + + const SymmetricTensor<2, dim+1, Number> stress_deviator = + std::pow(cell_jacobian, cell_jacobian_exponent) * mesh_motion_mu + * std::pow(mesh_motion_Jacobian, -Constants::two_thirds()) + * deviator( + symmetrize( + (deformation_gradient * mesh_motion_gradient) + * transpose(deformation_gradient * mesh_motion_gradient))); + + const Number pressure = mesh_motion_kappa * std::log(projected_jacobian); + + for (unsigned int i = 0; i < dofs_per_cell; ++i) { + const auto strain_i = deformation_gradient * rate_gradients[i] * inv_deformation_gradient; + + // stress deviator term + cell_residual(i) += symmetrize(strain_i) * stress_deviator + * mesh_motion_fe_values.quadrature_point(q_point)[0] * mesh_motion_fe_values.JxW(q_point); + + // pressure term + cell_residual(i) += (projected_strain_divergence.at(i) * pressure) + * mesh_motion_fe_values.quadrature_point(q_point)[0] * mesh_motion_fe_values.JxW(q_point); + + if (fill_system_matrix) { + + for (unsigned int j = 0; j < dofs_per_cell; ++j) { + const auto strain_j = deformation_gradient * rate_gradients[j] * inv_deformation_gradient; + + // stress tangent + const SymmetricTensor<2, dim+1, Number> stress_deviator_tangent_j = + std::pow(cell_jacobian, cell_jacobian_exponent) * mesh_motion_mu + * std::pow(mesh_motion_Jacobian, -Constants::two_thirds()) + * deviator( + symmetrize( + 2 * (strain_j - Constants::one_third() * trace(strain_j) * unit_symmetric_tensor()) + * (deformation_gradient * mesh_motion_gradient) + * transpose(deformation_gradient * mesh_motion_gradient))); + + cell_matrix(i, j) += (symmetrize(strain_i) * stress_deviator_tangent_j - symmetrize(strain_i * strain_j) * stress_deviator) + * mesh_motion_fe_values.quadrature_point(q_point)[0] * mesh_motion_fe_values.JxW(q_point); + + // pressure_tangent + const Number pressure_tangent_j = mesh_motion_kappa * (1.0 / projected_jacobian) * projected_jacobian_tangent[j]; + cell_matrix(i, j) += (projected_strain_divergence.at(i) * pressure_tangent_j + projected_strain_divergence_tangent[i][j] * pressure) + * mesh_motion_fe_values.quadrature_point(q_point)[0] * mesh_motion_fe_values.JxW(q_point); + + } + } + } + } + + // const Number relative_symmetry_norm2 = cell_matrix.relative_symmetry_norm2(); + // if(relative_symmetry_norm2 > 1e-8) + // std::cout << "relative_symmetry_norm2: " << cell_matrix.relative_symmetry_norm2() << std::endl; + + std::vector local_dof_indices (dofs_per_cell); + cell->get_dof_indices (local_dof_indices); + if (fill_system_matrix) { + mesh_motion_dof_system.nodal_constraints.distribute_local_to_global( + cell_matrix, + cell_residual, + local_dof_indices, + mesh_motion_nonlinear_system.Newton_step_matrix, + mesh_motion_nonlinear_system.Newton_step_residual, + true); + } else { + mesh_motion_dof_system.nodal_constraints.distribute_local_to_global( + cell_residual, local_dof_indices, + mesh_motion_nonlinear_system.Newton_step_residual); + } + } /* if cell is locally owned */ + } /*for (; cell!=endc; ++cell)*/ + + const unsigned short local_domain_is_valid = kinematic_domains_are_valid ? 1 : 0; + unsigned short all_kinematic_domains_are_valid; + + // did any of the processes fail to assemble? + MPI_Allreduce( + &local_domain_is_valid, + &all_kinematic_domains_are_valid, 1, MPI_UNSIGNED_SHORT, + MPI_MIN, mpi_communicator); + + if (all_kinematic_domains_are_valid < 1) { + throw std::runtime_error("The domain is not valid..."); + } + + if (fill_system_matrix) { + mesh_motion_nonlinear_system.Newton_step_matrix.compress(VectorOperation::add); + } + mesh_motion_nonlinear_system.Newton_step_residual.compress(VectorOperation::add); + + } + + template + class SumOfMatrices : public Subscriptor { + public: + SumOfMatrices( + const BlockType &m1, + const BlockType &m2): + m1(m1), + m2(m2) { + } + + template + void vmult(VectorType &dst, const VectorType &src) const { + m1.vmult(dst, src); + m2.vmult_add(dst, src); + } + + private: + const BlockType &m1; + const BlockType &m2; + }; + +// TODO encorporate mechanical and thermal subsystems into structs and include functions in them + template + void PlasticityLabProg::solve_system( + const DoFSystem &dof_system, + NewtonStepSystem &nonlinear_system, + const bool reset_solution) { + TrilinosWrappers::PreconditionAMG preconditioner; + + std::vector > constant_modes; + DoFTools::extract_constant_modes(dof_system.dof_handler, ComponentMask(), + constant_modes); + + TrilinosWrappers::PreconditionAMG::AdditionalData additional_data; + additional_data.constant_modes = constant_modes; + additional_data.elliptic = true; + additional_data.n_cycles = 1; + additional_data.w_cycle = false; + additional_data.output_details = false; + additional_data.smoother_sweeps = 2; + additional_data.aggregation_threshold = 1e-2; + preconditioner.initialize(nonlinear_system.Newton_step_matrix, additional_data); + + TrilinosWrappers::MPI::Vector tmp(dof_system.locally_owned_dofs, mpi_communicator); + const Number relative_accuracy = 1e-08; + const Number solver_tolerance = relative_accuracy + * nonlinear_system.Newton_step_matrix.residual(tmp, nonlinear_system.Newton_step_solution, + nonlinear_system.Newton_step_residual); + SolverControl solver_control(nonlinear_system.Newton_step_matrix.m(), + solver_tolerance); + + SolverBicgstab solver(solver_control); + + if (reset_solution) { + nonlinear_system.Newton_step_solution = 0; + nonlinear_system.Newton_step_solution.compress(VectorOperation::insert); + } + + solver.solve(nonlinear_system.Newton_step_matrix, nonlinear_system.Newton_step_solution, + nonlinear_system.Newton_step_residual, preconditioner); + + pcout << "solved in " << solver_control.last_step() << " steps to residual value of " << solver_control.last_value() << endl; + pcout << "solution norm is: " << nonlinear_system.Newton_step_solution.l2_norm() << endl; + + dof_system.nodal_constraints.distribute (nonlinear_system.Newton_step_solution); + } /*ElasticProblem::solve_system*/ + + + template + void PlasticityLabProg::get_plastic_strain( + TrilinosWrappers::MPI::Vector &plastic_strain, + const DoFHandler &discontinuous_dof_handler, + const Material &material, + const std::vector< MixedFEProjector > &qp_values_projectors) { + + const FiniteElement &fe = discontinuous_dof_handler.get_fe(); + + const unsigned int n_q_points = quadrature_formula.size(); + const unsigned int disc_dofs_per_cell = fe.dofs_per_cell; + + std::vector plastic_strain_qp_values(n_q_points); + std::vector projected_plastic_strains(disc_dofs_per_cell); + + auto cell = discontinuous_dof_handler.begin_active(); + auto endc = discontinuous_dof_handler.end(); + for (; cell != endc; ++cell) { + if (cell->is_locally_owned()) { + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + const point_index_t quadrature_point_index = cell->user_index() + q_point; + plastic_strain_qp_values[q_point] = std::exp(material.get_state_parameters(quadrature_point_index).at(0)) - 1; + } + + const unsigned int cell_index = cell->user_index() / n_q_points; + qp_values_projectors[cell_index].project( + &projected_plastic_strains, + plastic_strain_qp_values); + + std::vector local_dof_indices (disc_dofs_per_cell); + cell->get_dof_indices (local_dof_indices); + for (unsigned int dof_i = 0; dof_i < disc_dofs_per_cell; ++dof_i) { + plastic_strain(local_dof_indices[dof_i]) = projected_plastic_strains.at(dof_i); + } + } + } + } + + + template + void PlasticityLabProg::get_pressure( + TrilinosWrappers::MPI::Vector &pressure, + const DoFHandler &mixed_fe_dof_handler, + TrilinosWrappers::MPI::Vector &von_mises_stress, + const DoFHandler &discontinuous_dof_handler, + NewtonStepSystem &Newton_system, + const DoFSystem &mechanical_dof_system, + const NewtonStepSystem &thermal_Newton_system, + const DoFSystem &thermal_dof_system, + Material &material, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const std::vector< MixedFEProjector > &qp_values_projectors) { + + FEValues fe_values( + mapping, + mech_fe, + quadrature_formula, + update_values | update_quadrature_points | update_gradients); + + FEValues fe_therm_values( + mapping, + therm_fe, + quadrature_formula, + update_values); + + FEValues mixed_fe_values( + mapping, + mixed_var_fe, + quadrature_formula, + update_values); + + const unsigned int n_q_points = quadrature_formula.size(); + const unsigned int mixed_dofs_per_cell = mixed_var_fe.dofs_per_cell; + const unsigned int disc_dofs_per_cell = discontinuous_dof_handler.get_fe().dofs_per_cell; + + + std::vector< Tensor<2, dim, Number> > current_displacement_gradients(n_q_points); + std::vector< Tensor<2, dim, Number> > displacement_gradient_increments(n_q_points); + std::vector< Tensor<1, dim, Number> > current_displacement_values(n_q_points); + std::vector< Tensor<1, dim, Number> > displacement_value_increments(n_q_points); + + std::vector< Number > current_temperature_values(n_q_points); + std::vector< Number > updated_temperature_increments(n_q_points); + std::vector< Number > deformation_jacobians(n_q_points); + std::vector< Number > pressure_values(n_q_points); + std::vector< Number > von_mises_stress_values(n_q_points); + + std::vector projected_temperature_coefficients(mixed_dofs_per_cell); + std::vector projected_Jacobian_coefficients(mixed_dofs_per_cell); + std::vector projected_pressure_coefficients(mixed_dofs_per_cell); + std::vector projected_von_mises_stress_coefficients(disc_dofs_per_cell); + + Vector mixed_values(mixed_dofs_per_cell); + + const FEValuesExtractors::Vector displacements (0); + const FEValuesExtractors::Scalar temperature (0); + + auto cell = mechanical_dof_system.dof_handler.begin_active(); + auto endc = mechanical_dof_system.dof_handler.end(); + auto thermal_cell = thermal_dof_system.dof_handler.begin_active(); + auto mixed_fe_cell = mixed_fe_dof_handler.begin_active(); + auto discontinuous_fe_cell = discontinuous_dof_handler.begin_active(); + for (; cell != endc; ++cell, ++thermal_cell, ++mixed_fe_cell, ++discontinuous_fe_cell) { + if (cell->is_locally_owned()) { + + fe_values.reinit (cell); + fe_therm_values.reinit (thermal_cell); + mixed_fe_values.reinit (mixed_fe_cell); + + fe_values[displacements].get_function_gradients( + Newton_system.current_increment, + displacement_gradient_increments); + + fe_values[displacements].get_function_gradients( + Newton_system.previous_deformation, + current_displacement_gradients); + + fe_values[displacements].get_function_values( + Newton_system.current_increment, + displacement_value_increments); + + fe_values[displacements].get_function_values( + Newton_system.previous_deformation, + current_displacement_values); + + fe_therm_values[temperature].get_function_values ( + thermal_Newton_system.previous_deformation, + current_temperature_values); + + fe_therm_values[temperature].get_function_values ( + thermal_Newton_system.current_increment, + updated_temperature_increments); + + // get vectors for projection onto mixed fe values + for (unsigned int q_point = 0; q_point < n_q_points; + ++q_point) { + updated_temperature_increments.at(q_point) += current_temperature_values.at(q_point); + + const auto current_F = get_deformation_gradient( + current_displacement_gradients[q_point], + current_displacement_values[q_point][0]/fe_values.quadrature_point(q_point)[0] + ); + const auto updated_F = get_deformation_gradient( + current_displacement_gradients[q_point] + + displacement_gradient_increments[q_point], + (current_displacement_values[q_point][0] + + displacement_value_increments[q_point][0])/fe_values.quadrature_point(q_point)[0]); + + const point_index_t quadrature_point_index = cell->user_index() + q_point; + const Number material_Jacobian = material.get_material_Jacobian(quadrature_point_index) / determinant(current_F); + + deformation_jacobians.at(q_point) = material_Jacobian * determinant(updated_F); + } + + const unsigned int cell_index = cell->user_index() / n_q_points; + + mixed_fe_projector[cell_index].project( + &projected_temperature_coefficients, + updated_temperature_increments); + mixed_fe_projector[cell_index].project( + &projected_Jacobian_coefficients, + deformation_jacobians); + + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) { + + const point_index_t quadrature_point_index = cell->user_index() + q_point; + ConstitutiveModelRequest constitutive_request(update_pressure | update_stress_deviator); + + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + mixed_values(i) = mixed_fe_values.shape_value(i, q_point); + } + + const auto current_F = get_deformation_gradient( + current_displacement_gradients[q_point], + current_displacement_values[q_point][0]/fe_values.quadrature_point(q_point)[0] + ); + const auto updated_F = get_deformation_gradient( + current_displacement_gradients[q_point] + + displacement_gradient_increments[q_point], + (current_displacement_values[q_point][0] + + displacement_value_increments[q_point][0])/fe_values.quadrature_point(q_point)[0]); + + const auto inv_updated_F = invert(updated_F); + const Number Jacobian = determinant(updated_F); + const Number previous_Jacobian = determinant(current_F); + + const auto deformation_gradient_increment = std::pow(Jacobian / previous_Jacobian, -Constants::one_third()) * updated_F * invert(current_F); + + Number projected_jacobian = 0; + Number projected_temperature = 0; + for (unsigned int i = 0; i < mixed_dofs_per_cell; ++i) { + projected_jacobian += + mixed_values(i) * projected_Jacobian_coefficients.at(i); + projected_temperature += + mixed_values(i) * projected_temperature_coefficients.at(i); + } + + constitutive_request.set_deformation_Jacobian(projected_jacobian); + constitutive_request.set_temperature(projected_temperature); + constitutive_request.set_deformation_gradient(deformation_gradient_increment); + constitutive_request.set_time_increment(time_increment); + + material.compute_constitutive_request(constitutive_request, + quadrature_point_index); + + // pressure term + pressure_values.at(q_point) = constitutive_request.get_pressure(); + von_mises_stress_values.at(q_point) = + constitutive_request.get_stress_deviator().norm() / Constants::sqrt2thirds(); + } + + mixed_fe_projector[cell_index].project( + &projected_pressure_coefficients, + pressure_values); + + qp_values_projectors[cell_index].project( + &projected_von_mises_stress_coefficients, + von_mises_stress_values); + + std::vector local_dof_indices (mixed_dofs_per_cell); + mixed_fe_cell->get_dof_indices (local_dof_indices); + for (unsigned int dof_i = 0; dof_i < mixed_dofs_per_cell; ++dof_i) { + pressure(local_dof_indices[dof_i]) = projected_pressure_coefficients.at(dof_i); + } + + std::vector local_discontinuous_dof_indices(disc_dofs_per_cell); + discontinuous_fe_cell->get_dof_indices (local_discontinuous_dof_indices); + for (unsigned int dof_i = 0; dof_i < disc_dofs_per_cell; ++dof_i) { + von_mises_stress(local_discontinuous_dof_indices[dof_i]) = + projected_von_mises_stress_coefficients.at(dof_i); + } + + } /* if cell is locally owned */ + } /*for (; cell!=endc; ++cell)*/ + } + + template + void PlasticityLabProg::prepare_output_results( + DataOut &data_out, + const DoFSystem &mechanical_dof_system, + const NewtonStepSystem &mechanical_nonlinear_system, + const DoFSystem &thermal_dof_system, + const NewtonStepSystem &thermal_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const NewtonStepSystem &mesh_motion_nonlinear_system) const { + + std::vector displacement_names(dim, "displacement"); + displacement_names.emplace_back("angular_displacement"); + std::vector velocity_names(dim, "displacement_time_rate"); + velocity_names.emplace_back("angular_velocity"); + std::vector + data_component_interpretation( + dim, DataComponentInterpretation::component_is_part_of_vector); + data_component_interpretation.push_back( + DataComponentInterpretation::component_is_scalar); + + std::vector + mesh_motion_data_component_interpretation( + dim, DataComponentInterpretation::component_is_part_of_vector); + + data_out.add_data_vector(mechanical_dof_system.dof_handler, + mechanical_nonlinear_system.previous_deformation, + displacement_names, + data_component_interpretation); + data_out.add_data_vector(mechanical_dof_system.dof_handler, + mechanical_nonlinear_system.previous_time_derivative, + velocity_names, + data_component_interpretation); + data_out.add_data_vector(thermal_dof_system.dof_handler, + thermal_nonlinear_system.previous_deformation, + "Temperature"); + data_out.add_data_vector(mesh_motion_dof_system.dof_handler, + mesh_motion_nonlinear_system.previous_deformation, + std::vector(dim, "mesh_motion"), + mesh_motion_data_component_interpretation); + data_out.add_data_vector(mesh_motion_dof_system.dof_handler, + mesh_motion_nonlinear_system.previous_time_derivative, + std::vector(dim, "mesh_velocity"), + mesh_motion_data_component_interpretation); + data_out.build_patches(mapping, 2); + } + + template + template + void PlasticityLabProg::write_output_results( + DataOut &data_out, + const TriangulationType &tria, + const std::string &filename_base) const { + + const std::string filename = + (filename_base + "-" + + Utilities::int_to_string(tria.locally_owned_subdomain(), 4)); + + std::ofstream output_vtu((filename + ".vtu").c_str()); + data_out.write_vtu(output_vtu); + + if (Utilities::MPI::this_mpi_process(mpi_communicator) == 0) { + std::vector filenames; + for (unsigned int i = 0; + i < Utilities::MPI::n_mpi_processes(mpi_communicator); ++i) + filenames.push_back(filename_base + "-" + + Utilities::int_to_string(i, 4) + + ".vtu"); + std::ofstream pvtu_master_output((filename_base + ".pvtu").c_str()); + data_out.write_pvtu_record(pvtu_master_output, filenames); + std::ofstream visit_master_output((filename_base + ".visit").c_str()); + DataOutBase::write_visit_record(visit_master_output, filenames); + } + } /* output_results */ + + template class PlasticityLabProg<2, double>; + +} /*namespace PlasticityLab*/ diff --git a/ALE_Finite_Strain_Plasticity/src/PlasticityLabProg.h b/ALE_Finite_Strain_Plasticity/src/PlasticityLabProg.h new file mode 100644 index 00000000..8ede4d4d --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/PlasticityLabProg.h @@ -0,0 +1,456 @@ +/* + * PlasticityLabProg.h + * + * Created on: 09 Jul 2014 + * Author: cerecam + */ + +#ifndef PLASTICITYLABPROG_H_ +#define PLASTICITYLABPROG_H_ + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "DoFSystem.h" +#include "LBCSystem.h" +#include "MixedFEProjector.h" +#include "Material.h" +#include "NewtonStepSystem.h" + +namespace PlasticityLab { + using namespace dealii; + + template + class PlasticityLabProg { + public: + PlasticityLabProg(Material &); + virtual ~PlasticityLabProg(); + void run(); + + private: + void make_grid (int); + void make_cylindrical_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements); + void make_grid_(); + void make_necking_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements); + void make_interference_cylinder_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements); + void make_cylindrical_impact_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements); + void make_ball_in_hypershell_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements); + void make_hook_membrane_grid(int); + + void set_mesh_motion_LBCs( + Triangulation &triangulation, + LBCSystem &mesh_motion_lbc_system); + + + Tensor<2, dim+1, Number> get_rotation_tensor(const Tensor<2, dim+1, Number> &skew_symmetric_rotation) const; + Tensor<2, dim+1, Number> get_rotation_tensor_variation( + const Tensor<2, dim+1, Number> &skew_symmetric_rotation, + const Tensor<2, dim+1, Number> &skew_symmetric_rotation_variation) const; + + + void remap_material_state_variables( + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const NewtonStepSystem &mechanical_nonlinear_system, + const DoFSystem &mechanical_dof_system, + const DoFSystem &mixed_fe_dof_system, + const std::vector< MixedFEProjector > &mixed_fe_projector, + Material &material, + std::unordered_map> &remapped_deformation_gradients); + + + void remap_thermal_field( + NewtonStepSystem &thermal_nonlinear_system, + const DoFSystem &thermal_dof_system, + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system); + + + void remap_mechanical_fields( + NewtonStepSystem &mechanical_nonlinear_system, + const DoFSystem &mechanical_dof_system, + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system); + + + template + void setup_material_data(TriangulationType &triangulation, + MaterialType &material); + + void setup_material_area_factors( + const DoFSystem &mesh_motion_dof_system, + std::unordered_map> &material_area_factors); + + void update_material_area_factors( + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + std::unordered_map> &material_area_factors); + + template + void setup_mixed_fe_projection_data( + const TriangulationType &triangulation, + std::vector< MixedFEProjector > &MixedFeProjectors, + const FiniteElement &MixedFE, + const Quadrature &quadrature_formula); + + void assemble_mechanical_system( + NewtonStepSystem &Newton_system, + const DoFSystem &mechanical_dof_system, + const LBCSystem &mechanical_lbc_system, + const NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const NewtonStepSystem &thermal_Newton_system, + const DoFSystem &thermal_dof_system, + const DoFSystem &mixed_fe_dof_system, + Material &material, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const bool fill_system_matrix = true, + const bool update_material_state = false); + + void assemble_thermal_system( + NewtonStepSystem &Newton_system, + NewtonStepSystem &mechanical_nonlinear_system, + const DoFSystem &thermal_dof_system, + const LBCSystem &thermal_lbc_system, + const DoFSystem &mechanical_dof_system, + const DoFSystem &mixed_fe_dof_system, + Material &material, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const std::unordered_map> &material_area_factors, + const bool fill_system_matrix = true); + + void assemble_mesh_motion_system( + NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const LBCSystem &mesh_motion_lbc_system, + const NewtonStepSystem &deformation_nonlinear_system, + const DoFSystem &deformation_dof_system, + const DoFSystem &mixed_fe_dof_system, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const bool fill_system_matrix = true); + + void solve_system(const DoFSystem &dof_system, + NewtonStepSystem &nonlinear_system, + const bool reset_solution=true); + + void prepare_output_results(DataOut &data_out, + const DoFSystem &dof_system, + const NewtonStepSystem &nonlinear_system, + const DoFSystem &thermal_dof_system, + const NewtonStepSystem &thermal_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const NewtonStepSystem &mesh_motion_nonlinear_system) const; + + template + void write_output_results(DataOut &data_out, + const TriangulationType &tria, + const std::string &filename_base) const; + + void get_plastic_strain( + TrilinosWrappers::MPI::Vector &plastic_strain, + const DoFHandler &discontinuous_dof_handler, + const Material &material, + const std::vector< MixedFEProjector > &qp_values_projectors); + + void get_pressure( + TrilinosWrappers::MPI::Vector &pressure, + const DoFHandler &mixed_fe_dof_handler, + TrilinosWrappers::MPI::Vector &von_mises_stress, + const DoFHandler &discontinuous_dof_handler, + NewtonStepSystem &Newton_system, + const DoFSystem &mechanical_dof_system, + const NewtonStepSystem &thermal_Newton_system, + const DoFSystem &thermal_dof_system, + Material &material, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const std::vector< MixedFEProjector > &qp_values_projectors); + + void solve_mechanical_step(int time_step); + void solve_thermal_step(int time_step); + + void solve_mesh_motion_step( + NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const LBCSystem &mesh_motion_lbc_system, + const NewtonStepSystem &deformation_nonlinear_system, + const DoFSystem &deformation_dof_system, + const DoFSystem &mixed_fe_dof_system, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const int time_step); + + Tensor<2, dim+1, Number> get_deformation_gradient( + const Tensor<2, dim, Number> &increment_gradient, + const Number increment_0_over_rho) { + Tensor<2, dim+1, Number> deformation_gradient = unit_symmetric_tensor(); + for(unsigned int i=0; i postprocess_tensor_dimension( + const Tensor<2, dim, Number> &dimension_short_tensor, + const Number entry_0_over_rho) { + Tensor<2, dim+1, Number> postprocessed_tensor; + for(unsigned int i=0; i postprocess_tensor_dimension( + const Tensor<1, dim, Number> &dimension_short_tensor, + const Number entry_at_dim=static_cast(0.0)) { + Tensor<1, dim+1, Number> postprocessed_tensor; + for(unsigned int i=0; i scalar_to_angular_tensor(const Number angular_value) { + Tensor<1, dim+1, Number> postprocessed_tensor = Tensor<1, dim+1, Number>(); + postprocessed_tensor[dim] = angular_value; + return postprocessed_tensor; + } + + Tensor<2, dim+1, Number> order_1_tensor_to_angular_gradient( + const Tensor<1, dim, Number> &in_plane_gradient, + const Number minus_entry_over_rho) { + Tensor<2, dim+1, Number> postprocessed_tensor; + for(unsigned int i=0; i deformation_gradient_from_angular_displacement_gradient( + const Number angular_displacement, + const Tensor<1, dim, Number> &angular_displacement_gradient, + const Number radius + ) { + if(2 != dim) { + throw std::logic_error("Radial deformation gradient not implemented for dim!=2"); + } + + Tensor<2, dim+1, Number> result; + const Number theta = angular_displacement / radius; + Tensor<1, dim, Number> angular_displacmenet_over_r_squared; + angular_displacmenet_over_r_squared[0] = angular_displacement / (radius * radius); + const Tensor<1, dim, Number> theta_gradient = angular_displacement_gradient / radius - angular_displacmenet_over_r_squared; + + result[0][0] = std::cos(theta) - radius * std::sin(theta) * theta_gradient[0]; + result[0][1] = - radius * std::sin(theta) * theta_gradient[1]; + result[0][2] = -std::sin(theta); + + result[1][0] = 0; + result[1][1] = 1; + result[1][2] = 0; + + result[2][0] = std::sin(theta) + radius * std::cos(theta) * theta_gradient[0]; + result[2][1] = radius * std::cos(theta) * theta_gradient[1]; + result[2][2] = std::cos(theta); + + return result; + } + + Tensor<2, dim+1, Number> deformation_gradient_from_angular_displacement_gradient_variations( + const Number angular_displacement, + const Tensor<1, dim, Number> &angular_displacement_gradient, + const Number radius, + const Number angular_displacement_variation, + const Tensor<1, dim, Number> &angular_displacement_gradient_variation + ) { + if(2 != dim) { + throw std::logic_error("Radial deformation gradient not implemented for dim!=2"); + } + + Tensor<2, dim+1, Number> result; + const Number theta = angular_displacement / radius; + const Number theta_variation = angular_displacement_variation / radius; + + Tensor<1, dim, Number> angular_displacmenet_over_r_squared; + angular_displacmenet_over_r_squared[0] = angular_displacement / (radius * radius); + const Tensor<1, dim, Number> theta_gradient = angular_displacement_gradient / radius - angular_displacmenet_over_r_squared; + + Tensor<1, dim, Number> angular_displacmenet_variation_over_r_squared; + angular_displacmenet_variation_over_r_squared[0] = angular_displacement_variation / (radius * radius); + const Tensor<1, dim, Number> theta_gradient_variation = angular_displacement_gradient_variation / radius - angular_displacmenet_variation_over_r_squared; + + result[0][0] = - std::sin(theta) * theta_variation + - radius * std::cos(theta) * theta_variation * theta_gradient[0] + - radius * std::sin(theta) * theta_gradient_variation[0]; + + result[0][1] = - radius * std::cos(theta) * theta_variation * theta_gradient[1] + - radius * std::sin(theta) * theta_gradient_variation[1]; + + result[0][2] = -std::cos(theta) * theta_variation; + + result[1][0] = 0; + result[1][1] = 0; + result[1][2] = 0; + + result[2][0] = std::cos(theta) * theta_variation + - radius * std::sin(theta) * theta_variation * theta_gradient[0] + + radius * std::cos(theta) * theta_gradient_variation[0]; + + result[2][1] = - radius * std::sin(theta) * theta_variation * theta_gradient[1] + + radius * std::cos(theta) * theta_gradient_variation[1]; + + result[2][2] = - std::sin(theta) * theta_variation; + + return result; + } + + Tensor<2, dim+1, Number> rotation_tensor_to_transform_B_e( + const Number angular_displacement, + const Number radius + ) { + if(2 != dim) { + throw std::logic_error("Radial deformation gradient not implemented for dim!=2"); + } + + Tensor<2, dim+1, Number> result; + const Number theta = angular_displacement / radius; + + result[0][0] = std::cos(theta); + result[0][1] = 0; + result[0][2] = -std::sin(theta); + + result[1][0] = 0; + result[1][1] = 1; + result[1][2] = 0; + + result[2][0] = std::sin(theta); + result[2][1] = 0; + result[2][2] = std::cos(theta); + + return result; + } + + Tensor<2, dim+1, Number> rotation_tensor_variation_to_transform_B_e( + const Number angular_displacement, + const Number angular_displacement_variation, + const Number radius + ) { + if(2 != dim) { + throw std::logic_error("Radial deformation gradient not implemented for dim!=2"); + } + + Tensor<2, dim+1, Number> result; + const Number theta = angular_displacement / radius; + const Number theta_variation = angular_displacement_variation / radius; + + result[0][0] = -std::sin(theta) * theta_variation; + result[0][1] = 0; + result[0][2] = -std::cos(theta) * theta_variation; + + result[1][0] = 0; + result[1][1] = 0; + result[1][2] = 0; + + result[2][0] = std::cos(theta) * theta_variation; + result[2][1] = 0; + result[2][2] = -std::sin(theta) * theta_variation; + + return result; + } + + MPI_Comm mpi_communicator; + ConditionalOStream pcout; + + const Number order; + FESystem mech_fe; + FE_Q therm_fe; + FE_DGP mixed_var_fe; + FESystem mesh_motion_fe; + MappingQ mapping; + + parallel::distributed::Triangulation triangulation; + + DoFSystem mech_dof_system; + DoFSystem therm_dof_system; + DoFSystem mixed_fe_dof_system; + + LBCSystem mech_lbc_system; + LBCSystem therm_lbc_system; + + NewtonStepSystem mech_nonlinear_system; + NewtonStepSystem therm_nonlinear_system; + + NewtonStepSystem mesh_motion_nonlinear_system; + DoFSystem mesh_motion_dof_system; + LBCSystem mesh_motion_lbc_system; + + NewtonStepSystem deformation_remapping_nonlinear_system; + + QGauss quadrature_formula; + QGauss face_quadrature_formula; + + Material &material; + + std::vector< MixedFEProjector > mixed_FE_projectors; + + std::unordered_map> material_area_factors; + + Number time_increment = 1.0e-01; /*0.5e-6;*/ // [s] + unsigned int output_rate = 1; + Number time_since_start = 0; + + const Number ambient_temperature = 293.0; // [K] + const Number rho_infty = 0.0; + + const unsigned int surface_boundary_id = 2; + + const bool COMPUTE_FORCES_PER_UNIT_AREA_IN_CURRENT_CONFIGURATION = false; + const bool use_sigmoid_friction_law = true; + + Number global_lagrangian_penalty_factor = 1.0; + + }; + + struct NewtonIterationDivergenceException : std::exception { + const char *what() const _GLIBCXX_USE_NOEXCEPT { + return "Newton step solution diverged!\n"; + } + }; + +} /*namespace PlasticityLab*/ + +#endif /* PLASTICITYLABPROG_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/PlasticityLabProgDrivers.cpp b/ALE_Finite_Strain_Plasticity/src/PlasticityLabProgDrivers.cpp new file mode 100644 index 00000000..eb82daa3 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/PlasticityLabProgDrivers.cpp @@ -0,0 +1,1450 @@ +#include + +#include +#include +#include +#include +#include + + +#include + +#include "RotationFunction.h" +#include "ScaleZFunction.h" +#include "ScaleComponentFunction.h" +#include "PlasticityLabProg.h" + +using namespace dealii; +using std::endl; + +namespace PlasticityLab { + + template + void PlasticityLabProg::run() { + // make_grid_(); + // make_ball_in_hypershell_grid( + // make_cylindrical_grid( + // make_cylindrical_impact_grid( + make_necking_grid( + triangulation, + mech_lbc_system, + therm_lbc_system, + 3); + // triangulation, + // mech_lbc_system, + // therm_lbc_system, + // 3); + // make_hook_membrane_grid(1); + + set_mesh_motion_LBCs(triangulation, mesh_motion_lbc_system); + + const Number total_elongation = 8.0; // mm + const Number elongation_rate = 1.0; // [mm/s] + const unsigned int n_steps = ceil(total_elongation/(elongation_rate*time_increment)); + + mech_dof_system.setup_dof_system(mech_fe); + mech_lbc_system.apply_constraints(mech_dof_system); + mech_nonlinear_system.setup(mech_dof_system); + + therm_dof_system.setup_dof_system(therm_fe); + therm_lbc_system.apply_constraints(therm_dof_system); + therm_nonlinear_system.setup(therm_dof_system); + + therm_nonlinear_system.previous_deformation = ambient_temperature; + + mixed_fe_dof_system.setup_dof_system(mixed_var_fe); + + mesh_motion_dof_system.setup_dof_system(mesh_motion_fe); + mesh_motion_lbc_system.apply_constraints(mesh_motion_dof_system); + mesh_motion_nonlinear_system.setup(mesh_motion_dof_system); + + deformation_remapping_nonlinear_system.setup(mech_dof_system); + + setup_material_data(triangulation, material); + setup_material_area_factors(mesh_motion_dof_system, material_area_factors); + + setup_mixed_fe_projection_data( + triangulation, mixed_FE_projectors, + mixed_var_fe, quadrature_formula); + + std::vector< MixedFEProjector > discontinuous_projectors; + FE_DGQ discontinuous_fe(1); + + setup_mixed_fe_projection_data( + triangulation, discontinuous_projectors, + discontinuous_fe, quadrature_formula); + + TrilinosWrappers::MPI::Vector pressure( + mixed_fe_dof_system.locally_owned_dofs, + mpi_communicator); + + DoFSystem discontinuous_dof_system(triangulation, mapping); + discontinuous_dof_system.setup_dof_system(discontinuous_fe); + TrilinosWrappers::MPI::Vector plastic_strain( + discontinuous_dof_system.locally_owned_dofs, + mpi_communicator); + TrilinosWrappers::MPI::Vector von_mises_stress( + discontinuous_dof_system.locally_owned_dofs, + mpi_communicator); + + std::vector< MixedFEProjector > mech_fe_projectors; + + setup_mixed_fe_projection_data( + triangulation, mech_fe_projectors, + mech_fe, quadrature_formula); + + + + { + TrilinosWrappers::MPI::Vector initial_velocity( + mech_dof_system.locally_owned_dofs, + mpi_communicator); + + MPI_Barrier(mpi_communicator); + + for(const auto initial_velocity_interpolation_handler: mech_lbc_system.initial_velocity_interpolation_handlers) { + initial_velocity_interpolation_handler->interpolate(initial_velocity, mech_dof_system); + } + + mech_nonlinear_system.previous_time_derivative = initial_velocity; + mech_nonlinear_system.previous_time_derivative.compress( + VectorOperation::insert); + } + + + { + TrilinosWrappers::MPI::Vector initial_deformation( + mech_dof_system.locally_owned_dofs, + mpi_communicator); + + MPI_Barrier(mpi_communicator); + + for(const auto initial_deformation_interpolation_handler: mech_lbc_system.initial_deformation_interpolation_handlers) { + initial_deformation_interpolation_handler->interpolate(initial_deformation, mech_dof_system); + } + + mech_nonlinear_system.previous_deformation = initial_deformation; + mech_nonlinear_system.previous_deformation.compress( + VectorOperation::insert); + } + + + for (unsigned int timeStep = 0; timeStep < n_steps + 1; ++timeStep) { + for(const auto increment_interpolation_handler: mech_lbc_system.increment_interpolation_handlers) { + increment_interpolation_handler->advance_time(time_increment); + } + + get_plastic_strain( + plastic_strain, + discontinuous_dof_system.dof_handler, + material, + discontinuous_projectors); + + get_pressure( + pressure, + mixed_fe_dof_system.dof_handler, + von_mises_stress, + discontinuous_dof_system.dof_handler, + mech_nonlinear_system, + mech_dof_system, + therm_nonlinear_system, + therm_dof_system, + material, + mixed_FE_projectors, + discontinuous_projectors); + + if(0==timeStep % output_rate) { + pcout << "\nOutputting results..." << endl; + DataOut data_out; + + data_out.add_data_vector( + discontinuous_dof_system.dof_handler, + plastic_strain, + "plastic_strain"); + data_out.build_patches(); + + data_out.add_data_vector( + mixed_fe_dof_system.dof_handler, + pressure, + "pressure"); + data_out.build_patches(); + + data_out.add_data_vector( + discontinuous_dof_system.dof_handler, + von_mises_stress, + "von_mises_stress"); + + prepare_output_results( + data_out, + mech_dof_system, + mech_nonlinear_system, + therm_dof_system, + therm_nonlinear_system, + mesh_motion_dof_system, + mesh_motion_nonlinear_system); + + std::ostringstream oss; + oss << "step_" << timeStep; + const std::string output_name = oss.str(); + write_output_results(data_out, triangulation, output_name); + } + + if (timeStep == n_steps) break; + + pcout << "\n\nStarting time step " << timeStep << ":\n\n" << endl; + + { + TrilinosWrappers::MPI::Vector step_increment( + mech_dof_system.locally_owned_dofs, + mpi_communicator); + + MPI_Barrier(mpi_communicator); + + for(const auto increment_interpolation_handler: mech_lbc_system.increment_interpolation_handlers) { + increment_interpolation_handler->interpolate(step_increment, mech_dof_system); + } + + mech_nonlinear_system.current_increment = step_increment; + mech_nonlinear_system.current_increment.compress( + VectorOperation::insert); + } + + solve_mesh_motion_step( + mesh_motion_nonlinear_system, + mesh_motion_dof_system, + mesh_motion_lbc_system, + mech_nonlinear_system, + mech_dof_system, + mixed_fe_dof_system, + mixed_FE_projectors, + timeStep); + + mesh_motion_nonlinear_system.advance_time(time_increment, rho_infty, false); + mesh_motion_nonlinear_system.previous_deformation = mesh_motion_nonlinear_system.current_increment; + mesh_motion_nonlinear_system.previous_deformation *= -1; + + std::unordered_map> remapped_deformation_gradients; + remap_material_state_variables( + mesh_motion_nonlinear_system, + mesh_motion_dof_system, + mech_nonlinear_system, + mech_dof_system, + mixed_fe_dof_system, + mixed_FE_projectors, + material, + remapped_deformation_gradients); + + remap_thermal_field( + therm_nonlinear_system, + therm_dof_system, + mesh_motion_nonlinear_system, + mesh_motion_dof_system); + + remap_mechanical_fields( + mech_nonlinear_system, + mech_dof_system, + mesh_motion_nonlinear_system, + mesh_motion_dof_system); + + update_material_area_factors( + mesh_motion_nonlinear_system, + mesh_motion_dof_system, + material_area_factors); + + solve_mechanical_step(timeStep); + + solve_thermal_step(timeStep); + + solve_mechanical_step(timeStep); + + // udpate material state + pcout << "\n\t\tassembling mechanical system updating material state..." << endl; + assemble_mechanical_system( + mech_nonlinear_system, + mech_dof_system, + mech_lbc_system, + mesh_motion_nonlinear_system, + mesh_motion_dof_system, + therm_nonlinear_system, + therm_dof_system, + mixed_fe_dof_system, + material, + mixed_FE_projectors, + false, + true); + + mech_nonlinear_system.advance_time(time_increment, rho_infty, true); + therm_nonlinear_system.previous_deformation += therm_nonlinear_system.current_increment; + therm_nonlinear_system.previous_deformation.compress(VectorOperation::add); + + therm_nonlinear_system.current_increment = 0; + therm_nonlinear_system.current_increment.compress(VectorOperation::insert); + + pcout << "Next timestep..." << std::endl; + + } /*for(timeStep)*/ + } + + template + void PlasticityLabProg::solve_mechanical_step(int time_step) { + + TrilinosWrappers::MPI::Vector total_residual; + + for (unsigned int NewtonStep = 0; true; NewtonStep++) { + + pcout << "\n\ttime step " << time_step + << ", Newton step " << NewtonStep << "..." + << "\n\t\tassembling mechanical system with tangents..." << endl; + + assemble_mechanical_system( + mech_nonlinear_system, + mech_dof_system, + mech_lbc_system, + mesh_motion_nonlinear_system, + mesh_motion_dof_system, + therm_nonlinear_system, + therm_dof_system, + mixed_fe_dof_system, + material, + mixed_FE_projectors, + true); + + total_residual = mech_nonlinear_system.Newton_step_residual; + total_residual.compress(VectorOperation::insert); + + pcout << "-------------------------------------------------------------------" << endl; + + pcout << "Normalized system residual: " + << std::sqrt(total_residual.norm_sqr()) + << " ..." << endl; + pcout << "-------------------------------------------------------------------" << endl; + + if (std::sqrt(total_residual.norm_sqr()) <= 1e-5) { + break; + } + + const Number old_residual = total_residual.norm_sqr(); + Number previous_residual = old_residual; + + pcout << "solving system..." << endl; + try { + solve_system(mech_dof_system, mech_nonlinear_system); + } catch (...) { + if (std::isnan(mech_nonlinear_system.Newton_step_solution.norm_sqr())) { + throw; + } + pcout << "System solution falied. Continuing with partial solution..." << endl; + } + mech_dof_system.nodal_constraints.distribute( + mech_nonlinear_system.Newton_step_solution); + const Number solution_norm = std::sqrt( + mech_nonlinear_system.Newton_step_solution.norm_sqr()); + TrilinosWrappers::MPI::Vector full_step_increment(mech_nonlinear_system.current_increment); + TrilinosWrappers::MPI::Vector temp_locally_owned_increment(mech_dof_system.locally_owned_dofs); + + Number clip_factor = + (solution_norm <= std::sqrt(old_residual)) ? + 1.0 : sqrt(old_residual) / solution_norm; + if (clip_factor < 1.0) pcout << "clip factor: " << clip_factor << endl; + + pcout << "doing line search..." << endl; + bool hit_line_search_limit = false; + for (unsigned int i = 0; true/*i < 18*/; ++i) { + const Number alpha = std::pow(0.5, static_cast(i)); + if (i > 5 && clip_factor * alpha * solution_norm < 1e-1) { + hit_line_search_limit = true; + break; + } + if (i > 0) pcout << "\tline search step " << i << "..." << endl; + + while (true) { + temp_locally_owned_increment = full_step_increment; + temp_locally_owned_increment.sadd(1, -alpha * clip_factor, mech_nonlinear_system.Newton_step_solution); + temp_locally_owned_increment.compress(VectorOperation::insert); + mech_nonlinear_system.current_increment = temp_locally_owned_increment; + mech_nonlinear_system.current_increment.compress(VectorOperation::insert); + + try { + assemble_mechanical_system( + mech_nonlinear_system, + mech_dof_system, + mech_lbc_system, + mesh_motion_nonlinear_system, + mesh_motion_dof_system, + therm_nonlinear_system, + therm_dof_system, + mixed_fe_dof_system, + material, + mixed_FE_projectors, + false); + } catch (const std::runtime_error &) { + clip_factor *= 0.125; // using a power of 0.5; better for binary arithmetic + pcout << "\t-------------------------------------------------------------------" << endl; + pcout << "\tDeformation too large, causing degenerate mesh..." << endl; + pcout << "\tupdated clip factor: " << clip_factor << endl; + pcout << "\t-------------------------------------------------------------------" << endl; + continue; + } + break; + } + + total_residual = mech_nonlinear_system.Newton_step_residual; + total_residual.compress(VectorOperation::insert); + + const Number current_residual = total_residual.norm_sqr(); + + pcout << "\t-------------------------------------------------------------------" << endl; + + pcout << "\tNormalized system residual: " + << std::sqrt(current_residual) + << " ..." << endl; + pcout << "\t-------------------------------------------------------------------" << endl; + + if (previous_residual < old_residual and current_residual >= previous_residual) { + pcout << "\t---Accepting previous residual: " << std::sqrt(previous_residual) + << " ..." << endl; + + temp_locally_owned_increment = full_step_increment; + temp_locally_owned_increment.sadd(1, -2 * alpha * clip_factor, mech_nonlinear_system.Newton_step_solution); + temp_locally_owned_increment.compress(VectorOperation::insert); + mech_nonlinear_system.current_increment = temp_locally_owned_increment; + mech_nonlinear_system.current_increment.compress(VectorOperation::insert); + break; + } + previous_residual = current_residual; + } + + } + } + + + template + void PlasticityLabProg::solve_thermal_step(int time_step) { + + TrilinosWrappers::MPI::Vector total_therm_residual; + const Number starting_thermal_residual_squared_norm = 1.0; + + for (unsigned int NewtonStep = 0; true; NewtonStep++) { + + pcout << "\n\ttime step " << time_step + << ", Newton step " << NewtonStep << "..." + << "\n\t\tassembling thermal system with tangents..." << endl; + + assemble_thermal_system( + therm_nonlinear_system, + mech_nonlinear_system, + therm_dof_system, + therm_lbc_system, + mech_dof_system, + mixed_fe_dof_system, + material, + mixed_FE_projectors, + material_area_factors, + true); + + total_therm_residual = therm_nonlinear_system.Newton_step_residual; + total_therm_residual.compress(VectorOperation::insert); + + pcout << "-------------------------------------------------------------------" << endl; + pcout << "Normalized system residual (contactor): " + << std::sqrt(total_therm_residual.norm_sqr() + / starting_thermal_residual_squared_norm) + << " ..." << endl; + pcout << "-------------------------------------------------------------------" << endl; + + if (std::sqrt(total_therm_residual.norm_sqr() + / starting_thermal_residual_squared_norm) <= 1e-6) { + break; + } + + const Number old_residual = total_therm_residual.norm_sqr(); + + pcout << "solving system..." << endl; + + solve_system(therm_dof_system, therm_nonlinear_system); + + therm_dof_system.nodal_constraints.distribute(therm_nonlinear_system.Newton_step_solution); + TrilinosWrappers::MPI::Vector full_step_increment(therm_nonlinear_system.current_increment); + + TrilinosWrappers::MPI::Vector temp_locally_owned_increment(therm_dof_system.locally_owned_dofs); + + + pcout << "doing line search..." << endl; + for (unsigned int i = 0; i < (NewtonStep > 0 ? 6 : 1); ++i) { + const Number alpha = std::pow(0.5, static_cast(i)); + + mech_nonlinear_system.current_increment.compress(VectorOperation::insert); + + temp_locally_owned_increment = full_step_increment; + temp_locally_owned_increment.sadd(1, -alpha, therm_nonlinear_system.Newton_step_solution); + therm_dof_system.nodal_constraints.distribute(temp_locally_owned_increment); + temp_locally_owned_increment.compress(VectorOperation::insert); + therm_nonlinear_system.current_increment = temp_locally_owned_increment; + therm_nonlinear_system.current_increment.compress(VectorOperation::insert); + + assemble_thermal_system( + therm_nonlinear_system, + mech_nonlinear_system, + therm_dof_system, + therm_lbc_system, + mech_dof_system, + mixed_fe_dof_system, + material, + mixed_FE_projectors, + material_area_factors, + false); + + total_therm_residual = therm_nonlinear_system.Newton_step_residual; + total_therm_residual.compress(VectorOperation::insert); + + const Number current_residual = total_therm_residual.norm_sqr(); + if (current_residual < old_residual) + break; + } + } + pcout << endl; + } + + + template + void PlasticityLabProg::solve_mesh_motion_step( + NewtonStepSystem &mesh_motion_nonlinear_system, + const DoFSystem &mesh_motion_dof_system, + const LBCSystem &mesh_motion_lbc_system, + const NewtonStepSystem &deformation_nonlinear_system, + const DoFSystem &deformation_dof_system, + const DoFSystem &mixed_fe_dof_system, + const std::vector< MixedFEProjector > &mixed_fe_projector, + const int time_step) { + + TrilinosWrappers::MPI::Vector total_residual; + + for (unsigned int NewtonStep = 0; true; NewtonStep++) { + + pcout << "\n\ttime step " << time_step + << ", Newton step " << NewtonStep << "..." + << "\n\t\tassembling mesh motion system with tangents..." << endl; + + assemble_mesh_motion_system( + mesh_motion_nonlinear_system, + mesh_motion_dof_system, + mesh_motion_lbc_system, + deformation_nonlinear_system, + deformation_dof_system, + mixed_fe_dof_system, + mixed_fe_projector, + true); + + total_residual = mesh_motion_nonlinear_system.Newton_step_residual; + total_residual.compress(VectorOperation::insert); + + pcout << "-------------------------------------------------------------------" << endl; + + pcout << "Normalized system residual: " + << std::sqrt(total_residual.norm_sqr()) + << " ..." << endl; + pcout << "-------------------------------------------------------------------" << endl; + + if (std::sqrt(total_residual.norm_sqr()) <= 1e-4) { + break; + } + + const Number old_residual = total_residual.norm_sqr(); + Number previous_residual = old_residual; + + pcout << "solving system..." << endl; + try { + solve_system(mesh_motion_dof_system, mesh_motion_nonlinear_system); + } catch (...) { + if (std::isnan(mesh_motion_nonlinear_system.Newton_step_solution.norm_sqr())) { + throw; + } + pcout << "System solution falied. Continuing with partial solution..." << endl; + } + mesh_motion_dof_system.nodal_constraints.distribute(mesh_motion_nonlinear_system.Newton_step_solution); + const Number solution_norm = std::sqrt(mesh_motion_nonlinear_system.Newton_step_solution.norm_sqr()); + TrilinosWrappers::MPI::Vector full_step_increment(mesh_motion_nonlinear_system.current_increment); + TrilinosWrappers::MPI::Vector temp_locally_owned_increment(mesh_motion_dof_system.locally_owned_dofs); + + Number clip_factor = + (solution_norm <= std::sqrt(old_residual)) ? 1.0 : sqrt(old_residual) / solution_norm; + if (clip_factor < 1.0) pcout << "clip factor: " << clip_factor << endl; + + pcout << "doing line search..." << endl; + bool hit_line_search_limit = false; + for (unsigned int i = 0; true/*i < 18*/; ++i) { + const Number alpha = std::pow(0.5, static_cast(i)); + if (i > 5 && clip_factor * alpha * solution_norm < 1e-1) { + hit_line_search_limit = true; + break; + } + if (i > 0) pcout << "\tline search step " << i << "..." << endl; + + while (true) { + temp_locally_owned_increment = full_step_increment; + temp_locally_owned_increment.sadd(1, -alpha * clip_factor, mesh_motion_nonlinear_system.Newton_step_solution); + temp_locally_owned_increment.compress(VectorOperation::insert); + mesh_motion_nonlinear_system.current_increment = temp_locally_owned_increment; + mesh_motion_nonlinear_system.current_increment.compress(VectorOperation::insert); + + try { + assemble_mesh_motion_system( + mesh_motion_nonlinear_system, + mesh_motion_dof_system, + mesh_motion_lbc_system, + deformation_nonlinear_system, + deformation_dof_system, + mixed_fe_dof_system, + mixed_fe_projector, + false); + } catch (const std::runtime_error &) { + clip_factor *= 0.125; // using a power of 0.5; better for binary arithmetic + pcout << "\t-------------------------------------------------------------------" << endl; + pcout << "\tDeformation too large, causing degenerate mesh..." << endl; + pcout << "\tupdated clip factor: " << clip_factor << endl; + pcout << "\t-------------------------------------------------------------------" << endl; + continue; + } + break; + } + + total_residual = mesh_motion_nonlinear_system.Newton_step_residual; + total_residual.compress(VectorOperation::insert); + + const Number current_residual = total_residual.norm_sqr(); + + pcout << "\t-------------------------------------------------------------------" << endl; + + pcout << "\tNormalized system residual: " + << std::sqrt(current_residual) + << " ..." << endl; + pcout << "\t-------------------------------------------------------------------" << endl; + + if (previous_residual < old_residual and current_residual >= previous_residual) { + pcout << "\t---Accepting previous residual: " << std::sqrt(previous_residual) + << " ..." << endl; + + temp_locally_owned_increment = full_step_increment; + temp_locally_owned_increment.sadd(1, -2 * alpha * clip_factor, mesh_motion_nonlinear_system.Newton_step_solution); + temp_locally_owned_increment.compress(VectorOperation::insert); + mesh_motion_nonlinear_system.current_increment = temp_locally_owned_increment; + mesh_motion_nonlinear_system.current_increment.compress(VectorOperation::insert); + break; + } + previous_residual = current_residual; + } + } + } + + + template + struct RefiningTransform + { + RefiningTransform( + double height, + double refining_fraction, + double base=0, + size_t dimension=1) : + height(height), + refining_fraction(refining_fraction), + base(base), + dimension(dimension) {} + + Point operator()(const Point &p) const + { + Point q = p; + if ((p[dimension]-base)/(height-base) <= 0.5) { + q[dimension] = base + refining_fraction/0.5 * (p[dimension]-base); + } else if ((p[dimension]-base)/(height-base) > 0.5) { + q[dimension] = base + refining_fraction * (height - base) + (1.0 - refining_fraction) / 0.5 * (p[dimension] - 0.5 * (height + base)); + } + return q; + } + + double height; + double refining_fraction; + double base; + size_t dimension; + }; + + + template + void PlasticityLabProg::set_mesh_motion_LBCs( + Triangulation &triangulation, + LBCSystem &mesh_motion_lbc_system) { + + std::set all_boundary_ids; + for(types::boundary_id id: triangulation.get_boundary_ids()) { + all_boundary_ids.insert(id); + } + + mesh_motion_lbc_system.no_normal_flux_constraints.push_back(std::make_pair(0, all_boundary_ids)); + } + + + template + void PlasticityLabProg::make_cylindrical_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements) { + + const Number initial_velocity = 1.9e5; // [mm/s] + const Number height = 2.5*25.4; // [mm] + const Number inner_radius = 12.5; // [mm] + const Number radius = 12.5; // [mm] + + const Number top_coordinate = height/2; + const Number base_coordinate = 0.0; + + const unsigned int base_repetitions = std::pow(2, n_initial_global_refinements); + const unsigned int aspect_ratio = std::ceil(0.25 * height / radius); + + GridGenerator::subdivided_hyper_rectangle( + triangulation, + std::vector {base_repetitions, aspect_ratio * base_repetitions}, + Point(inner_radius, base_coordinate), + Point(inner_radius + radius, top_coordinate), + true + ); + + for (auto &cell: triangulation.active_cell_iterators()) { + for (const auto &face : cell->face_iterators()) { + if(face->boundary_id() == 0 || face->boundary_id() == 1) { + if(face->center()[1] > 0.95 * height/2) { + face->set_boundary_id(4); + } + } + } + } + + // GridTools::transform(RefiningTransform(top_coordinate, 0.3, base_coordinate), triangulation); + // GridTools::transform(RefiningTransform(top_coordinate, 0.4, base_coordinate), triangulation); + // GridTools::transform(RefiningTransform/(inner_radius, 0.35, inner_radius + radius, 0), triangulation); + + // for(unsigned int i=0; i<2; i++) { + // for (auto &cell : triangulation.active_cell_iterators()) { + // for (const auto &face : cell->face_iterators()) { + // if (face->boundary_id() == 2) { + // cell->set_refine_flag(); + // break; + // } + // } + // } + // triangulation.execute_coarsening_and_refinement(); + // } + + ComponentMask x_component_mask(dim+1, false); + x_component_mask.set(0, true); + ComponentMask y_component_mask(dim+1, false); + y_component_mask.set(1, true); + ComponentMask x_and_y_component_mask(dim+1, false); + x_and_y_component_mask.set(0, true); + x_and_y_component_mask.set(1, true); + ComponentMask z_component_mask(dim+1, false); + z_component_mask.set(dim-1, true); + ComponentMask rho_component_mask(dim+1, false); + rho_component_mask.set(dim, true); + + // std::map< types::boundary_id, const Function< dim, Number > * > base_constraint_function_map; + // base_constraint_function_map.insert( + // std::pair*>(2, &mech_lbc_system.zero_function)); + // mech_lbc_system.interpolatoryConstraintAppliers.push_back( + // InterpolatoryConstraintApplier( + // base_constraint_function_map, + // y_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > top_constraint_function_map; + top_constraint_function_map.insert( + std::pair*>(3, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + top_constraint_function_map, + x_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > clamp_constraint_function_map; + clamp_constraint_function_map.insert( + std::pair*>(4, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + clamp_constraint_function_map, + x_component_mask)); + + if(std::abs(inner_radius) < 1e-16) { + std::map< types::boundary_id, const Function< dim, Number > * > axial_constraint_function_map; + axial_constraint_function_map.insert( + std::pair*>(0, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + axial_constraint_function_map, + x_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > axial_rotation_constraint_function_map; + axial_rotation_constraint_function_map.insert( + std::pair*>(0, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + axial_rotation_constraint_function_map, + rho_component_mask)); + } + + // therm_lbc_system.boundaryLoadAppliers.push_back( + // std::pair >( + // 2, BodyForceApplier(0, 22e0))); + + std::map< types::boundary_id, const Function< dim, Number > * > top_rotation_constraint_function_map; + top_rotation_constraint_function_map.insert( + std::pair*>(3, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + top_rotation_constraint_function_map, + rho_component_mask)); + + // std::map< types::boundary_id, const Function< dim, Number > * > base_rotation_constraint_function_map; + // base_rotation_constraint_function_map.insert( + // std::pair*>(2, &mech_lbc_system.zero_function)); + // mech_lbc_system.interpolatoryConstraintAppliers.push_back( + // InterpolatoryConstraintApplier( + // base_rotation_constraint_function_map, + // rho_component_mask)); + + // Thermal constraints + const Number convection_coefficient = /*17.5e-6*/ 100e-6; // [J.mm^-2.s^-1.K^-1] + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 0, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 1, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 2, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 3, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + + // therm_lbc_system.convection_BC_appliers.push_back( + // std::pair >( + // 2, + // ConvectionBoundaryConditionApplier( + // 0, 3000*convection_coefficient, 1350.0 /*a little less than melting*/))); + + // const Number total_elongation = 2 * 80.0; // mm + // const Number elongation_rate = time_since_start < 6.0? 0.05 : 1.75; // [mm/s] + // const unsigned int n_steps = ceil(total_elongation/(elongation_rate*time_increment)); + // auto scale_z_handler = new IncrementInterpolationHandler( + // new ConstantFunction({0, -total_elongation/(static_cast(n_steps)/**height*/), 0}), + // true, + // y_component_mask, + // false, + // ComponentMask(dim+1, false), + // 3, + // mapping); + + // mech_lbc_system.increment_interpolation_handlers.push_back(scale_z_handler); + + mech_lbc_system.boundaryLoadAppliers.push_back( + std::pair >( + 3, BodyForceApplier(dim-1, -40))); + + auto top_surface_unidirectional_penalty_spec = new BoundaryUnidirectionalPenaltySpec(3, 1e-2, 0, 1e4 / (time_increment * time_increment) ); + mech_lbc_system.boundary_unidirectional_penalty_specs.push_back(top_surface_unidirectional_penalty_spec); + + // auto constant_velocity_handler = new IncrementInterpolationHandler( + // new ScaleZFunction(-total_elongation/(static_cast(n_steps)*time_increment/**height*/), dim-1), + // true, + // y_component_mask, + // false, + // ComponentMask(dim+1, false), + // 0, + // mapping); + // mech_lbc_system.initial_velocity_interpolation_handlers.push_back(constant_velocity_handler); + // std::map< types::boundary_id, const Function< dim, Number > * > top_constraint_function_map; + // top_constraint_function_map.insert( + // std::pair*>(3, &mech_lbc_system.zero_function)); + // mech_lbc_system.interpolatoryConstraintAppliers.push_back( + // InterpolatoryConstraintApplier( + // top_constraint_function_map, + // y_component_mask)); + + const Number drive_speed = 0.8*314.159/3.0; // [rad/s] + + auto scale_rotation_increment = new IncrementInterpolationHandler( + new ScaleComponentFunction(drive_speed * time_increment, 0, dim), + true, + rho_component_mask, + false, + ComponentMask(dim+1, false), + 3, + mapping); + mech_lbc_system.increment_interpolation_handlers.push_back(scale_rotation_increment); + + auto constant_angular_velocity_handler = new IncrementInterpolationHandler( + new ScaleComponentFunction(drive_speed, 0, dim), + true, + rho_component_mask, + false, + ComponentMask(dim+1, false), + 3, + mapping); + mech_lbc_system.initial_velocity_interpolation_handlers.push_back(constant_angular_velocity_handler); + + // mech_lbc_system.boundaryLoadAppliers.push_back( + // std::pair >( + // 1, BodyForceApplier(dim, 3.750e0))); + + } /* make_cylindrical_grid() */ + + + template + void PlasticityLabProg::make_grid_() { + + } /*make_grid_()*/ + +template +struct InterferenceTaperTransform +{ + Point operator()(const Point &p) const + { + Point q = p; + if (p[0]>=35 && p[0]<=300 && p[1]<=0 && p[1]>=-150) + { + q[0] += 5 * ((p[1] + 150) / 150) * ((p[0]-300) / (35-300)); + } + return q; + } +}; + +template +struct NeckingTaperTransform +{ + double factor; + NeckingTaperTransform(double factor) : factor(factor) {} + + Point operator()(const Point &p) const + { + Point q = p; + q[0] += factor * q[0] * q[1]; + return q; + } +}; + + + template + void PlasticityLabProg::make_necking_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements) { + + const Number height = 53.334; // [mm] + const Number radius = 6.413; // [mm] + + const Number top_coordinate = height/2; + const Number base_coordinate = 0.0; + const unsigned int base_repetitions = std::pow(2, n_initial_global_refinements); + const unsigned int aspect_ratio = std::ceil(0.5 * height / radius); + + GridGenerator::subdivided_hyper_rectangle( + triangulation, + std::vector {base_repetitions, aspect_ratio * base_repetitions}, + Point(0, base_coordinate), + Point(radius, top_coordinate), + true + ); + + // GridTools::transform(RefiningTransform(top_coordinate, 0.15, base_coordinate), triangulation); + + ComponentMask x_component_mask(dim+1, false); + x_component_mask.set(0, true); + ComponentMask y_component_mask(dim+1, false); + y_component_mask.set(1, true); + ComponentMask z_component_mask(dim+1, false); + z_component_mask.set(dim-1, true); + ComponentMask rho_component_mask(dim+1, false); + rho_component_mask.set(dim, true); + + std::map< types::boundary_id, const Function< dim, Number > * > base_constraint_function_map; + base_constraint_function_map.insert( + std::pair*>(2, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + base_constraint_function_map, + y_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > top_constraint_function_map; + top_constraint_function_map.insert( + std::pair*>(3, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + top_constraint_function_map, + y_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > yz_constraint_function_map; + yz_constraint_function_map.insert( + std::pair*>(0, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + yz_constraint_function_map, + x_component_mask)); + + + const Number total_elongation = 2*8.0; // mm + const Number elongation_rate = 2*1.0; // [mm/s] + const unsigned int n_steps = ceil(total_elongation/(elongation_rate*time_increment)); + + auto scale_z_handler = new IncrementInterpolationHandler( + new ScaleZFunction(total_elongation/(static_cast(n_steps)*height), dim-1), + true, + y_component_mask, + false, + ComponentMask(dim+1, false), + 0, + mapping); + + mech_lbc_system.increment_interpolation_handlers.push_back(scale_z_handler); + + std::map< types::boundary_id, const Function< dim, Number > * > top_rotation_constraint_function_map; + top_rotation_constraint_function_map.insert( + std::pair*>(3, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + top_rotation_constraint_function_map, + rho_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > axial_rotation_constraint_function_map; + axial_rotation_constraint_function_map.insert( + std::pair*>(0, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + axial_rotation_constraint_function_map, + rho_component_mask)); + + // Thermal constraints + const Number convection_coefficient = 17.5e-6; // [J.mm^-2.s^-1.K^-1] + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 1, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 3, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + } /* make_necking_grid() */ + + + template + void PlasticityLabProg::make_interference_cylinder_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements) { + + const Number height = 300.0; // [mm] + const Number radius = 40.0; // [mm] + + const unsigned int base_repetitions = std::pow(2, n_initial_global_refinements); + const unsigned int aspect_ratio = std::ceil(0.5 * height / radius); + + GridGenerator::subdivided_hyper_rectangle( + triangulation, + std::vector {base_repetitions, aspect_ratio * base_repetitions}, + Point(0, 0), + Point(radius, height), + true + ); + + // mech_lbc_system.boundaryLoadAppliers.push_back( + // std::pair >( + // 1, BodyForceApplier(dim, 0.8*4.50e1))); + + ComponentMask x_component_mask(dim+1, false); + x_component_mask.set(0, true); + ComponentMask y_component_mask(dim+1, false); + y_component_mask.set(1, true); + ComponentMask z_component_mask(dim+1, false); + z_component_mask.set(dim-1, true); + ComponentMask rho_component_mask(dim+1, false); + rho_component_mask.set(dim, true); + + std::map< types::boundary_id, const Function< dim, Number > * > top_constraint_function_map; + top_constraint_function_map.insert( + std::pair*>(3, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + top_constraint_function_map, + y_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > yz_constraint_function_map; + yz_constraint_function_map.insert( + std::pair*>(0, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + yz_constraint_function_map, + x_component_mask)); + + + const Number total_elongation = 300.0; // mm + const Number elongation_rate = 1.0; // [mm/s] + const unsigned int n_steps = ceil(total_elongation/(elongation_rate*time_increment)); + + auto push_z_handler = new IncrementInterpolationHandler( + new ConstantFunction(std::vector< Number >{0, -total_elongation/static_cast(n_steps), 0}), + true, + y_component_mask, + false, + ComponentMask(dim+1, false), + 0, + mapping); + + mech_lbc_system.increment_interpolation_handlers.push_back(push_z_handler); + + std::map< types::boundary_id, const Function< dim, Number > * > top_rotation_constraint_function_map; + top_rotation_constraint_function_map.insert( + std::pair*>(3, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + top_rotation_constraint_function_map, + rho_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > axial_rotation_constraint_function_map; + axial_rotation_constraint_function_map.insert( + std::pair*>(0, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + axial_rotation_constraint_function_map, + rho_component_mask)); + + const Number drive_speed = 0.2; // [rad/s] + + auto scale_rotation_increment = new IncrementInterpolationHandler( + new ScaleComponentFunction(drive_speed * time_increment, 0, dim), + true, + rho_component_mask, + false, + ComponentMask(dim+1, false), + 3, + mapping); + mech_lbc_system.increment_interpolation_handlers.push_back(scale_rotation_increment); + auto constant_angular_velocity_handler = new IncrementInterpolationHandler( + new ScaleComponentFunction(drive_speed, 0, dim), + true, + rho_component_mask, + false, + ComponentMask(dim+1, false), + 3, + mapping); + mech_lbc_system.initial_velocity_interpolation_handlers.push_back(constant_angular_velocity_handler); + + // auto constant_velocity_angular_handler = new IncrementInterpolationHandler( + // new ScaleComponentFunction(0.0e-3, 0, dim), + // true, + // rho_component_mask, + // false, + // ComponentMask(dim+1, false), + // 0, + // mapping); + + // mech_lbc_system.initial_deformation_interpolation_handlers.push_back(constant_velocity_angular_handler); + + // Thermal constraints + const Number convection_coefficient = 17.5e-6; // [J.mm^-2.s^-1.K^-1] + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 1, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 2, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 3, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + +// std::map< types::boundary_id, const Function< dim, Number > * > thermal_constraint_function_map; +// thermal_constraint_function_map.insert( +// std::pair*>(1, &therm_lbc_system.zero_function)); +// thermal_constraint_function_map.insert( +// std::pair*>(8, &therm_lbc_system.zero_function)); +// therm_dof_system.interpolatoryConstraintAppliers.push_back( +// InterpolatoryConstraintApplier( +// thermal_constraint_function_map,ComponentMask(1, true))); + } /* make_interference_cylinder_grid() */ + + + template + void PlasticityLabProg::make_ball_in_hypershell_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements) { + + const unsigned int INNER_BOUNDARY_ID = 0; + + const Number outer_radius = 60.0; // [mm] + + GridGenerator::half_hyper_ball( + triangulation, + Point(0, -10), + outer_radius + ); + + for (const auto &cell : triangulation.active_cell_iterators()) { + cell->set_boundary_id(INNER_BOUNDARY_ID); + } + + triangulation.refine_global(n_initial_global_refinements); + + mech_lbc_system.boundaryLoadAppliers.push_back( + std::pair >( + 1, BodyForceApplier(dim, 0.8*4.50e1))); + + ComponentMask x_component_mask(dim+1, false); + x_component_mask.set(0, true); + ComponentMask y_component_mask(dim+1, false); + y_component_mask.set(1, true); + ComponentMask z_component_mask(dim+1, false); + z_component_mask.set(dim-1, true); + ComponentMask rho_component_mask(dim+1, false); + rho_component_mask.set(dim, true); + ComponentMask all_component_mask(dim+1, true); + + std::map< types::boundary_id, const Function< dim, Number > * > yz_constraint_function_map; + yz_constraint_function_map.insert( + std::pair*>(1, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + yz_constraint_function_map, + x_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > down_constraint_function_map; + down_constraint_function_map.insert( + std::pair*>(INNER_BOUNDARY_ID, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + down_constraint_function_map, + y_component_mask)); + + const Number total_elongation = 300.0; // mm + const Number elongation_rate = 225.0e-2; // [mm/s] + const unsigned int n_steps = ceil(total_elongation/(elongation_rate*time_increment)); + + auto push_z_handler = new IncrementInterpolationHandler( + new ConstantFunction(std::vector< Number >{0, -total_elongation/static_cast(n_steps), 0}), + true, + y_component_mask, + false, + ComponentMask(dim+1, false), + INNER_BOUNDARY_ID, + mapping); + + mech_lbc_system.increment_interpolation_handlers.push_back(push_z_handler); + + std::map< types::boundary_id, const Function< dim, Number > * > top_rotation_constraint_function_map; + top_rotation_constraint_function_map.insert( + std::pair*>(0, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + top_rotation_constraint_function_map, + rho_component_mask)); + + // Thermal constraints + const Number convection_coefficient = 17.5e-6; // [J.mm^-2.s^-1.K^-1] + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 1, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 2, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 3, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + } /* make_ball_in_hypershell_grid() */ + + + + + + template + void PlasticityLabProg::make_cylindrical_impact_grid( + Triangulation &triangulation, + LBCSystem &mech_lbc_system, + LBCSystem &therm_lbc_system, + int n_initial_global_refinements) { + + const Number initial_velocity = 1.9e5; // [mm/s] + const Number height = 25.4; // [mm] + const Number radius = 3.81; // [mm] + + const unsigned int base_repetitions = std::pow(2, n_initial_global_refinements); + const unsigned int aspect_ratio = std::ceil(0.25 * height / radius); + + GridGenerator::subdivided_hyper_rectangle( + triangulation, + std::vector {base_repetitions, aspect_ratio * base_repetitions}, + Point(0, 0), + Point(radius, height), + true + ); + +// mech_lbc_system.boundaryLoadAppliers.push_back( +// std::pair >( +// 6, BodyForceApplier(2, -4.50))); + + ComponentMask x_component_mask(dim, false); + x_component_mask.set(0, true); + ComponentMask y_component_mask(3, false); + y_component_mask.set(1, true); + ComponentMask z_component_mask(dim, false); + z_component_mask.set(dim-1, true); + ComponentMask rho_component_mask(dim+1, false); + rho_component_mask.set(dim, true); + + std::map< types::boundary_id, const Function< dim, Number > * > axial_constraint_function_map; + axial_constraint_function_map.insert( + std::pair*>(0, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + axial_constraint_function_map, + x_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > base_constraint_function_map; + base_constraint_function_map.insert( + std::pair*>(2, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + base_constraint_function_map, + y_component_mask)); + + auto constant_velocity_handler = new IncrementInterpolationHandler( + new ConstantFunction(std::vector< Number >{0, -initial_velocity, 0}), + true, + y_component_mask, + false, + ComponentMask(dim, false), + 0, + mapping); + + mech_lbc_system.initial_velocity_interpolation_handlers.push_back(constant_velocity_handler); + + std::map< types::boundary_id, const Function< dim, Number > * > top_rotation_constraint_function_map; + top_rotation_constraint_function_map.insert( + std::pair*>(3, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + top_rotation_constraint_function_map, + rho_component_mask)); + + std::map< types::boundary_id, const Function< dim, Number > * > axial_rotation_constraint_function_map; + axial_rotation_constraint_function_map.insert( + std::pair*>(0, &mech_lbc_system.zero_function)); + mech_lbc_system.interpolatoryConstraintAppliers.push_back( + InterpolatoryConstraintApplier( + axial_rotation_constraint_function_map, + rho_component_mask)); + + auto constant_velocity_angular_handler = new IncrementInterpolationHandler( + new ScaleComponentFunction(0.0e2, 0, dim), + true, + rho_component_mask, + false, + ComponentMask(dim+1, false), + 0, + mapping); + + mech_lbc_system.initial_deformation_interpolation_handlers.push_back(constant_velocity_angular_handler); + + // Thermal constraints + const Number convection_coefficient = 17.5e-6; // [J.mm^-2.s^-1.K^-1] + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 1, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + therm_lbc_system.convection_BC_appliers.push_back( + std::pair >( + 3, + ConvectionBoundaryConditionApplier( + 0, convection_coefficient, ambient_temperature))); + +// std::map< types::boundary_id, const Function< dim, Number > * > thermal_constraint_function_map; +// thermal_constraint_function_map.insert( +// std::pair*>(1, &therm_lbc_system.zero_function)); +// thermal_constraint_function_map.insert( +// std::pair*>(8, &therm_lbc_system.zero_function)); +// therm_dof_system.interpolatoryConstraintAppliers.push_back( +// InterpolatoryConstraintApplier( +// thermal_constraint_function_map,ComponentMask(1, true))); + + } /* make_cylindrical_impact_grid() */ + + + template + void PlasticityLabProg::make_hook_membrane_grid( + int /*n_initial_global_refinements*/) { + + } /* make_necking_grid() */ + + + + template + Tensor<2, dim+1, Number> PlasticityLabProg::get_rotation_tensor( + const Tensor<2, dim+1, Number> &skew_symmetric_rotation) const { + const Number theta = Constants::sqrt_half() * skew_symmetric_rotation.norm(); + if (theta > 1e-8) { + const Number h1 = (1./(theta*theta)*(1.-std::cos(theta))); + const Number h2 = (1./theta*std::sin(theta)); + return static_cast>(unit_symmetric_tensor()) + + h1 * skew_symmetric_rotation * skew_symmetric_rotation + + h2 * skew_symmetric_rotation; + } else { + return static_cast>(unit_symmetric_tensor()); + } + } + + + template + Tensor<2, dim+1, Number> PlasticityLabProg::get_rotation_tensor_variation( + const Tensor<2, dim+1, Number> &skew_symmetric_rotation, + const Tensor<2, dim+1, Number> &skew_symmetric_rotation_variation) const { + + const Number theta = Constants::sqrt_half() * skew_symmetric_rotation.norm(); + if (theta > 1e-8) { + const Number h1 = (1./(theta*theta)*(1.-std::cos(theta))); + const Number h2 = (1./theta*std::sin(theta)); + const Number delta_theta = 1./(2.*theta) * scalar_product(skew_symmetric_rotation, skew_symmetric_rotation_variation); + const Number delta_h1 = (-2./theta * (h1 - 0.5 * h2)) * delta_theta; + const Number delta_h2 = (-1./theta * h2 + 1./theta * std::cos(theta)) * delta_theta; + const Tensor<2, dim+1, Number> rotation_tensor_variation = delta_h1 * skew_symmetric_rotation * skew_symmetric_rotation + + h1 * skew_symmetric_rotation_variation * skew_symmetric_rotation + + h1 * skew_symmetric_rotation * skew_symmetric_rotation_variation + + delta_h2 * skew_symmetric_rotation + + h2 * skew_symmetric_rotation_variation; + return rotation_tensor_variation; + } else { + return Tensor<2, dim+1, Number>(); + } + } + +} + diff --git a/ALE_Finite_Strain_Plasticity/src/PointHistory.h b/ALE_Finite_Strain_Plasticity/src/PointHistory.h new file mode 100644 index 00000000..885de8a9 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/PointHistory.h @@ -0,0 +1,79 @@ +/* + * PointHistory.h + * + * Created on: 21 Jul 2014 + * Author: cerecam + */ + +#ifndef POINTHISTORY_H_ +#define POINTHISTORY_H_ + +#include +#include + +#include +#include +#include + +#include + +namespace PlasticityLab { + + template + class PointHistory { + public: + PointHistory(); + virtual ~PointHistory(); + + struct HardeningParameters { + HardeningParameters( + Number equivalent_plastic_strain, + dealii::SymmetricTensor<2, dim, Number> kinematic_hardening): + equivalent_plastic_strain(equivalent_plastic_strain), + kinematic_hardening(kinematic_hardening) { } + HardeningParameters() {} + + Number equivalent_plastic_strain; + dealii::SymmetricTensor<2, dim, Number> kinematic_hardening; + }; + + PointHistory(const dealii::SymmetricTensor<2, dim, Number> &, + const HardeningParameters &, + Number plastic_entropy, + Number material_Jacobian); + + dealii::SymmetricTensor<2, dim, Number> plastic_strain; + HardeningParameters hardening_parameters; + Number plastic_entropy; + Number material_Jacobian; + }; + + + template + PointHistory::PointHistory() + : + plastic_strain (dealii::unit_symmetric_tensor()), + hardening_parameters(Number(0.0), Number(0.0) * dealii::unit_symmetric_tensor()), + plastic_entropy(Number(0.0)), + material_Jacobian(1.0) { + } + + template + PointHistory:: + PointHistory(const dealii::SymmetricTensor<2, dim, Number> &plastic_strain, + const HardeningParameters &hardening_parameters, + const Number plastic_entropy, + const Number material_Jacobian): + plastic_strain(plastic_strain), + hardening_parameters(hardening_parameters), + plastic_entropy(plastic_entropy), + material_Jacobian(material_Jacobian) { + } + + template + PointHistory::~PointHistory() { + } + +} /* namespace PlasticityLab */ + +#endif /* POINTHISTORY_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/ReferencePoint.h b/ALE_Finite_Strain_Plasticity/src/ReferencePoint.h new file mode 100644 index 00000000..dc27fcfb --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ReferencePoint.h @@ -0,0 +1,40 @@ +/* + * ReferencePoint.h + * + * Created on: 29 Nov 2020 + * Author: maien + */ + +#ifndef REFERENCEPOINT_H_ +#define REFERENCEPOINT_H_ + +#include +#include +#include + +using namespace dealii; + +namespace PlasticityLab { + template + class ReferencePoint { + public: + ReferencePoint(); + virtual ~ReferencePoint(); + + typename DoFHandler::active_cell_iterator mesh_motion_cell; + typename DoFHandler::active_cell_iterator field_cell; + unsigned int q_point; + Point reference_point; + Point remapped_point; + }; + + template + ReferencePoint::ReferencePoint() { + } + + template + ReferencePoint::~ReferencePoint() {} + +} /* namespace PlasticityLab */ + +#endif /* REFERENCEPOINT_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/RemappedPoint.h b/ALE_Finite_Strain_Plasticity/src/RemappedPoint.h new file mode 100644 index 00000000..b95b186b --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/RemappedPoint.h @@ -0,0 +1,40 @@ +/* + * RemappedPoint.h + * + * Created on: 29 Nov 2020 + * Author: maien + */ + +#ifndef REMAPPEDPOINT_H_ +#define REMAPPEDPOINT_H_ + +#include +#include +#include + +using namespace dealii; + +namespace PlasticityLab { + template + class RemappedPoint { + public: + RemappedPoint(); + virtual ~RemappedPoint(); + + typename DoFHandler::active_cell_iterator mesh_motion_cell; + typename DoFHandler::active_cell_iterator field_cell; + typename DoFHandler::active_cell_iterator mixed_fe_cell; + Point unit_cell_point; + Point remapped_point; + }; + + template + RemappedPoint::RemappedPoint() { + } + + template + RemappedPoint::~RemappedPoint() {} + +} /* namespace PlasticityLab */ + +#endif /* REMAPPEDPOINT_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/RotationFunction.h b/ALE_Finite_Strain_Plasticity/src/RotationFunction.h new file mode 100644 index 00000000..f83b8640 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/RotationFunction.h @@ -0,0 +1,107 @@ +/* + * RotationFunction.h + * + * Created on: 06 Dec 2016 + * Author: maien + */ + +#ifndef ROTATIONFUNCTION_H_ +#define ROTATIONFUNCTION_H_ + +#include +#include +#include + +using namespace dealii; + +namespace PlasticityLab { + + template + class RotationFunction: public Function { + public: + RotationFunction( + const Number angular_frequency, + const Number axial_velocity, + const Number current_angle = 0.0); + virtual ~RotationFunction(); + + virtual void vector_value (const Point< dim > &p, Vector< Number > &values) const; + virtual void set_time (const Number new_time); + + private: + void update_rotation_matrix(); + Tensor<2, dim, Number> previousRotationMatrix, currentRotationMatrix; + Number current_angle; + Number previous_displacement, current_displacement; + Number angular_frequency; + Number axial_velocity; + }; + + template + class AngularVelocityFunction: public Function { + public: + AngularVelocityFunction(const Number angular_frequency) : Function(dim) { + this->angular_frequency = angular_frequency; + } + virtual ~AngularVelocityFunction() {} + + virtual void vector_value (const Point< dim > &p, Vector< Number > &values) const { + values[0] = - 2 * 3.14159 * angular_frequency * p[1]; + values[1] = 2 * 3.14159 * angular_frequency * p[0]; + if(3==dim) { + values[2] = 0; + } + } + + private: + Number angular_frequency; + }; + + template + RotationFunction::~RotationFunction() {} + + template + RotationFunction::RotationFunction( + const Number angular_frequency, + const Number axial_velocity, + const Number current_angle) : Function(dim) { + this->angular_frequency = angular_frequency; + this->axial_velocity = axial_velocity; + this->current_angle = current_angle; + this->set_time(0.0); + current_displacement = 0.0; + } + + template + void RotationFunction::vector_value (const Point< dim > &p, Vector< Number > &values) const { + const auto p_prev = previousRotationMatrix * p; + const auto res = currentRotationMatrix * p; + for (unsigned int i = 0; i < dim; ++i) + values[i] = res[i] - p_prev[i] + (i == 2 ? current_displacement - previous_displacement : 0.0); + } + + template + void RotationFunction::update_rotation_matrix () { + previousRotationMatrix = currentRotationMatrix; + const Number c_theta = std::cos(current_angle); + const Number s_theta = std::sin(current_angle); + currentRotationMatrix[0][0] = c_theta; + currentRotationMatrix[0][1] = -s_theta; + currentRotationMatrix[1][0] = s_theta; + currentRotationMatrix[1][1] = c_theta; + if (dim == 3) + currentRotationMatrix[2][2] = 1.0; + } + + template + void RotationFunction::set_time (const Number new_time) { + Function::set_time(new_time); + current_angle = angular_frequency * Function::get_time(); + update_rotation_matrix(); + previous_displacement = current_displacement; + current_displacement = axial_velocity * Function::get_time(); + } + +} /* namespace PlasticityLab */ + +#endif /* ROTATIONFUNCTION_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/ScaleComponentFunction.h b/ALE_Finite_Strain_Plasticity/src/ScaleComponentFunction.h new file mode 100644 index 00000000..b5c32034 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ScaleComponentFunction.h @@ -0,0 +1,56 @@ +/* + * ScaleComponentFunction.h + * + * Created on: 28 Dec 2019 + * Author: maien + */ + +#ifndef SCALECOMPONENTFUNCTION_H_ +#define SCALECOMPONENTFUNCTION_H_ + +#include +#include +#include + +using namespace dealii; + +namespace PlasticityLab { + + template + class ScaleComponentFunction: public Function { + public: + ScaleComponentFunction( + const Number scale_factor, + const unsigned int in_component=2, + const unsigned int out_component=2); + virtual ~ScaleComponentFunction(); + virtual void vector_value(const Point &p, Vector &values) const; + + private: + Number scale_factor; + const unsigned int in_component; + const unsigned int out_component; + }; + + template + ScaleComponentFunction::ScaleComponentFunction( + const Number scale_factor, + const unsigned int in_component, + const unsigned int out_component) : + Function(components), + in_component(in_component), + out_component(out_component), + scale_factor(scale_factor) { } + + template + ScaleComponentFunction::~ScaleComponentFunction() {} + + template + void ScaleComponentFunction::vector_value(const Point &p, Vector &values) const { + values *= 0.0; + values[out_component] = scale_factor * p[in_component]; + } + +} /* namespace PlasticityLab */ + +#endif /* SCALECOMPONENTFUNCTION_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/ScaleZFunction.h b/ALE_Finite_Strain_Plasticity/src/ScaleZFunction.h new file mode 100644 index 00000000..3041cbc7 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ScaleZFunction.h @@ -0,0 +1,51 @@ +/* + * ScaleZFunction.h + * + * Created on: 06 Dec 2016 + * Author: maien + */ + +#ifndef SCALEZFUNCTION_H_ +#define SCALEZFUNCTION_H_ + +#include +#include +#include + +using namespace dealii; + +namespace PlasticityLab { + + template + class ScaleZFunction: public Function { + public: + ScaleZFunction(const Number scale_factor, const unsigned int component=2); + virtual ~ScaleZFunction(); + virtual void vector_value(const Point &p, Vector &values) const; + + private: + Number scale_factor; + const unsigned int component; + }; + + template + ScaleZFunction::ScaleZFunction( + const Number scale_factor, + const unsigned int component) : + Function(components), + component(component) { + this->scale_factor = scale_factor; + } + + template + ScaleZFunction::~ScaleZFunction() {} + + template + void ScaleZFunction::vector_value(const Point &p, Vector &values) const { + values *= 0.0; + values[component] = scale_factor * p[component]; + } + +} /* namespace PlasticityLab */ + +#endif /* SCALEZFUNCTION_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/TensorUtilities.h b/ALE_Finite_Strain_Plasticity/src/TensorUtilities.h new file mode 100644 index 00000000..402c64ca --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/TensorUtilities.h @@ -0,0 +1,90 @@ +/* + * TensorUtilities.h + * + * Created on: 06 Nov 2020 + * Author: maien + */ + +#ifndef TENSOR_UTILITIES_H_ +#define TENSOR_UTILITIES_H_ + +#include + +#include +#include + + +using namespace dealii; + +namespace PlasticityLab { + template + SymmetricTensor<2, dim, Number> get_log_of_tensor( + const SymmetricTensor<2, dim, Number> &symmetric_stretch_rate) { + try{ + const auto eig_vals_vecs = eigenvectors(symmetric_stretch_rate); + SymmetricTensor<2, dim, Number> result = + std::log(eig_vals_vecs[0].first) + * symmetrize( + outer_product( + eig_vals_vecs[0].second, + eig_vals_vecs[0].second)); + for(unsigned int d=1; d + SymmetricTensor<2, dim, Number> get_log_of_tensor_variation( + const SymmetricTensor<2, dim, Number> &symmetric_stretch_rate, + const SymmetricTensor<2, dim, Number> &symmetric_stretch_rate_variation) { + const double epsilon = 1e-10; + return (1./epsilon) * (get_log_of_tensor(symmetric_stretch_rate + epsilon * symmetric_stretch_rate_variation) - get_log_of_tensor(symmetric_stretch_rate)); + } + + template + SymmetricTensor<2, dim, Number> get_exp_of_tensor( + const SymmetricTensor<2, dim, Number> &symmetric_stretch_rate) { + try{ + const auto eig_vals_vecs = eigenvectors(symmetric_stretch_rate); + SymmetricTensor<2, dim, Number> result = + std::exp(eig_vals_vecs[0].first) + * symmetrize( + outer_product( + eig_vals_vecs[0].second, + eig_vals_vecs[0].second)); + for(unsigned int d=1; d + SymmetricTensor<2, dim, Number> get_exp_of_tensor_variation( + const SymmetricTensor<2, dim, Number> &symmetric_stretch_rate, + const SymmetricTensor<2, dim, Number> &symmetric_stretch_rate_variation) { + const Number epsilon = 1e-10; + return (1./epsilon) * (get_exp_of_tensor(symmetric_stretch_rate + epsilon * symmetric_stretch_rate_variation) - get_exp_of_tensor(symmetric_stretch_rate)); + } +} + +#endif // TENSOR_UTILITIES_H_ \ No newline at end of file diff --git a/ALE_Finite_Strain_Plasticity/src/ThermoPlasticMaterial.cpp b/ALE_Finite_Strain_Plasticity/src/ThermoPlasticMaterial.cpp new file mode 100644 index 00000000..4daf35cb --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ThermoPlasticMaterial.cpp @@ -0,0 +1,486 @@ +/* + * ThermoPlasticMaterial.cpp + * + * Created on: 05 Jan 2015 + * Author: maien + */ + +#include +#include + +#include +#include + +#include "symmetric_tensor_entries.h" + +#include "ExponentialHardeningThermoviscoplasticYieldLaw.h" +#include "JohnsonCookThermoviscoplasticYieldLaw.h" + +#include "ThermoPlasticMaterial.h" +#include "Constants.h" +#include "TensorUtilities.h" + +namespace PlasticityLab { + + template + ThermoPlasticMaterial:: + ThermoPlasticMaterial( + const Number kappa, + const Number mu, + const Number thermal_expansion_coefficient, + const Number thermal_conductivity, + const Number heat_capacity, + const Number dissipation_factor, + const ViscoplasticYieldLaw &viscoplastic_yield_law) : + kappa (kappa), + mu (mu), + thermal_expansion_coefficient(thermal_expansion_coefficient), + thermal_conductivity(thermal_conductivity), + heat_capacity(heat_capacity), + reference_temperature(293.15), + dissipation_factor(dissipation_factor), + viscoplastic_yield_law(viscoplastic_yield_law) { } + + template + ThermoPlasticMaterial::~ThermoPlasticMaterial() { + } + + template + void ThermoPlasticMaterial::compute_constitutive_request( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index) { + const ConstitutiveModelUpdateFlags update_flags = constitutive_request.get_update_flags(); + + if (update_pressure & update_flags) + compute_pressure(constitutive_request, point_index); + + if ((update_stress_deviator | update_mechanical_dissipation) & update_flags) + compute_stress_deviator_and_d_gamma(constitutive_request, point_index); + + if (update_heat_flux & update_flags) + compute_heat_flux(constitutive_request, point_index); + + if (update_thermoelastic_heating & update_flags) + compute_thermo_elastic_heating(constitutive_request, point_index); + + if (update_stored_heat & update_flags) + compute_stored_heat_rate(constitutive_request, point_index); + } + + template + std::vector ThermoPlasticMaterial::get_state_parameters( + const point_index_t &point_index, + const Tensor<2, dim, Number> &reference_transformation) const { + std::vector state_parameters; + state_parameters.reserve(get_material_parameter_count()); + + const PointHistory &point_history = material_point_history.at(point_index); + state_parameters.push_back(std::log(1 + point_history.hardening_parameters.equivalent_plastic_strain)); + + const Number reference_transformation_Jacobian = determinant(reference_transformation); + const auto isochoric_reference_transformation = + std::pow(reference_transformation_Jacobian, -Constants::one_third()) * reference_transformation; + + const SymmetricTensor<2, dim, Number> log_of_b_e = + get_log_of_tensor( + symmetrize( + isochoric_reference_transformation + * static_cast>(point_history.plastic_strain) + * transpose(isochoric_reference_transformation))); + + for (const auto &element : + dealii_utils::symmetric_tensor_entries(log_of_b_e)) { + state_parameters.push_back(element); + } + + for (const auto &element : + dealii_utils::symmetric_tensor_entries( + point_history.hardening_parameters.kinematic_hardening) + ) { + state_parameters.push_back(element); + } + + state_parameters.push_back(std::log(std::pow(reference_transformation_Jacobian, 1) * point_history.material_Jacobian)); + + return state_parameters; + } + + template + size_t ThermoPlasticMaterial:: get_material_parameter_count() const { + return 1 + 2 * (dim * (dim + 1) / 2) + 1; // one scalar and two symmetric tensors and one more scalar + } + + template + void ThermoPlasticMaterial::set_state_parameters( + const point_index_t &point_index, + const std::vector &state_parameters, + const Tensor<2, dim, Number> &reference_transformation) { + PointHistory &point_history = material_point_history.at(point_index); + size_t cursor = 0; + + point_history.hardening_parameters.equivalent_plastic_strain = std::exp(state_parameters[cursor++]) - 1; + + SymmetricTensor<2, dim, Number> log_of_b_e; + + for (auto &element : + dealii_utils::symmetric_tensor_entries(log_of_b_e)) { + element = state_parameters[cursor++]; + } + + const Number reference_transformation_Jacobian = determinant(reference_transformation); + const auto inverse_isochoric_reference_transformation = + std::pow(reference_transformation_Jacobian, Constants::one_third()) * invert(reference_transformation); + + point_history.plastic_strain = symmetrize( + inverse_isochoric_reference_transformation + * static_cast>(get_exp_of_tensor(log_of_b_e)) + * transpose(inverse_isochoric_reference_transformation)); + + for (auto &element : + dealii_utils::symmetric_tensor_entries( + point_history.hardening_parameters.kinematic_hardening + )) { + element = state_parameters[cursor++]; + } + + point_history.material_Jacobian = std::pow(reference_transformation_Jacobian, -1) * std::exp(state_parameters[cursor++]); + } + + template + Number ThermoPlasticMaterial::get_material_Jacobian(const point_index_t &point_index) const { + return material_point_history.at(point_index).material_Jacobian; + } + + + template + dealii::SymmetricTensor<2, dim, Number> ThermoPlasticMaterial::get_plastic_strain(const point_index_t &point_index) const { + return material_point_history.at(point_index).plastic_strain; + } + + + + + template + void + ThermoPlasticMaterial::setup_point_history (const point_index_t point_count) { + { + std::vector< PointHistory > tmp; + tmp.swap (material_point_history); + } + const typename PointHistory::HardeningParameters hardening_parameters( + Number(0.0), + Number(0.0)*dealii::unit_symmetric_tensor()); + const PointHistory< dim, Number> point_history(unit_symmetric_tensor(), + hardening_parameters, + Number(0.0), + Number(1.0)); + material_point_history.resize (point_count, point_history); + } + + template + inline void + ThermoPlasticMaterial:: + compute_pressure(ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index) { + const Number J = constitutive_request.get_deformation_Jacobian(); + const Number temperature = constitutive_request.get_temperature(); + if (J > 0) { + const Number p = kappa * (J-1.0/J) - 3 * kappa * thermal_expansion_coefficient * (temperature - reference_temperature) * (1 + 1./(J*J)); + constitutive_request.set_pressure(p); + // pressure tangent + const Number dp = kappa * (1 + 1/(J*J)) - 3 * kappa * thermal_expansion_coefficient * (temperature - reference_temperature) * (-2 * 1./(J*J*J)); + constitutive_request.set_pressure_tangent_modulus(dp); + } else { + std::ostringstream convert; + convert << "Encountered deformation gradient with non-positive determinant! " << J; + throw MaterialDomainException(convert.str()); + } + } + + template + void ThermoPlasticMaterial::compute_stress_deviator_and_d_gamma( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index) { + const ConstitutiveModelUpdateFlags update_flags = constitutive_request.get_update_flags(); + const Tensor<2, dim, Number> b_e = material_point_history[point_index].plastic_strain; + typename PointHistory::HardeningParameters hardening_parameters = + material_point_history[point_index].hardening_parameters; + const Tensor<2, dim, Number> isochoric_deformation_gradient = constitutive_request.get_deformation_gradient(); + const Number temperature = constitutive_request.get_temperature(); + const auto b_e_bar_next = static_cast >( + symmetrize(isochoric_deformation_gradient * b_e + * transpose(isochoric_deformation_gradient))); + if(std::isnan(b_e_bar_next.norm())) { + std::cout << "b_e_bar_next is nan: " << b_e_bar_next << std::endl; + std::cout << "b_e: " << b_e << std::endl; + std::cout << "isochoric_deformation_gradient: " << isochoric_deformation_gradient << std::endl; + std::ostringstream convert; + convert << "Encountered an elastic deviatoric tensor with NaN values! "; + throw MaterialDomainException(convert.str()); + } + const auto epsilon_e_bar_next = get_log_of_tensor<>(b_e_bar_next); + const SymmetricTensor<2, dim, Number> dev_stress_trial = deviator((0.5 * mu) * epsilon_e_bar_next); + // const SymmetricTensor<2, dim, Number> dev_stress_trial = deviator((0.5 * mu) * b_e_bar_next); + const SymmetricTensor<2, dim, Number> ksi_trial = dev_stress_trial + - hardening_parameters.kinematic_hardening; + const Number norm_ksi_trial = ksi_trial.norm(); + const Number mu_bar = (0.5 * mu); + // const Number mu_bar = (0.5 * mu) * Constants::one_third() + // * trace(b_e_bar_next); + const SymmetricTensor<2, dim, Number> stress_flow_direction = ksi_trial + / norm_ksi_trial; + constitutive_request.set_b_e_bar(b_e_bar_next); + constitutive_request.set_mu((0.5 * mu)); + const Number time_increment = constitutive_request.get_time_increment(); + + const Number trial_yield_criterion = viscoplastic_yield_law.trial_yield_criterion(norm_ksi_trial, + hardening_parameters.equivalent_plastic_strain, + 0.0, + time_increment, + temperature); + + if (0 < trial_yield_criterion && constitutive_request.get_is_plastic()) { + constitutive_request.set_is_plastic(true); + Number delta_gamma, alpha_n_plus_1; + try { + determine_delta_gamma(delta_gamma, alpha_n_plus_1, norm_ksi_trial, + mu_bar, hardening_parameters.equivalent_plastic_strain, temperature, + time_increment, 1e-04, 300); + } catch(MaterialDomainException exc) { + std::cout << "isochoric_deformation_gradient: " << isochoric_deformation_gradient + << "\nb_e: " << b_e + << "\nb_e_bar_next: " << b_e_bar_next + << "\nmu_bar: " << mu_bar + << std::endl; + std::cerr << exc.what() << std::endl; + // throw exc; + } + constitutive_request.set_delta_gamma(delta_gamma); + + // 4. Update back stress, plastic strain and stress + Number K_alpha_n_plus_1, K_alpha_n, H_alpha_n_plus_1, H_alpha_n; + Number DK_alpha_n_plus_1, DH_alpha_n_plus_1; + viscoplastic_yield_law.hardening_values(H_alpha_n, + K_alpha_n, + hardening_parameters.equivalent_plastic_strain, + 0.0, + time_increment, + temperature); + const Number y_alpha = viscoplastic_yield_law.hardening_values( + H_alpha_n_plus_1, + K_alpha_n_plus_1, + alpha_n_plus_1, + delta_gamma, + time_increment, + temperature); + const Number d_y_alpha_d_alpha = viscoplastic_yield_law.hardening_alpha_derivatives( + DH_alpha_n_plus_1, + DK_alpha_n_plus_1, + alpha_n_plus_1, + delta_gamma, + time_increment, + temperature); + + if (update_stress_deviator & update_flags) { + const SymmetricTensor<2, dim, Number> stress = deviator(dev_stress_trial + - 2 * mu_bar * delta_gamma + * stress_flow_direction); + constitutive_request.set_stress_deviator(stress); + constitutive_request.set_dH(DH_alpha_n_plus_1); + constitutive_request.set_dK(DK_alpha_n_plus_1); + if (update_material_point_history & update_flags) { + material_point_history[point_index].hardening_parameters.equivalent_plastic_strain = + alpha_n_plus_1; + material_point_history[point_index].hardening_parameters.kinematic_hardening = + hardening_parameters.kinematic_hardening + + Constants::sqrt2thirds() + * (K_alpha_n_plus_1 - K_alpha_n) + * stress_flow_direction; + + // // compute one_third_I_bar_e (c.f. Simo, Miehe 1992 pp 64) + // const auto stress_over_mu = stress / (0.5 * mu); + // const Number norm_stress_over_mu = stress_over_mu.norm(); + // const Number J_e2 = 0.5 * norm_stress_over_mu * norm_stress_over_mu; + // const Number J_e3 = determinant(stress_over_mu); + // const Number q = 0.5*(1-J_e3); + // const Number sqrt_d = std::sqrt(-std::pow(Constants::one_third()*J_e2, 3) + q*q); + // const Number one_third_I_bar_e = std::pow(q + sqrt_d, Constants::one_third()) + // + std::pow(q - sqrt_d, Constants::one_third()); + + // auto b_e_bar = stress / (0.5 * mu) + // + Constants::one_third() * trace(b_e_bar_next) + // * unit_symmetric_tensor(); + auto b_e_bar = get_exp_of_tensor(stress / (0.5 * mu)); + + // correct volumetric component so that return mapping does not change volume + const Number det_b_e_bar_trial = determinant(b_e_bar_next); + Number det_plastic_strain = determinant(b_e_bar); + if(std::abs(det_plastic_strain - 1) > 1e-7) { + std::cout << "det_plastic_strain: " << det_plastic_strain << std::endl; + } + while (std::abs(det_plastic_strain-det_b_e_bar_trial) > 1e-10) { + const Number u = (det_b_e_bar_trial - det_plastic_strain) / (det_plastic_strain * trace(invert(b_e_bar))); + b_e_bar += u*unit_symmetric_tensor(); + det_plastic_strain = determinant(b_e_bar); + } + + const Tensor<2, dim, Number> inverse_isochoric_deformation_gradient = invert(isochoric_deformation_gradient); + material_point_history[point_index].plastic_strain = b_e_bar; + } + } /*if(update_stress_deviator & update_flags)*/ + if (update_mechanical_dissipation & update_flags) { + const Number time_increment = constitutive_request.get_time_increment(); + const Number mechanical_dissipation = + dissipation_factor + * Constants::sqrt2thirds() + * y_alpha * delta_gamma + / (1000. * time_increment); // [J.mm^-3.s^-1] + constitutive_request.set_mechanical_dissipation(mechanical_dissipation); + Number DH_theta, DK_theta; + const Number d_y_alpha_d_theta = + viscoplastic_yield_law.hardening_temperature_derivatives(DH_theta, DK_theta, + alpha_n_plus_1, + delta_gamma, + time_increment, + temperature); + const Number mechanical_dissipation_temperature_tangent = + dissipation_factor + * d_y_alpha_d_theta + * (Constants::sqrt2thirds() * delta_gamma + - y_alpha / (3 * mu_bar)) + / (1000. * time_increment); // [J.mm^-3.s^-3.K^-1] + constitutive_request.set_mechanical_dissipation_tangent_modulus( + mechanical_dissipation_temperature_tangent); + } /*if (update_mechanical_dissipation & updateFlags)*/ + } /*if ( trial yield criterion test )*/ + else { + constitutive_request.set_delta_gamma(0.0); + constitutive_request.set_is_plastic(false); + if (update_stress_deviator & update_flags) { + constitutive_request.set_stress_deviator(dev_stress_trial); + constitutive_request.set_dK(0.0); + constitutive_request.set_dH(0.0); + } + if (update_mechanical_dissipation & update_flags) { + constitutive_request.set_mechanical_dissipation(0.0); + constitutive_request.set_mechanical_dissipation_tangent_modulus(0.0); + } + // The following is only necessary for the elastic case when b_e is tracked instead of G_p + if (update_stress_deviator & update_flags) { + if (update_material_point_history & update_flags) { + material_point_history[point_index].plastic_strain = b_e_bar_next; + } + } + } /*else*/ + // The following is only necessary if the total Jacobian is tracked (J_c * J_m), rather than just J_m + if (update_material_point_history & update_flags) { + material_point_history.at(point_index).material_Jacobian = constitutive_request.get_unprojected_deformation_Jacobian(); + } + } /*computeStressDeviatorAndDGamma()*/ + + template + void ThermoPlasticMaterial:: + compute_heat_flux( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index) { + const Tensor<1, dim, Number> thermal_gradient = constitutive_request.get_thermal_gradient(); + constitutive_request.set_heat_flux(thermal_conductivity * thermal_gradient); + constitutive_request.set_heat_flux_tangent_moduli(thermal_conductivity * unit_symmetric_tensor()); + } + + template + void ThermoPlasticMaterial:: + compute_thermo_elastic_heating( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index) { + const auto point_history = material_point_history.at(point_index); + const Number J = constitutive_request.get_deformation_Jacobian(); + const Number previous_J = constitutive_request.get_previous_deformation_Jacobian(); + const Number J_time_rate = constitutive_request.get_deformation_Jacobian_time_rate(); + const Number theta = constitutive_request.get_temperature(); + const Number previous_theta = constitutive_request.get_previous_temperature(); + const Number time_increment = constitutive_request.get_time_increment(); + if (J != 0 and previous_J != 0) { + const Number eta = (3.0/1000.0) * kappa * thermal_expansion_coefficient * (J - 1.0/J); + const Number previous_eta = (3.0/1000.0) * kappa * thermal_expansion_coefficient * (previous_J - 1.0/previous_J); + constitutive_request.set_thermo_elastic_heating(-theta * (eta - previous_eta) / time_increment); + constitutive_request.set_thermo_elastic_heating_tangent_modulus(-(eta - previous_eta) / time_increment); + } else { + // TODO define and throw appropriate exception: bad deformation gradient! + constitutive_request.set_thermo_elastic_heating(0); + constitutive_request.set_thermo_elastic_heating_tangent_modulus(0); + } + } + + template + void ThermoPlasticMaterial:: + compute_stored_heat_rate( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index) { + const Number stored_heat_rate = heat_capacity * constitutive_request.get_temperature_time_rate(); + constitutive_request.set_stored_heat_rate(stored_heat_rate); + constitutive_request.set_stored_heat_rate_tangent_modulus(heat_capacity); + } + + template + inline void + ThermoPlasticMaterial:: + determine_delta_gamma(Number &delta_gamma, Number &alpha_n_plus_1, + const Number norm_ksi_trial, + const Number mu_bar, + const Number alpha_n, + const Number temperature, + const Number time_increment, + const Number tol, + const unsigned int max_iter) const { + unsigned int k = 0; + const Number sqrt2thirds = Constants::sqrt2thirds(); + const Number two_thirds = Constants::two_thirds(); + Number g_of_gamma_k, Dg_of_gamma_k; + Number H_alpha_n, H_alpha_n_plus_1, K_alpha_n, K_alpha_n_plus_1; + Number DK_alpha_n_plus_1, DH_alpha_n_plus_1; + + delta_gamma = 0; + alpha_n_plus_1 = alpha_n; + + viscoplastic_yield_law.hardening_values(H_alpha_n, K_alpha_n, alpha_n, 0.0, time_increment, temperature); + + viscoplastic_yield_law.hardening_values(H_alpha_n_plus_1, K_alpha_n_plus_1, alpha_n_plus_1, delta_gamma, time_increment, temperature); + g_of_gamma_k = norm_ksi_trial + - 2 * mu_bar * delta_gamma + - sqrt2thirds * H_alpha_n_plus_1 + - sqrt2thirds * (K_alpha_n_plus_1 - K_alpha_n); + do { + viscoplastic_yield_law.hardening_alpha_derivatives(DH_alpha_n_plus_1, DK_alpha_n_plus_1, alpha_n_plus_1, delta_gamma, time_increment, temperature); + Dg_of_gamma_k = -2 * mu_bar - two_thirds * (DK_alpha_n_plus_1 + DH_alpha_n_plus_1); + + delta_gamma = delta_gamma - g_of_gamma_k / Dg_of_gamma_k; + alpha_n_plus_1 = alpha_n + sqrt2thirds * delta_gamma; + + viscoplastic_yield_law.hardening_values(H_alpha_n_plus_1, K_alpha_n_plus_1, alpha_n_plus_1, delta_gamma, time_increment, temperature); + g_of_gamma_k = norm_ksi_trial + - 2 * mu_bar * delta_gamma + - sqrt2thirds * H_alpha_n_plus_1 + - sqrt2thirds * (K_alpha_n_plus_1 - K_alpha_n); + } while (std::fabs(g_of_gamma_k) > tol && ++k < max_iter); + if (std::fabs(g_of_gamma_k) > tol) { + std::ostringstream convert; + convert << "Did not converge after " << k << " iterations. g: " << g_of_gamma_k + << ", norm_ksi_trial: " << norm_ksi_trial + << ", mu_bar: " << mu_bar + << ", H_alpha_n_plus_1: " << H_alpha_n_plus_1 + << ", alpha: " << alpha_n_plus_1 + << ", delta_gamma: " << delta_gamma + << ", temperature: " << temperature + << ", gradient: " << Dg_of_gamma_k; + throw MaterialDomainException(convert.str()); + } + } + + template class ThermoPlasticMaterial<3, ExponentialHardeningThermoviscoplasticYieldLaw, double>; + template class ThermoPlasticMaterial<2, ExponentialHardeningThermoviscoplasticYieldLaw, double>; + + template class ThermoPlasticMaterial<3, JohnsonCookThermoviscoplasticYieldLaw, double>; + template class ThermoPlasticMaterial<2, JohnsonCookThermoviscoplasticYieldLaw, double>; + +} /* namespace PlasticityLab */ diff --git a/ALE_Finite_Strain_Plasticity/src/ThermoPlasticMaterial.h b/ALE_Finite_Strain_Plasticity/src/ThermoPlasticMaterial.h new file mode 100644 index 00000000..ac58424f --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/ThermoPlasticMaterial.h @@ -0,0 +1,100 @@ +/* + * ThermoPlasticMaterial.h + * + * Created on: 05 Jan 2015 + * Author: maien + */ + +#ifndef THERMOPLASTICMATERIAL_H_ +#define THERMOPLASTICMATERIAL_H_ + +#include "PointHistory.h" +#include "Material.h" +#include "ConstitutiveModelRequest.h" + +using namespace dealii; + +namespace PlasticityLab { + + template + class ThermoPlasticMaterial : public Material { + public: + ThermoPlasticMaterial(const Number kappa, + const Number mu, + const Number thermal_expansion_coefficient, + const Number thermal_conductivity, + const Number heat_capacity, + const Number dissipation_factor, + const ViscoplasticYieldLaw &viscoplastic_yield_law); + + virtual ~ThermoPlasticMaterial(); + + void compute_constitutive_request( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index); + + Number get_material_Jacobian(const point_index_t &point_index) const; + dealii::SymmetricTensor<2, dim, Number> get_plastic_strain(const point_index_t &point_index) const; + + std::vector get_state_parameters( + const point_index_t &point_index, + const Tensor<2, dim, Number> &reference_transformation=unit_symmetric_tensor()) const; + + void set_state_parameters( + const point_index_t &point_index, + const std::vector &state_parameters, + const Tensor<2, dim, Number> &reference_transformation=unit_symmetric_tensor()); + size_t get_material_parameter_count() const; + + + void setup_point_history (const point_index_t point_count); + + private: + const Number kappa; + const Number mu; + + const Number thermal_expansion_coefficient; + const Number thermal_conductivity; + const Number heat_capacity; + const Number reference_temperature; + + const Number dissipation_factor; + const ViscoplasticYieldLaw viscoplastic_yield_law; + + std::vector< PointHistory > material_point_history; + + inline void + compute_pressure( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index); + + inline void + determine_delta_gamma(Number &delta_gamma, Number &alpha_n_plus_1, + const Number norm_ksi_trial, + const Number mu_bar, + const Number alpha_n, + const Number temperature, + const Number time_increment, + const Number tol, unsigned int max_iter) const; + + void compute_stress_deviator_and_d_gamma( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index); + + void compute_heat_flux( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index); + + void compute_thermo_elastic_heating( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index); + + void compute_stored_heat_rate( + ConstitutiveModelRequest &constitutive_request, + const point_index_t &point_index); + + }; + +} /* namespace PlasticityLab */ + +#endif /* THERMOPLASTICMATERIAL_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/TimeRateRequest.h b/ALE_Finite_Strain_Plasticity/src/TimeRateRequest.h new file mode 100644 index 00000000..642f49c0 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/TimeRateRequest.h @@ -0,0 +1,370 @@ +/* + * TimeRateRequest.h + * + * Created on: 27 Nov 2019 + * Author: maien + */ + +#ifndef TIMERATEREQUEST_H_ +#define TIMERATEREQUEST_H_ + +#include + +#include "Constants.h" +#include "TimeRateUpdateFlags.h" + +namespace PlasticityLab { + + template + class TimeRateRequest { + public: + TimeRateRequest(TimeRateUpdateFlags); + virtual ~TimeRateRequest(); + + // Interface to be used by request client (FE system assembler) + // --request configuration stage-- + void set_value(const ValueType &value); + void set_previous_value(const ValueType &previous_value); + void set_second_previous_value(const ValueType &second_previous_value); + + void set_time_increment(const Number time_increment); + void set_previous_time_increment(const Number previous_time_increment); + + void set_previous_partial_time_rate(const ValueType &previous_partial_time_rate); + void set_previous_total_time_rate(const ValueType &previous_total_time_rate); + + void set_velocity(const dealii::Tensor<1, dim, Number> &velocity); + + // Interface to be used by request client (FE system assembler) + // --request response retrieval and interrogation stage-- + ValueType get_partial_time_rate() const; + ValueType get_total_time_rate() const; + ValueType get_partial_second_time_rate() const; + ValueType get_total_second_time_rate() const; + + ValueType get_partial_time_rate_tangent(const ValueType &value_increment) const; + ValueType get_partial_second_time_rate_tangent(const ValueType &value_increment) const; + + template + ValueType get_total_time_rate_tangent( + const ValueType &value_increment, + const ValueType &gradient_increment) const; + + template + ValueType get_total_second_time_rate_tangent( + const ValueType &value_increment, + const ValueType &gradient_increment) const; + + // interface used by constitutive model object to perform computation + // TODO consider hiding this interface and exposing it through adapter + TimeRateUpdateFlags get_update_flags() const; + ValueType get_value() const; + ValueType get_previous_value() const; + ValueType get_second_previous_value() const; + + Number get_time_increment() const; + Number get_previous_time_increment() const; + + ValueType get_previous_partial_time_rate() const; + ValueType get_previous_total_time_rate() const; + + dealii::Tensor<1, dim, Number> get_velocity() const; + + // set the results + void set_partial_time_rate(const ValueType &partial_time_rate); + void set_total_time_rate(const ValueType &total_time_rate); + void set_partial_second_time_rate(const ValueType &partial_second_time_rate); + void set_total_second_time_rate(const ValueType &total_second_time_rate); + + void set_partial_time_rate_tangent(const ValueType &partial_time_rate_tangent); + void set_total_time_rate_tangent(const ValueType &total_time_rate_tangent); + void set_partial_second_time_rate_tangent(const ValueType &partial_second_time_rate_tangent); + void set_total_second_time_rate_tangent(const ValueType &total_second_time_rate_tangent); + + protected: + // inputs + TimeRateUpdateFlags update_flags; + + ValueType value; + ValueType previous_value; + ValueType second_previous_value; + + Number time_increment; + Number previous_time_increment; + + ValueType previous_partial_time_rate; + ValueType previous_total_time_rate; + + dealii::Tensor<1, dim, Number> velocity; + + // outputs + ValueType partial_time_rate; + ValueType total_time_rate; + ValueType partial_second_time_rate; + ValueType total_second_time_rate; + + ValueType partial_time_rate_tangent; + ValueType total_time_rate_tangent; + ValueType partial_second_time_rate_tangent; + ValueType total_second_time_rate_tangent; + }; + + + template + TimeRateRequest:: + TimeRateRequest(TimeRateUpdateFlags update_flags): + update_flags(update_flags) { + } + + template + TimeRateRequest::~TimeRateRequest() { } + + + template + void TimeRateRequest:: + set_value(const ValueType &value) { + this->value = value; + } + + + template + void TimeRateRequest:: + set_previous_value(const ValueType &previous_value) { + this->previous_value = previous_value; + } + + + template + void TimeRateRequest:: + set_second_previous_value(const ValueType &second_previous_value) { + this->second_previous_value = second_previous_value; + } + + + template + void TimeRateRequest:: + set_time_increment(const Number time_increment) { + this->time_increment = time_increment; + } + + + template + void TimeRateRequest:: + set_previous_time_increment(const Number previous_time_increment) { + this->previous_time_increment = previous_time_increment; + } + + + template + void TimeRateRequest:: + set_previous_partial_time_rate(const ValueType &previous_partial_time_rate) { + this->previous_partial_time_rate = previous_partial_time_rate; + } + + + template + void TimeRateRequest:: + set_previous_total_time_rate(const ValueType &previous_total_time_rate) { + this->previous_total_time_rate = previous_total_time_rate; + } + + + template + void TimeRateRequest:: + set_velocity(const dealii::Tensor<1, dim, Number> &velocity) { + this->velocity = velocity; + } + + + + + template + ValueType TimeRateRequest:: + get_partial_time_rate() const { + return partial_time_rate; + } + + + template + ValueType TimeRateRequest:: + get_total_time_rate() const { + return total_time_rate; + } + + + template + ValueType TimeRateRequest:: + get_partial_second_time_rate() const { + return partial_second_time_rate; + } + + + template + ValueType TimeRateRequest:: + get_total_second_time_rate() const { + return total_second_time_rate; + } + + + template + ValueType TimeRateRequest:: + get_partial_time_rate_tangent(const ValueType &value_increment) const { + return partial_time_rate_tangent; + } + + + template + ValueType TimeRateRequest:: + get_partial_second_time_rate_tangent(const ValueType &value_increment) const { + return partial_second_time_rate_tangent; + } + + + template + template + ValueType TimeRateRequest:: + get_total_time_rate_tangent( + const ValueType &value_increment, + const ValueType &gradient_increment) const { + throw; + } + + + template + template + ValueType TimeRateRequest:: + get_total_second_time_rate_tangent( + const ValueType &value_increment, + const ValueType &gradient_increment) const { + throw; + } + + + /* + + */ + template + TimeRateUpdateFlags TimeRateRequest:: + get_update_flags() const { + return update_flags; + } + + + template + ValueType TimeRateRequest:: + get_value() const { + return value; + } + + + template + ValueType TimeRateRequest:: + get_previous_value() const { + return previous_value; + } + + + template + ValueType TimeRateRequest:: + get_second_previous_value() const { + return second_previous_value; + } + + + template + Number TimeRateRequest:: + get_time_increment() const { + return time_increment; + } + + + template + Number TimeRateRequest:: + get_previous_time_increment() const { + return previous_time_increment; + } + + + template + ValueType TimeRateRequest:: + get_previous_partial_time_rate() const { + return previous_partial_time_rate; + } + + + template + ValueType TimeRateRequest:: + get_previous_total_time_rate() const { + return previous_total_time_rate; + } + + + template + dealii::Tensor<1, dim, Number> TimeRateRequest:: + get_velocity() const { + return velocity; + } + + + /* + + */ + template + void TimeRateRequest:: + set_partial_time_rate(const ValueType &partial_time_rate) { + this->partial_time_rate = partial_time_rate; + } + + + template + void TimeRateRequest:: + set_total_time_rate(const ValueType &total_time_rate) { + this->total_time_rate = total_time_rate; + } + + + template + void TimeRateRequest:: + set_partial_second_time_rate(const ValueType &partial_second_time_rate) { + this->partial_second_time_rate = partial_second_time_rate; + } + + + template + void TimeRateRequest:: + set_total_second_time_rate(const ValueType &total_second_time_rate) { + this->total_second_time_rate = total_second_time_rate; + } + + + template + void TimeRateRequest:: + set_partial_time_rate_tangent(const ValueType &partial_time_rate_tangent) { + this->partial_time_rate_tangent = partial_time_rate_tangent; + } + + + template + void TimeRateRequest:: + set_total_time_rate_tangent(const ValueType &total_time_rate_tangent) { + this->total_time_rate_tangent = total_time_rate_tangent; + } + + + template + void TimeRateRequest:: + set_partial_second_time_rate_tangent(const ValueType &partial_second_time_rate_tangent) { + this->partial_second_time_rate_tangent = partial_second_time_rate_tangent; + } + + + template + void TimeRateRequest:: + set_total_second_time_rate_tangent(const ValueType &total_second_time_rate_tangent) { + this->total_second_time_rate_tangent = total_second_time_rate_tangent; + } + + +} /* namespace PlasticityLab */ + +#endif /* TIMERATEREQUEST_H_ */ diff --git a/ALE_Finite_Strain_Plasticity/src/TimeRateUpdateFlags.h b/ALE_Finite_Strain_Plasticity/src/TimeRateUpdateFlags.h new file mode 100644 index 00000000..4e261982 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/TimeRateUpdateFlags.h @@ -0,0 +1,57 @@ +/* + * TimeRateUpdateFlags.h + * + * Created on: 27 Nov 2019 + * Author: maien + */ + +#ifndef TIMERATEUPDATEFLAGS_H_ +#define TIMERATEUPDATEFLAGS_H_ + +namespace PlasticityLab { + + enum TimeRateUpdateFlags { + default_timerate_update_flags = 0x0000, + update_partial_time_rate = 0x0001, + update_total_time_rate = 0x0002, + update_partial_second_time_rate=0x0004, + update_total_second_time_rate=0x0008, + update_partial_time_rate_tangent=0x0010, + update_total_time_rate_tangent=0x0020, + update_partial_second_time_rate_tangent=0x0040, + update_total_second_time_rate_tangent=0x0080 + }; + + inline + TimeRateUpdateFlags + operator | (TimeRateUpdateFlags f1, TimeRateUpdateFlags f2) { + return static_cast ( + static_cast (f1) | + static_cast (f2)); + } + + inline + const TimeRateUpdateFlags & + operator |= (TimeRateUpdateFlags &f1, TimeRateUpdateFlags f2) { + f1 = f1 | f2; + return f1; + } + + inline + TimeRateUpdateFlags + operator & (TimeRateUpdateFlags f1, TimeRateUpdateFlags f2) { + return static_cast ( + static_cast (f1) & + static_cast (f2)); + } + + inline + const TimeRateUpdateFlags & + operator &= (TimeRateUpdateFlags &f1, TimeRateUpdateFlags f2) { + f1 = f1 & f2; + return f1; + } + +} /* namespace PlasticityLab */ + +#endif /*TIMERATEUPDATEFLAGS_H_*/ diff --git a/ALE_Finite_Strain_Plasticity/src/main.cpp b/ALE_Finite_Strain_Plasticity/src/main.cpp new file mode 100644 index 00000000..a5e2135b --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/main.cpp @@ -0,0 +1,128 @@ +//============================================================================ +// Name : main.cpp +// Author : Maien Hamed +// Version : +// Copyright : +// Description : Hello World in C++, Ansi-style +//============================================================================ + +#include + +#include "utilities.h" +#include "ThermoPlasticMaterial.h" +#include "ExponentialHardeningThermoviscoplasticYieldLaw.h" +#include "JohnsonCookThermoviscoplasticYieldLaw.h" +#include "ExponentialHardeningElastoplasticMaterial.h" +#include "PlasticityLabProg.h" + +#define DIM 2 + +PlasticityLab::ThermoPlasticMaterial, double> +getExponentialHardeningThermoPlasticMaterial(); + +PlasticityLab::ThermoPlasticMaterial, double> +getJohnsonCookThermoPlasticMaterial(); + +int main(int argc, char **argv) { + try { + Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv); + { + deallog.depth_console(0); + auto material = getExponentialHardeningThermoPlasticMaterial(); + PlasticityLab::PlasticityLabProg plasticityLab(material); + plasticityLab.run(); + if (Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0) + std::cout << "Finished." << std::endl; // prints + } + } catch (std::exception &exc) { + std::cerr << std::endl << std::endl + << "----------------------------------------------------" + << std::endl; + std::cerr << "Exception on processing: " << std::endl + << exc.what() << std::endl + << "Aborting!" << std::endl + << "----------------------------------------------------" + << std::endl; + return 1; + } catch (...) { + std::cerr << std::endl << std::endl + << "----------------------------------------------------" + << std::endl; + std::cerr << "Unknown exception!" << std::endl + << "Aborting!" << std::endl + << "----------------------------------------------------" + << std::endl; + return 1; + } + return 0; +} + +PlasticityLab::ThermoPlasticMaterial, double> +getExponentialHardeningThermoPlasticMaterial() { + double kappa (164206.0), // [MPa] + mu (801938.0), // [MPa] + thermal_expansion_coefficient(1.0e-5), // [K^-1] + thermal_conductivity(4.5e-2), // [J/mm.K.s] + heat_capacity(3.588e-3), // cp*rho: [J.mm^-3.K^-1] + K_0(450.0/*std::numeric_limits::max()*/), // [MPa] + K_infty(715.0/*std::numeric_limits::max()*/), // [MPa] + delta(16.93), // dimensionless + H_bar(129.24), // [MPa] + beta(1.0), // dimensionless (1.0 for isotropic hardening, 0.0 for kinematic hardening) + flow_stress_softening(0.002), // [K^-1] + hardening_softening(0.002), // [K^-1] + dissipation_factor(0.9); // dimensionless + + PlasticityLab::ExponentialHardeningThermoviscoplasticYieldLaw thermo_viscoplastic_yield_law( + K_0, + K_infty, + delta, + H_bar, + beta, + flow_stress_softening, + hardening_softening); + + return PlasticityLab::ThermoPlasticMaterial, double> + (kappa, + mu, + thermal_expansion_coefficient, + thermal_conductivity, + heat_capacity, + dissipation_factor, + thermo_viscoplastic_yield_law); +} + +PlasticityLab::ThermoPlasticMaterial, double> +getJohnsonCookThermoPlasticMaterial() { + double kappa (103300.0), // [MPa] + mu (47690.0), // [MPa] + A(89.7), // [MPa] + B(291.87), // [MPa] + C(0.025), // dimensionless + m(1.09), // dimensionless + n(0.31), // dimensionless + melting_temperature(1356), // [K] + reference_temperature(293.15), // [K] + reference_strain_rate(1.0), // [s^-1] + beta(1.0), //dimensionless + thermal_expansion_coefficient(1.0e-5), // [K^-1] + thermal_conductivity(4.5e-2), // [J/mm.K.s] // http://www.matweb.com/search/datasheet_print.aspx?matguid=193434cf42e343fab880e1dabdb143ba + heat_capacity(3.588e-3), // cp*rho: [J.mm^-3.K^-1] + dissipation_factor(0.9); // dimensionless + + PlasticityLab::JohnsonCookThermoviscoplasticYieldLaw thermo_viscoplastic_yield_law( + mu, A, B, C, + m, n, + melting_temperature, + reference_strain_rate, + reference_temperature); + + return PlasticityLab::ThermoPlasticMaterial, double> + (kappa, + mu, + thermal_expansion_coefficient, + thermal_conductivity, + heat_capacity, + dissipation_factor, + thermo_viscoplastic_yield_law); +} diff --git a/ALE_Finite_Strain_Plasticity/src/symmetric_tensor_entries.h b/ALE_Finite_Strain_Plasticity/src/symmetric_tensor_entries.h new file mode 100644 index 00000000..98d9961a --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/symmetric_tensor_entries.h @@ -0,0 +1,149 @@ +#pragma once + +#include + +#include +#include + +namespace dealii_utils +{ + // ---------------- Const view ---------------- + template + class SymmetricTensorConstEntriesView + { + public: + using tensor_type = dealii::SymmetricTensor; + + explicit SymmetricTensorConstEntriesView(const tensor_type &t) : t_(&t) {} + + class const_iterator + { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = Number; + using difference_type = std::ptrdiff_t; + using pointer = const Number *; + using reference = const Number &; + + const_iterator() = default; + const_iterator(const tensor_type *t, unsigned int i) : t_(t), i_(i) {} + + reference operator*() const { return t_->access_raw_entry(i_); } + + const_iterator &operator++() { ++i_; return *this; } + const_iterator operator++(int) { const_iterator tmp(*this); ++(*this); return tmp; } + + friend bool operator==(const const_iterator &a, const const_iterator &b) + { + return a.t_ == b.t_ && a.i_ == b.i_; + } + friend bool operator!=(const const_iterator &a, const const_iterator &b) { return !(a == b); } + + private: + const tensor_type *t_ = nullptr; + unsigned int i_ = 0; + }; + + const_iterator begin() const { return const_iterator(t_, 0u); } + const_iterator end() const { return const_iterator(t_, tensor_type::n_independent_components); } + const_iterator cbegin() const { return begin(); } + const_iterator cend() const { return end(); } + + private: + const tensor_type *t_; + }; + + + // ---------------- Mutable view ---------------- + template + class SymmetricTensorMutableEntriesView + { + public: + using tensor_type = dealii::SymmetricTensor; + + explicit SymmetricTensorMutableEntriesView(tensor_type &t) : t_(&t) {} + + class iterator + { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = Number; + using difference_type = std::ptrdiff_t; + using pointer = Number *; + using reference = Number &; + + iterator() = default; + iterator(tensor_type *t, unsigned int i) : t_(t), i_(i) {} + + reference operator*() const { return t_->access_raw_entry(i_); } + + iterator &operator++() { ++i_; return *this; } + iterator operator++(int) { iterator tmp(*this); ++(*this); return tmp; } + + friend bool operator==(const iterator &a, const iterator &b) + { + return a.t_ == b.t_ && a.i_ == b.i_; + } + friend bool operator!=(const iterator &a, const iterator &b) { return !(a == b); } + + private: + tensor_type *t_ = nullptr; + unsigned int i_ = 0; + }; + + class const_iterator + { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = Number; + using difference_type = std::ptrdiff_t; + using pointer = const Number *; + using reference = const Number &; + + const_iterator() = default; + const_iterator(const tensor_type *t, unsigned int i) : t_(t), i_(i) {} + + reference operator*() const { return t_->access_raw_entry(i_); } + + const_iterator &operator++() { ++i_; return *this; } + const_iterator operator++(int) { const_iterator tmp(*this); ++(*this); return tmp; } + + friend bool operator==(const const_iterator &a, const const_iterator &b) + { + return a.t_ == b.t_ && a.i_ == b.i_; + } + friend bool operator!=(const const_iterator &a, const const_iterator &b) { return !(a == b); } + + private: + const tensor_type *t_ = nullptr; + unsigned int i_ = 0; + }; + + iterator begin() { return iterator(t_, 0u); } + iterator end() { return iterator(t_, tensor_type::n_independent_components); } + + const_iterator begin() const { return const_iterator(t_, 0u); } + const_iterator end() const { return const_iterator(t_, tensor_type::n_independent_components); } + const_iterator cbegin() const { return begin(); } + const_iterator cend() const { return end(); } + + private: + tensor_type *t_; + }; + + + // ---------------- Factories ---------------- + template + SymmetricTensorConstEntriesView + symmetric_tensor_entries(const dealii::SymmetricTensor &t) + { + return SymmetricTensorConstEntriesView(t); + } + + template + SymmetricTensorMutableEntriesView + symmetric_tensor_entries(dealii::SymmetricTensor &t) + { + return SymmetricTensorMutableEntriesView(t); + } +} // namespace dealii_utils diff --git a/ALE_Finite_Strain_Plasticity/src/utilities.h b/ALE_Finite_Strain_Plasticity/src/utilities.h new file mode 100644 index 00000000..c2a714f6 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/src/utilities.h @@ -0,0 +1,20 @@ +#ifndef _UTILITIES_H +#define _UTILITIES_H + +#include +#include + +namespace PlasticityLab { + + static MPI_Comm mpi_communicator(MPI_COMM_WORLD); + + struct NotImplementedException : std::exception { + const char *what() const _GLIBCXX_USE_NOEXCEPT { + return "Not Implemented.!\n"; + } + }; + +} /*namespace PlasticityLab*/ + + +#endif /*_UTILITIES_H*/ From 3cba745b95528c332cfc63a5d2c9a9b97b178e47 Mon Sep 17 00:00:00 2001 From: Maien Hamed Date: Wed, 21 Jan 2026 01:42:27 -0700 Subject: [PATCH 2/2] Update README.md, create doc files, and move CMakeLists to entry dir --- .../{src => }/CMakeLists.txt | 4 +- ALE_Finite_Strain_Plasticity/README.md | 73 ++++++++++++++++--- ALE_Finite_Strain_Plasticity/doc/author | 1 + ALE_Finite_Strain_Plasticity/doc/build-on | 1 + ALE_Finite_Strain_Plasticity/doc/dependencies | 1 + ALE_Finite_Strain_Plasticity/doc/entry-name | 1 + ALE_Finite_Strain_Plasticity/doc/tooltip | 1 + 7 files changed, 69 insertions(+), 13 deletions(-) rename ALE_Finite_Strain_Plasticity/{src => }/CMakeLists.txt (95%) create mode 100644 ALE_Finite_Strain_Plasticity/doc/author create mode 100644 ALE_Finite_Strain_Plasticity/doc/build-on create mode 100644 ALE_Finite_Strain_Plasticity/doc/dependencies create mode 100644 ALE_Finite_Strain_Plasticity/doc/entry-name create mode 100644 ALE_Finite_Strain_Plasticity/doc/tooltip diff --git a/ALE_Finite_Strain_Plasticity/src/CMakeLists.txt b/ALE_Finite_Strain_Plasticity/CMakeLists.txt similarity index 95% rename from ALE_Finite_Strain_Plasticity/src/CMakeLists.txt rename to ALE_Finite_Strain_Plasticity/CMakeLists.txt index e6c5e9fa..3c42dc4a 100644 --- a/ALE_Finite_Strain_Plasticity/src/CMakeLists.txt +++ b/ALE_Finite_Strain_Plasticity/CMakeLists.txt @@ -15,8 +15,8 @@ SET(TARGET "PlasticityLab") # or switch altogether to the large project CMakeLists.txt file discussed # in the "CMake in user projects" page accessible from the "User info" # page of the documentation. -FILE(GLOB_RECURSE TARGET_SRC "*.cpp") -FILE(GLOB_RECURSE TARGET_INC "*.h") +FILE(GLOB_RECURSE TARGET_SRC "./src/*.cpp") +FILE(GLOB_RECURSE TARGET_INC "./src/*.h") SET(TARGET_SRC ${TARGET_SRC} ${TARGET_INC}) # Define the output that should be cleaned: diff --git a/ALE_Finite_Strain_Plasticity/README.md b/ALE_Finite_Strain_Plasticity/README.md index e2f2bdca..be5ad9ee 100644 --- a/ALE_Finite_Strain_Plasticity/README.md +++ b/ALE_Finite_Strain_Plasticity/README.md @@ -1,17 +1,68 @@ -## To run: +# PlasticityLab: ALE finite-strain thermoplasticity (axisymmetric) +## Overview + +This code-gallery entry provides a deal.II-based implementation of a large-deformation thermomechanical solver for finite-strain thermoplasticity, developed to support numerical simulation of severe-deformation metal forming processes and related problems involving strong thermomechanical coupling and viscoplastic flow. + +The solver implements a finite-strain associative coupled thermoplasticity model. + +## Key idea: ALE via incremental reference motion + +The solver incorporates an Arbitrary Lagrangian–Eulerian (ALE) formulation for coupled finite-strain thermoplasticity in which the motion of the reference configuration is represented incrementally through a reference velocity field. This avoids the need to explicitly track the deformation from the initial material configuration, either as a deformation field or through storing and updating the full deformation gradient history. + +The method targets regimes where large accumulated strains can cause excessive mesh distortion in purely Lagrangian finite element simulations. The ALE formulation reduces sensitivity to mesh distortion and enables stable simulation without requiring prohibitively small time steps. + +## Physics and models +### Finite-strain thermoplasticity + +The constitutive model is a finite-strain, associative, coupled thermoplasticity formulation based on a multiplicative decomposition of the deformation gradient and a J2 (von Mises) flow theory. The implementation supports viscoplastic behavior via rate-dependent flow stress models (including Johnson-Cook). + +### Thermomechanical coupling + +The thermal problem is coupled to the mechanical response through plastic dissipation and heat conduction. + +### Discretization and solution strategy (high level) + +Mixed finite element formulation to mitigate volumetric locking (Jacobian/pressure treated as additional unknowns). + +Newton-Raphson nonlinear solve with consistent tangent moduli (targeting second-order convergence behavior). + +Mechanical-thermal operator splitting per time step (mechanical, then thermal, then mechanical sub-step). + +### Axisymmetric reduction and benchmark problems + +Although the formulation is derived for general 3D settings, the code uses an axisymmetric approximation for benchmark problems and representative manufacturing-process simulations. + +The entry validates and illustrates the approach using benchmark problems including: + +thermally triggered necking of a circular bar (thermoplasticity benchmark), + +Taylor anvil impact of a circular bar (dynamic high-rate deformation benchmark), + +## To run ``` # in a build directory: -$ cmake -DDEAL_II_DIR= +$ cmake -DDEAL_II_DIR= $ make release -$ make -j 8 && $HOME/share/bin/mpirun -n 18 ./PlasticityLab - -# The triangulation is configured in PlasticityLabProgDrivers.cpp in run() -# The material is configured in main.cpp -# The timestep is configured in PlasticityLabProg.h +$ make -j 8 && mpirun -n 18 ./PlasticityLab ``` -## Citation: -If you use this code as part of your work, please cite: -Hamed, M.M.O., McBride, A.T. & Reddy, B.D. An ALE approach for large-deformation thermoplasticity with application to friction welding. Comput Mech 72, 803–826 (2023). -https://doi.org/10.1007/s00466-023-02303-0 +## Notes on configuration + +Geometry / triangulation: configured in PlasticityLabProgDrivers.cpp in run(). +Material model selection and parameters: configured in main.cpp. + +Time step settings: configured in PlasticityLabProg.h. + +## References +``` +@article{HamedMcBrideReddy2023_ALE_Thermoplasticity_FrictionWelding, + author = {Hamed, M. M. O. and McBride, A. T. and Reddy, B. D.}, + title = {An {ALE} approach for large-deformation thermoplasticity with application to friction welding}, + journal = {Computational Mechanics}, + volume = {72}, + pages = {803--826}, + year = {2023}, + doi = {10.1007/s00466-023-02303-0} +} +``` \ No newline at end of file diff --git a/ALE_Finite_Strain_Plasticity/doc/author b/ALE_Finite_Strain_Plasticity/doc/author new file mode 100644 index 00000000..ab638c94 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/doc/author @@ -0,0 +1 @@ +Maien Hamed diff --git a/ALE_Finite_Strain_Plasticity/doc/build-on b/ALE_Finite_Strain_Plasticity/doc/build-on new file mode 100644 index 00000000..fe4c76fa --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/doc/build-on @@ -0,0 +1 @@ +step-42 diff --git a/ALE_Finite_Strain_Plasticity/doc/dependencies b/ALE_Finite_Strain_Plasticity/doc/dependencies new file mode 100644 index 00000000..df1d8c33 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/doc/dependencies @@ -0,0 +1 @@ +DEAL_II_WITH_MPI DEAL_II_WITH_P4EST DEAL_II_WITH_TRILINOS \ No newline at end of file diff --git a/ALE_Finite_Strain_Plasticity/doc/entry-name b/ALE_Finite_Strain_Plasticity/doc/entry-name new file mode 100644 index 00000000..d06debe6 --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/doc/entry-name @@ -0,0 +1 @@ +An ALE approach for large-deformation thermoplasticity diff --git a/ALE_Finite_Strain_Plasticity/doc/tooltip b/ALE_Finite_Strain_Plasticity/doc/tooltip new file mode 100644 index 00000000..c0cdaadb --- /dev/null +++ b/ALE_Finite_Strain_Plasticity/doc/tooltip @@ -0,0 +1 @@ +An implementation of a large-deformation arbitrary Lagrangian-Eulerian finite-strain thermoplasticity solver \ No newline at end of file