24#include "elements/properties/b2fortran_element_property.H" 
   25#include "elements/properties/b2solid_mechanics.H" 
   26#include "io/b2000_db/b2000_db_v3/b2fortran_element_property.H" 
   27#include "ip/b2ip_constants.H" 
   30#ifndef B2_MATERIAL_SOLID_MECHANICS_UMAT_H_ 
   31#define B2_MATERIAL_SOLID_MECHANICS_UMAT_H_ 
   33namespace b2000 { 
namespace element {
 
   35typedef void(umat_subroutine_f)(
 
   67      const double COORDS[3],     
 
   68      const double DROT[3][3],    
 
   71      const double DFGRD0[3][3],  
 
   72      const double DFGRD1[3][3],  
 
   81template <umat_subroutine_f UMAT_SUBROUTINE, const 
char MATERIAL_TYPE_NAME[], 
int NSTATV>
 
   82class MaterialSolidMechanics3DUMAT_copy;
 
   84template <umat_subroutine_f UMAT_SUBROUTINE, const 
char MATERIAL_TYPE_NAME[], 
int NSTATV>
 
   88    LinearType linear(
const int layer_id = -1)
 const { 
return nonlinear; }
 
   90    bool path_dependent(
const int layer_id = -1)
 const { 
return true; }
 
   92    SolidMechanics3D* copy(
int layer_) {
 
   93        return new MaterialSolidMechanics3DUMAT_copy<UMAT_SUBROUTINE, MATERIAL_TYPE_NAME, NSTATV>(
 
   97    bool isotropic(
const int layer_id = -1)
 const { 
return false; }
 
   99    void get_dynamic_nonlinear_stress(
 
  100          Model* model, 
const Element* element,
 
  101          b2000::b2linalg::Vector<double, b2000::b2linalg::Vdense_constref> nodes_interpolation,
 
  102          const double element_coordinate[3], 
const int layer_id,
 
  103          const double covariant_natural_base[3][3], 
const double displacement_gradient[3][3],
 
  104          const double green_lagrange_strain[6], 
const double green_lagrange_strain_dot[6],
 
  105          const double velocity[3], 
const double acceleration[3], 
const double time,
 
  106          const double delta_time, 
const double area,
 
  107          const EquilibriumSolution equilibrium_solution, 
double piola_kirchhoff_stress[6],
 
  108          double d_piola_kirchhoff_stress_d_strain[21],
 
  109          double d_piola_kirchhoff_stress_d_strain_dot[21],
 
  110          double d_piola_kirchhoff_stress_d_time[6], 
double inertial_force[3], 
double& density,
 
  111          GradientContainer* gradient_container, SolverHints* solver_hints,
 
  112          const double covariant_base[3][3], 
const double contravariant_base[3][3]) {
 
  113        get_static_nonlinear_stress(
 
  114              model, element, nodes_interpolation, element_coordinate, layer_id,
 
  115              covariant_natural_base, displacement_gradient, green_lagrange_strain, time,
 
  116              delta_time, area, equilibrium_solution, piola_kirchhoff_stress,
 
  117              d_piola_kirchhoff_stress_d_strain, d_piola_kirchhoff_stress_d_time,
 
  118              gradient_container, solver_hints, covariant_base, contravariant_base);
 
  121    void get_static_nonlinear_stress(
 
  122          Model* model, 
const Element* element, Vector<double, Vdense_constref> nodes_interpolation,
 
  123          const double element_coordinate[3], 
const int layer_id,
 
  124          const double covariant_natural_base[3][3], 
const double displacement_gradient[3][3],
 
  125          const double green_lagrange_strain[6], 
const double time, 
const double delta_time,
 
  126          const double area, 
const EquilibriumSolution equilibrium_solution,
 
  127          double piola_kirchhoff_stress[6], 
double d_piola_kirchhoff_stress_d_strain[21],
 
  128          double d_piola_kirchhoff_stress_d_time[6], GradientContainer* gradient_container,
 
  129          SolverHints* solver_hints, 
const double covariant_base[3][3] = 0,
 
  130          const double contravariant_base[3][3] = 0) {
 
  131        Exception() << 
"A copy of the object must be used." << 
THROW;
 
  134    typedef ObjectTypeComplete<
 
  135          MaterialSolidMechanics3DUMAT<UMAT_SUBROUTINE, MATERIAL_TYPE_NAME, NSTATV>,
 
  136          FortranElementProperty::type_t>
 
  141template <umat_subroutine_f UMAT_SUBROUTINE, const 
char MATERIAL_TYPE_NAME[], 
int NSTATV>
 
  142typename MaterialSolidMechanics3DUMAT<UMAT_SUBROUTINE, MATERIAL_TYPE_NAME, NSTATV>::type_t
 
  143      MaterialSolidMechanics3DUMAT<UMAT_SUBROUTINE, MATERIAL_TYPE_NAME, NSTATV>::type(
 
  144            MATERIAL_TYPE_NAME, 
"", StringList(), element::module, &b2000::ElementProperty::type);
 
  146template <umat_subroutine_f UMAT_SUBROUTINE, const 
char MATERIAL_TYPE_NAME[], 
int NSTATV>
 
  149    typedef MaterialSolidMechanics3DUMAT<UMAT_SUBROUTINE, MATERIAL_TYPE_NAME, NSTATV> parent_type;
 
  151    MaterialSolidMechanics3DUMAT_copy(parent_type& parent_)
 
  152        : parent(parent_), conv_time(0), conv_sse(0), conv_spd(0), conv_scd(0) {
 
  153        std::fill(conv_deformation_gradient[0], conv_deformation_gradient[3], 0);
 
  154        std::fill(conv_strain_ea, conv_strain_ea + 6, 0);
 
  155        std::fill(conv_stress_ea, conv_stress_ea + 6, 0);
 
  156        std::fill(conv_statv, conv_statv + NSTATV, 0);
 
  159    LinearType linear(
const int layer_id = -1)
 const { 
return nonlinear; }
 
  161    bool path_dependent(
const int layer_id = -1)
 const { 
return true; }
 
  163    SolidMechanics3D* copy(
int layer_) { 
return new MaterialSolidMechanics3DUMAT_copy(*
this); }
 
  165    bool isotropic(
const int layer_id = -1)
 const { 
return false; }
 
  167    void get_dynamic_nonlinear_stress(
 
  168          Model* model, 
const Element* element, Vector<double, Vdense_constref> nodes_interpolation,
 
  169          const double element_coordinate[3], 
const int layer_id,
 
  170          const double covariant_natural_base[3][3], 
const double displacement_gradient[3][3],
 
  171          const double green_lagrange_strain[6], 
const double green_lagrange_strain_dot[6],
 
  172          const double velocity[3], 
const double acceleration[3], 
const double time,
 
  173          const double delta_time, 
const double area,
 
  174          const EquilibriumSolution equilibrium_solution, 
double piola_kirchhoff_stress[6],
 
  175          double d_piola_kirchhoff_stress_d_strain[21],
 
  176          double d_piola_kirchhoff_stress_d_strain_dot[21],
 
  177          double d_piola_kirchhoff_stress_d_time[6], 
double inertial_force[3], 
double& density,
 
  178          GradientContainer* gradient_container, SolverHints* solver_hints,
 
  179          const double covariant_base[3][3], 
const double contravariant_base[3][3]) {
 
  180        get_static_nonlinear_stress(
 
  181              model, element, nodes_interpolation, element_coordinate, layer_id,
 
  182              covariant_natural_base, displacement_gradient, green_lagrange_strain, time,
 
  183              delta_time, area, equilibrium_solution, piola_kirchhoff_stress,
 
  184              d_piola_kirchhoff_stress_d_strain, d_piola_kirchhoff_stress_d_time,
 
  185              gradient_container, solver_hints, covariant_base, contravariant_base);
 
  188    void get_static_nonlinear_stress(
 
  189          Model* model, 
const Element* element, Vector<double, Vdense_constref> nodes_interpolation,
 
  190          const double element_coordinate[3], 
const int layer_id,
 
  191          const double covariant_natural_base[3][3], 
const double displacement_gradient[3][3],
 
  192          const double green_lagrange_strain[6], 
const double time, 
const double delta_time,
 
  193          const double area, 
const EquilibriumSolution equilibrium_solution,
 
  194          double piola_kirchhoff_stress[6], 
double d_piola_kirchhoff_stress_d_strain[21],
 
  195          double d_piola_kirchhoff_stress_d_time[6], GradientContainer* gradient_container,
 
  196          SolverHints* solver_hints, 
const double covariant_base[3][3] = 0,
 
  197          const double contravariant_base[3][3] = 0) {
 
  199        bool material_ref_identity;
 
  200        double material_ref[3][3];
 
  201        const double* props = parent.get_material_and_material_referential(
 
  202              element, layer_id, covariant_natural_base, material_ref, material_ref_identity, 
true);
 
  203        const int nprops = int(props[B2MATPOSSTART]);
 
  208        if (green_lagrange_strain == 0) {
 
  209            std::fill_n(strain_bg, 6, 0.0);
 
  210        } 
else if (covariant_base == 0) {
 
  211            std::copy(green_lagrange_strain, green_lagrange_strain + 6, strain_bg);
 
  213            transform_strain_from_base_A_to_I(covariant_base, green_lagrange_strain, strain_bg)
 
  220        if (material_ref_identity) {
 
  221            std::copy(strain_bg, strain_bg + 6, strain_ea);
 
  223            transform_strain_from_I_to_base_B(material_ref, strain_bg, strain_ea);
 
  229        for (
int i = 0; i != 6; ++i) { dstrain[i] = strain_ea[i] - conv_strain_ea[i]; }
 
  232        double coords[3] = {};
 
  233        std::pair<int, Node* const*> nodes = element->get_nodes();
 
  234        for (
int i = 0; i != nodes.first; ++i) {
 
  235            const double* c = nodes.second[i]->get_coor().second;
 
  236            for (
int j = 0; j != 3; ++j) { coords[j] += nodes_interpolation[i] * c[j]; }
 
  240        double deformation_gradient[3][3];
 
  241        for (
int i = 0; i != 3; ++i) {
 
  242            for (
int j = 0; j != 3; ++j) {
 
  243                deformation_gradient[j][i] = displacement_gradient[j][i];
 
  245            deformation_gradient[i][i] += 1;
 
  248        double dtime = time - conv_time;
 
  250        double pnewdt = delta_time;
 
  252        double statv[NSTATV];
 
  253        std::copy(conv_statv, conv_statv + NSTATV, statv);
 
  255        double sse = conv_sse;
 
  256        double spd = conv_spd;
 
  257        double scd = conv_scd;
 
  260        std::copy(conv_stress_ea, conv_stress_ea + 6, stress_ea);
 
  262        double drot[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
 
  263        const double celent = area;
 
  265        const int noel = element->get_id();
 
  267        const int layer = layer_id + 1;
 
  271        const int nstatv = NSTATV;
 
  272        const int val_unknown = 0;
 
  273        const double time_all[2] = {conv_time, conv_time};
 
  279              stress_ea, statv, ddsdde[0], &sse, &spd, &scd, 0, 0, 0,
 
  281              conv_strain_ea, dstrain, time_all, &dtime, 0,
 
  284              MATERIAL_TYPE_NAME, &val3, &val3, &val6, &nstatv, props + B2MATPOSSTART + 1, &nprops,
 
  285              coords, drot, &pnewdt, &celent, conv_deformation_gradient, deformation_gradient,
 
  286              &noel, &val_unknown, &layer, &val_unknown, &val_unknown, &val_unknown,
 
  287              strlen(MATERIAL_TYPE_NAME));
 
  289        if (equilibrium_solution) {
 
  291                  deformation_gradient[0], deformation_gradient[3], conv_deformation_gradient[0]);
 
  292            std::copy(strain_ea, strain_ea + 6, conv_strain_ea);
 
  293            std::copy(stress_ea, stress_ea + 6, conv_stress_ea);
 
  295            std::copy(statv, statv + NSTATV, conv_statv);
 
  299        if (covariant_base != 0) {
 
  305        get_base_opposite_variance(G, G_d);
 
  313        if (d_piola_kirchhoff_stress_d_strain != NULL) {
 
  314            double d_stress_d_strain_ea[21];
 
  320                double* ptr = d_stress_d_strain_ea;
 
  321                for (
int j = 0; j != 6; ++j) {
 
  322                    for (
int i = j; i != 6; ++i, ++ptr) {
 
  323                        *ptr = 0.5 * (ddsdde[j][i] + ddsdde[i][j]);
 
  330            transform_constitutive_tensor_from_base_A_to_base_B(
 
  331                  G, material_ref, d_stress_d_strain_ea, d_piola_kirchhoff_stress_d_strain);
 
  337        transform_stress_from_base_A_to_I(material_ref, stress_ea, stress_bg);
 
  342        if (piola_kirchhoff_stress != 0) {
 
  343            transform_stress_from_I_to_base_B(G_d, stress_bg, piola_kirchhoff_stress);
 
  346        if (gradient_container == 0) { 
return; }
 
  351        double strain_bg_storage[6];
 
  352        std::copy(strain_bg, strain_bg + 6, strain_bg_storage);
 
  353        for (
int i = 3; i != 6; ++i) { strain_bg_storage[i] *= 0.5; }
 
  357        double stress_bg_storage[6];
 
  359            std::copy(stress_bg, stress_bg + 6, stress_bg_storage);
 
  367            double deformation_gradient[3][3];
 
  368            if (displacement_gradient != NULL) {
 
  369                if (contravariant_base) {
 
  371                          displacement_gradient, contravariant_base, deformation_gradient);
 
  374                          displacement_gradient[0], displacement_gradient[3],
 
  375                          deformation_gradient[0]);
 
  378                std::fill(deformation_gradient[0], deformation_gradient[3], 0);
 
  380            deformation_gradient[0][0] += 1;
 
  381            deformation_gradient[1][1] += 1;
 
  382            deformation_gradient[2][2] += 1;
 
  389            if (material_ref_identity) {
 
  390                transform_stress_from_base_A_ov_to_I(
 
  391                      deformation_gradient, stress_ea, stress_bg_storage);
 
  393                double deformation_gradient_aligned_ortho[3][3];
 
  395                      deformation_gradient, material_ref, deformation_gradient_aligned_ortho);
 
  396                transform_stress_from_base_A_ov_to_I(
 
  397                      deformation_gradient_aligned_ortho, stress_ea, stress_bg_storage);
 
  401            for (
int i = 0; i != 6; ++i) { stress_bg_storage[i] *= det_inv; }
 
  407        static const GradientContainer::FieldDescription strain_descr = {
 
  409              "Exx.Eyy.Ezz.Exy.Eyz.Exz",
 
  410              (nonlinear ? 
"Green Lagrange strain" : 
"Linear strain"),
 
  418        static const GradientContainer::FieldDescription stress_descr = {
 
  420              "Sxx.Syy.Szz.Sxy.Syz.Sxz",
 
  421              (nonlinear ? 
"Cauchy stress" : 
"Linear stress"),
 
  430        if (gradient_container->compute_field_value(strain_descr.name)) {
 
  431            gradient_container->set_field_value(strain_descr, strain_bg_storage);
 
  433        if (gradient_container->compute_field_value(stress_descr.name)) {
 
  434            gradient_container->set_field_value(stress_descr, stress_bg_storage);
 
  440    double conv_deformation_gradient[3][3];
 
  441    double conv_strain_ea[6];
 
  442    double conv_stress_ea[6];
 
  444    double conv_statv[NSTATV];
 
  452#define DEFINE_NEW_MATERIAL_SOLID_MECHANICS_3D_UMAT(                                          \ 
  453      subroutine_name, SUBROUTINE_NAME, material_name, NSTATV)                                \ 
  454    extern "C" b2000::element::umat_subroutine_f FC_GLOBAL(subroutine_name, SUBROUTINE_NAME); \ 
  456    char mname[] = material_name;                                                             \ 
  458    template class b2000::element::MaterialSolidMechanics3DUMAT<                              \ 
  459          FC_GLOBAL(subroutine_name, SUBROUTINE_NAME), mname, NSTATV>; 
#define THROW
Definition b2exception.H:198
 
Definition b2solid_mechanics.H:113
 
Definition b2fortran_element_property.H:53
 
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
 
void set_identity_3_3(T1 a[3][3])
Definition b2tensor_calculus.H:511
 
void inner_product_3_3_NN(const T a[3][3], const T b[3][3], T c[3][3])
Definition b2tensor_calculus.H:808
 
T determinant_3_3(const T a[3][3])
Definition b2tensor_calculus.H:669
 
void copy_3_3(const T1 a[3][3], T1 b[3][3])
Definition b2tensor_calculus.H:525