v0.16.0
Loading...
Searching...
No Matches
UmatInterface.cpp
Go to the documentation of this file.
1/** \file UmatInterface.cpp
2 * \brief UmatInterface
3 *
4 * UmatInterface
5 *
6 */
7
8#include <MoFEM.hpp>
9using namespace MoFEM;
10#include "UmatInterface.hpp"
11
12namespace UmatOps {
13
14inline int tensorIndex(const int ii, const int jj) { return 3 * ii + jj; }
15
18 mat.resize(3, 3, false);
19 mat.clear();
21}
22
25 mat.resize(9, 9, false);
26 mat.clear();
28}
29
30}; // namespace UmatOps
31// MatUmat can do the conversions depending of the strain measure used.
32
33using namespace UmatOps;
34
35template <int MODEL_TYPE>
37 : nstatv(nstatv), nprops(nprops), props(nprops, 0.0), statev(nstatv, 0.0) {}
38
40 if (handle) {
41 dlclose(handle);
42 handle = nullptr;
43 umat = nullptr;
44 }
45}
46
47template <int MODEL_TYPE>
49MoFEM::UmatInterface<MODEL_TYPE>::initialise(const std::string &library_path,
50 const std::string &material_name) {
52
53 if (handle) {
54 dlclose(handle);
55 handle = nullptr;
56 umat = nullptr;
57 }
58
59 std::memset(filename, 0, sizeof(filename));
60 std::strncpy(filename, library_path.c_str(), sizeof(filename) - 1);
61
62 std::memset(cmname, ' ', sizeof(cmname));
63 const auto material_name_size = material_name.size() < sizeof(cmname)
64 ? material_name.size()
65 : sizeof(cmname);
66 std::memcpy(cmname, material_name.data(), material_name_size);
67
68 handle = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
69 if (!handle) {
70 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
71 "Failed to open UMAT library %s: %s", filename, dlerror());
72 }
73
74 umat = (umat_f)dlsym(handle, "umat_");
75 if (!umat) {
76 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
77 "Failed to resolve symbol umat_ in %s: %s", filename, dlerror());
78 }
79
81}
82
83template <int MODEL_TYPE>
86
87 if (!umat) {
88 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
89 "UMAT function pointer is not initialised");
90 }
91
92 umat(stress.data(), statev.data(), ddsdde.data(), &sse, &spd, &scd, &rpl,
93 ddsddt, drplde, &drpldt, stran.data(), dstran.data(), time, &dtime,
94 &temp, &dtemp, predef.data(), dpred.data(), cmname, &ndi, &nshr, &ntens,
95 &nstatv, props.data(), &nprops, coords, drot.data(), &pnewdt, &celent,
96 dfgrd0.data(), dfgrd1.data(), &noel, &npt, &layer, &kspt, &kstep, &kinc,
97 sizeof(cmname));
98
100}
101
102template <int MODEL_TYPE>
106
107 dfgrd0.fill(0);
108 for (int dd = 0; dd != 3; ++dd)
109 dfgrd0[dd + 3 * dd] = 1.0;
110
112}
113
114template <int MODEL_TYPE>
116 const MatrixDouble &grad, bool use_deformation_gradient) {
118
119 dfgrd1.fill(0);
120 for (int dd = 0; dd != 3; ++dd)
121 dfgrd1[dd + 3 * dd] = 1.0;
122
123 for (int row = 0; row != DIM; ++row) {
124 for (int col = 0; col != DIM; ++col) {
125 const double grad_value = grad(row, col);
126 dfgrd1[row + 3 * col] = use_deformation_gradient
127 ? grad_value
128 : grad_value + (row == col ? 1.0 : 0.0);
129 }
130 }
131
133}
134
135template <int MODEL_TYPE>
138 double time_increment) {
140
141 time[1] = current_time;
142 dtime = time_increment;
143 time[0] = current_time - time_increment;
144
146}
147
148template <int MODEL_TYPE>
151 int increment_number) {
153
154 kstep = step_number;
155 kinc = increment_number;
156
158}
159
160template <int MODEL_TYPE>
164
165 auto get_small_strain_voigt = [](const std::array<double, 9> &dfgrd,
166 auto &strain) {
167 std::array<double, 9> grad = dfgrd;
168 for (int dd = 0; dd != DIM; ++dd)
169 grad[dd + 3 * dd] -= 1.0;
170
171 if constexpr (MODEL_TYPE == MatOps::MODEL_3D) {
172 strain[0] = grad[0];
173 strain[1] = grad[4];
174 strain[2] = grad[8];
175 strain[3] = grad[1] + grad[3];
176 strain[4] = grad[2] + grad[6];
177 strain[5] = grad[5] + grad[7];
178 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRAIN) {
179 strain[0] = grad[0];
180 strain[1] = grad[4];
181 strain[2] = 0.0;
182 strain[3] = grad[1] + grad[3];
183 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRESS) {
184 strain[0] = grad[0];
185 strain[1] = grad[4];
186 strain[2] = grad[1] + grad[3];
187 } else {
188 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
189 "UMAT strain increment is not implemented for this model type");
190 }
191 };
192
193 std::array<double, NTENS> reference_strain{};
194 std::array<double, NTENS> current_strain{};
195 get_small_strain_voigt(dfgrd0, reference_strain);
196 get_small_strain_voigt(dfgrd1, current_strain);
197
198 for (int ii = 0; ii != NTENS; ++ii) {
199 stran[ii] = reference_strain[ii];
200 dstran[ii] = current_strain[ii] - reference_strain[ii];
201 }
202
204}
205
206template <int MODEL_TYPE>
208 int n_statev, const std::vector<double> &state_var_values) {
210
212}
213
214template <int MODEL_TYPE>
216 MatrixDouble &F) const {
219 for (int row = 0; row != DIM; ++row)
220 for (int col = 0; col != DIM; ++col)
221 F(row, col) = dfgrd1[row + 3 * col];
223}
224
225template <int MODEL_TYPE>
227 MatrixDouble &sigma) const {
229 CHKERR resizeTensor2(sigma);
230 if constexpr (MODEL_TYPE == MatOps::MODEL_3D) {
231 sigma(0, 0) = stress[0];
232 sigma(1, 1) = stress[1];
233 sigma(2, 2) = stress[2];
234 sigma(0, 1) = sigma(1, 0) = stress[3];
235 sigma(0, 2) = sigma(2, 0) = stress[4];
236 sigma(1, 2) = sigma(2, 1) = stress[5];
237 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRAIN) {
238 sigma(0, 0) = stress[0];
239 sigma(1, 1) = stress[1];
240 sigma(2, 2) = stress[2];
241 sigma(0, 1) = sigma(1, 0) = stress[3];
242 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRESS) {
243 sigma(0, 0) = stress[0];
244 sigma(1, 1) = stress[1];
245 sigma(0, 1) = sigma(1, 0) = stress[2];
246 } else {
247 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
248 "UMAT stress conversion is not implemented for this model type");
249 }
251}
252
253template <int MODEL_TYPE>
255 MatrixDouble &cauchy_tangent) const {
257 CHKERR resizeTensor4(cauchy_tangent);
258 if constexpr (MODEL_TYPE == MatOps::MODEL_3D) {
259 static const std::array<std::pair<int, int>, 6> pairs = {
260 std::pair<int, int>{0, 0}, {1, 1}, {2, 2}, {0, 1}, {0, 2}, {1, 2}};
261 for (int row = 0; row != 6; ++row) {
262 const auto [i, j] = pairs[row];
263 for (int col = 0; col != 6; ++col) {
264 const auto [k, l] = pairs[col];
265 const double value = ddsdde[row + 6 * col];
266 cauchy_tangent(tensorIndex(i, j), tensorIndex(k, l)) = value;
267 cauchy_tangent(tensorIndex(j, i), tensorIndex(k, l)) = value;
268 cauchy_tangent(tensorIndex(i, j), tensorIndex(l, k)) = value;
269 cauchy_tangent(tensorIndex(j, i), tensorIndex(l, k)) = value;
270 }
271 }
272 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRAIN) {
273 static const std::array<std::pair<int, int>, 4> pairs = {
274 std::pair<int, int>{0, 0}, {1, 1}, {2, 2}, {0, 1}};
275 for (int row = 0; row != 4; ++row) {
276 const auto [i, j] = pairs[row];
277 for (int col = 0; col != 4; ++col) {
278 const auto [k, l] = pairs[col];
279 const double value = ddsdde[row + 4 * col];
280 cauchy_tangent(tensorIndex(i, j), tensorIndex(k, l)) = value;
281 cauchy_tangent(tensorIndex(j, i), tensorIndex(k, l)) = value;
282 cauchy_tangent(tensorIndex(i, j), tensorIndex(l, k)) = value;
283 cauchy_tangent(tensorIndex(j, i), tensorIndex(l, k)) = value;
284 }
285 }
286 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRESS) {
287 static const std::array<std::pair<int, int>, 3> pairs = {
288 std::pair<int, int>{0, 0}, {1, 1}, {0, 1}};
289 for (int row = 0; row != 3; ++row) {
290 const auto [i, j] = pairs[row];
291 for (int col = 0; col != 3; ++col) {
292 const auto [k, l] = pairs[col];
293 const double value = ddsdde[row + 3 * col];
294 cauchy_tangent(tensorIndex(i, j), tensorIndex(k, l)) = value;
295 cauchy_tangent(tensorIndex(j, i), tensorIndex(k, l)) = value;
296 cauchy_tangent(tensorIndex(i, j), tensorIndex(l, k)) = value;
297 cauchy_tangent(tensorIndex(j, i), tensorIndex(l, k)) = value;
298 }
299 }
300 } else {
301 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
302 "UMAT tangent conversion is not implemented for this model type");
303 }
305}
306
UmatInterface.
void(*)(double *stress, double *statev, double *ddsdde, double *sse, double *spd, double *scd, double *rpl, double *ddsddt, double *drplde, double *drpldt, double *stran, double *dstran, double *time, double *dtime, double *temp, double *dtemp, double *predef, double *dpred, char *cmname, int *ndi, int *nshr, int *ntens, int *nstatv, double *props, int *nprops, double *coords, double *drot, double *pnewdt, double *celent, double *dfgrd0, double *dfgrd1, int *noel, int *npt, int *layer, int *kspt, int *kstep, int *kinc, std::size_t cmname_len) umat_f
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ F
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
@ MODEL_3D
Definition MatOps.hpp:181
@ MODEL_2D_PLANE_STRESS
Definition MatOps.hpp:183
@ MODEL_2D_PLANE_STRAIN
Definition MatOps.hpp:182
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
MoFEMErrorCode resizeTensor2(MatrixDouble &mat)
MoFEMErrorCode resizeTensor4(MatrixDouble &mat)
int tensorIndex(const int ii, const int jj)
void temp(int x, int y=10)
Definition simple.cpp:4
MoFEMErrorCode setStepData(int step_number, int increment_number)
MoFEMErrorCode initialise(const std::string &library_path="./umat.so", const std::string &material_name="UMAT")
MoFEMErrorCode setTimeData(double current_time, double time_increment)
MoFEMErrorCode getCauchyTangentTensor(MatrixDouble &cauchy_tangent) const
MoFEMErrorCode setStrainIncrementFromDeformationGradient()
MoFEMErrorCode callUmat()
UmatInterface(int nstatv=0, int nprops=2)
MoFEMErrorCode storeStateVar(int n_state_var, const std::vector< double > &state_var_values)
MoFEMErrorCode setDeformationGradient(const MatrixDouble &grad, bool use_deformation_gradient)
MoFEMErrorCode setIdentityDeformationGradient()
MoFEMErrorCode getCauchyStressTensor(MatrixDouble &sigma) const
MoFEMErrorCode getDeformationGradient(MatrixDouble &F) const
subroutine umat(stress, statev, ddsdde, sse, spd, scd, rpl, ddsddt, drplde, drpldt, stran, dstran, time, dtime, temp, dtemp, predef, dpred, cmname, ndi, nshr, ntens, nstatv, props, nprops, coords, drot, pnewdt, celent, dfgrd0, dfgrd1, noel, npt, layer, kspt, kstep, kinc)