v0.16.3
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>
118
119 drot.fill(0);
120 for (int dd = 0; dd != 3; ++dd)
121 drot[dd + 3 * dd] = 1.0;
122
124}
125
126template <int MODEL_TYPE>
128 const MatrixDouble &grad, bool use_deformation_gradient) {
130
131 dfgrd1.fill(0);
132 for (int dd = 0; dd != 3; ++dd)
133 dfgrd1[dd + 3 * dd] = 1.0;
134
135 for (int row = 0; row != DIM; ++row) {
136 for (int col = 0; col != DIM; ++col) {
137 const double grad_value = grad(row, col);
138 dfgrd1[row + 3 * col] = use_deformation_gradient
139 ? grad_value
140 : grad_value + (row == col ? 1.0 : 0.0);
141 }
142 }
143
145}
146
147template <int MODEL_TYPE>
150 double time_increment) {
152
153 time[1] = current_time;
154 dtime = time_increment;
155 time[0] = current_time - time_increment;
156
158}
159
160template <int MODEL_TYPE>
163 int increment_number) {
165
166 kstep = step_number;
167 kinc = increment_number;
168
170}
171
172template <int MODEL_TYPE>
176
177 auto get_small_strain_voigt = [](const std::array<double, 9> &dfgrd,
178 auto &strain) {
179 std::array<double, 9> grad = dfgrd;
180 for (int dd = 0; dd != DIM; ++dd)
181 grad[dd + 3 * dd] -= 1.0;
182
183 if constexpr (MODEL_TYPE == MatOps::MODEL_3D) {
184 strain[0] = grad[0];
185 strain[1] = grad[4];
186 strain[2] = grad[8];
187 strain[3] = grad[1] + grad[3];
188 strain[4] = grad[2] + grad[6];
189 strain[5] = grad[5] + grad[7];
190 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRAIN) {
191 strain[0] = grad[0];
192 strain[1] = grad[4];
193 strain[2] = 0.0;
194 strain[3] = grad[1] + grad[3];
195 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRESS) {
196 strain[0] = grad[0];
197 strain[1] = grad[4];
198 strain[2] = grad[1] + grad[3];
199 } else if constexpr (MODEL_TYPE == MatOps::MODEL_AXISYMMETRIC) {
200 strain[0] = grad[0];
201 strain[1] = grad[4];
202 strain[2] = grad[8];
203 strain[3] = grad[1] + grad[3];
204 } else {
205 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
206 "UMAT strain increment is not implemented for this model type");
207 }
208 };
209
210 std::array<double, NTENS> reference_strain{};
211 std::array<double, NTENS> current_strain{};
212 get_small_strain_voigt(dfgrd0, reference_strain);
213 get_small_strain_voigt(dfgrd1, current_strain);
214
215 for (int ii = 0; ii != NTENS; ++ii) {
216 stran[ii] = reference_strain[ii];
217 dstran[ii] = current_strain[ii] - reference_strain[ii];
218 }
219
221}
222
223template <int MODEL_TYPE>
225 int n_statev, const std::vector<double> &state_var_values) {
227
229}
230
231template <int MODEL_TYPE>
233 MatrixDouble &F) const {
236 for (int row = 0; row != DIM; ++row)
237 for (int col = 0; col != DIM; ++col)
238 F(row, col) = dfgrd1[row + 3 * col];
240}
241
242template <int MODEL_TYPE>
244 MatrixDouble &sigma) const {
246 CHKERR resizeTensor2(sigma);
247 if constexpr (MODEL_TYPE == MatOps::MODEL_3D) {
248 sigma(0, 0) = stress[0];
249 sigma(1, 1) = stress[1];
250 sigma(2, 2) = stress[2];
251 sigma(0, 1) = sigma(1, 0) = stress[3];
252 sigma(0, 2) = sigma(2, 0) = stress[4];
253 sigma(1, 2) = sigma(2, 1) = stress[5];
254 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRAIN ||
255 MODEL_TYPE == MatOps::MODEL_AXISYMMETRIC) {
256 sigma(0, 0) = stress[0];
257 sigma(1, 1) = stress[1];
258 sigma(2, 2) = stress[2];
259 sigma(0, 1) = sigma(1, 0) = stress[3];
260 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRESS) {
261 sigma(0, 0) = stress[0];
262 sigma(1, 1) = stress[1];
263 sigma(0, 1) = sigma(1, 0) = stress[2];
264 } else {
265 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
266 "UMAT stress conversion is not implemented for this model type");
267 }
269}
270
271template <int MODEL_TYPE>
273 MatrixDouble &cauchy_tangent) const {
275 CHKERR resizeTensor4(cauchy_tangent);
276 if constexpr (MODEL_TYPE == MatOps::MODEL_3D) {
277 static const std::array<std::pair<int, int>, 6> pairs = {
278 std::pair<int, int>{0, 0}, {1, 1}, {2, 2}, {0, 1}, {0, 2}, {1, 2}};
279 for (int row = 0; row != 6; ++row) {
280 const auto [i, j] = pairs[row];
281 for (int col = 0; col != 6; ++col) {
282 const auto [k, l] = pairs[col];
283 const double value = ddsdde[row + 6 * col];
284 cauchy_tangent(tensorIndex(i, j), tensorIndex(k, l)) = value;
285 cauchy_tangent(tensorIndex(j, i), tensorIndex(k, l)) = value;
286 cauchy_tangent(tensorIndex(i, j), tensorIndex(l, k)) = value;
287 cauchy_tangent(tensorIndex(j, i), tensorIndex(l, k)) = value;
288 }
289 }
290 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRAIN ||
291 MODEL_TYPE == MatOps::MODEL_AXISYMMETRIC) {
292 static const std::array<std::pair<int, int>, 4> pairs = {
293 std::pair<int, int>{0, 0}, {1, 1}, {2, 2}, {0, 1}};
294 for (int row = 0; row != 4; ++row) {
295 const auto [i, j] = pairs[row];
296 for (int col = 0; col != 4; ++col) {
297 const auto [k, l] = pairs[col];
298 const double value = ddsdde[row + 4 * col];
299 cauchy_tangent(tensorIndex(i, j), tensorIndex(k, l)) = value;
300 cauchy_tangent(tensorIndex(j, i), tensorIndex(k, l)) = value;
301 cauchy_tangent(tensorIndex(i, j), tensorIndex(l, k)) = value;
302 cauchy_tangent(tensorIndex(j, i), tensorIndex(l, k)) = value;
303 }
304 }
305 } else if constexpr (MODEL_TYPE == MatOps::MODEL_2D_PLANE_STRESS) {
306 static const std::array<std::pair<int, int>, 3> pairs = {
307 std::pair<int, int>{0, 0}, {1, 1}, {0, 1}};
308 for (int row = 0; row != 3; ++row) {
309 const auto [i, j] = pairs[row];
310 for (int col = 0; col != 3; ++col) {
311 const auto [k, l] = pairs[col];
312 const double value = ddsdde[row + 3 * col];
313 cauchy_tangent(tensorIndex(i, j), tensorIndex(k, l)) = value;
314 cauchy_tangent(tensorIndex(j, i), tensorIndex(k, l)) = value;
315 cauchy_tangent(tensorIndex(i, j), tensorIndex(l, k)) = value;
316 cauchy_tangent(tensorIndex(j, i), tensorIndex(l, k)) = value;
317 }
318 }
319 } else {
320 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
321 "UMAT tangent conversion is not implemented for this model type");
322 }
324}
325
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_AXISYMMETRIC
Definition MatOps.hpp:196
@ MODEL_3D
Definition MatOps.hpp:193
@ MODEL_2D_PLANE_STRESS
Definition MatOps.hpp:195
@ MODEL_2D_PLANE_STRAIN
Definition MatOps.hpp:194
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 setIdentityRotationIncrement()
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)