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