OOFEM 3.0
Loading...
Searching...
No Matches
mfrontusermaterial.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
35// Use the following flags and specify location of the cmake files.
36// cmake -DUSE_MFRONT=ON -DMFrontGenericInterface_DIR=/usr/local/share/mgis/cmake/ ..
37
38#include "mfrontusermaterial.h"
39#include "gausspoint.h"
40#include "floatarrayf.h"
41#include "floatmatrixf.h"
42#include "classfactory.h"
43#include "dynamicinputrecord.h"
44
45#ifdef _WIN32 //_MSC_VER and __MINGW32__ included
46 #include <Windows.h>
47#else
48 #include <dlfcn.h>
49#endif
50
51#include <cstring>
52
53namespace oofem {
55
56// eventual reindexing
57int const MFrontUserMaterial :: mfront2oo9[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
58int const MFrontUserMaterial :: mfront2oo6[6] = {0, 1, 2, 3, 4, 5};
59
60MFrontUserMaterial :: MFrontUserMaterial(int n, Domain *d) : StructuralMaterial(n, d) {}
61
62MFrontUserMaterial :: ~MFrontUserMaterial()
63{
64
65}
66
67void MFrontUserMaterial :: initializeFrom(InputRecord &ir)
68{
69 using namespace mgis::behaviour;
70
71 StructuralMaterial :: initializeFrom(ir);
72
73
74 FloatArray s(6);
75 this->initialStress = s;
76
77 std :: string libname;
78 std :: string modelname;
81 strncpy(this->libname, libname.c_str(), 199);
82 strncpy(this->modelname, modelname.c_str(), 199);
83 // loading the MFront library using MGIS
84 this->behaviour = std::make_unique<Behaviour>(load(this->libname, this->modelname, Hypothesis::TRIDIMENSIONAL));
85 // initialize material properties from user data
87 // check that the number of material properties given by the user is correct
88 const auto nprops = mgis::behaviour::getArraySize(this->behaviour->mps, this->behaviour->hypothesis);
89 if (this->properties.giveSize() != nprops) {
90 throw(std::runtime_error("wrong number of material properties"));
91 }
92 // treating the case for external state variables
93 const auto nesvs = mgis::behaviour::getArraySize(this->behaviour->esvs, this->behaviour->hypothesis);
94 if (nesvs != 1) {
95 throw(std::runtime_error("wrong number of external state variables"));
96 }
97 if (this->behaviour->esvs[0].name != "Temperature") {
98 throw(std::runtime_error("the temperature is the only external state variable supported so far"));
99 }
100
101}
102
103void MFrontUserMaterial :: giveInputRecord(DynamicInputRecord &input)
104{
105 StructuralMaterial :: giveInputRecord(input);
106}
107
108MaterialStatus *MFrontUserMaterial :: CreateStatus(GaussPoint *gp) const
109{
110 return new MFrontUserMaterialStatus(gp, *(this->behaviour));
111}
112
113
115MFrontUserMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
116{
117 auto ms = dynamic_cast< MFrontUserMaterialStatus * >( this->giveStatus(gp) );
118 if (!ms->hasTangent()) {
119 // Evaluating the function once, so that the tangent can be obtained.
120 const_cast<MFrontUserMaterial*>(this)->giveRealStressVector_3d(zeros<6>(), gp, tStep);
121 }
122
123 double h = mPerturbation;
124 FloatArray strain, strainh, stress, stressh;
125 strain = static_cast<StructuralMaterialStatus *>(gp->giveMaterialStatus())->giveTempStrainVector();
126 stress = static_cast<StructuralMaterialStatus *>(gp->giveMaterialStatus())->giveTempStressVector();
127 FloatMatrix En(strain.giveSize(), strain.giveSize());
128 for (int i = 1; i <= strain.giveSize(); ++i) {
129 strainh = strain;
130 strainh.at(i) += h;
131 stressh = this->giveRealStressVector_3d(strainh, gp, tStep);
132 stressh.subtract(stress);
133 stressh.times(1.0 / h);
134 En.setColumn(stressh, i);
135 }
136 stress = this->giveRealStressVector_3d(strain, gp, tStep);
137
138 return En;
139}
140
141
143MFrontUserMaterial :: give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
144{
145 auto ms = dynamic_cast<MFrontUserMaterialStatus * >(this->giveStatus(gp));
146 if (!ms->hasTangent()) {
147 // Evaluating the function once, so that the tangent can be obtained.
148 const auto &vF = ms->giveTempFVector();
149 this->giveFirstPKStressVector_3d(vF, gp, tStep);
150 }
151
152 double h = mPerturbation;
153 auto const &vF = ms->giveTempFVector();
154 auto const &stress = ms->giveTempPVector();
156 for ( int i = 1; i <= 9; ++i ) {
157 auto vF_h = vF;
158 vF_h.at(i) += h;
159 auto stressh = this->giveFirstPKStressVector_3d(vF_h, gp, tStep);
160 auto ds = (stressh - stress) * (1. / h);
161 En.setColumn(ds, i);
162 }
163
164 // Reset
165 this->giveFirstPKStressVector_3d(vF, gp, tStep);
166
167 return En;
168}
169
171MFrontUserMaterial :: givePlaneStrainStiffMtrx_dPdF(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const
172{
173 auto dPdF3D = this->give3dMaterialStiffnessMatrix_dPdF(mmode, gp, tStep);
174 return dPdF3D({0, 1, 2, 5, 8}, {0, 1, 2, 5, 8});
175}
176
177
179MFrontUserMaterial :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const
180{
181 auto ms = static_cast< MFrontUserMaterialStatus * >( this->giveStatus(gp) );
182
183 FloatArrayF<6> old_strain = ms->giveStrainVector();
184 FloatArrayF<6> old_stress = initialStress + ms->giveStressVector();
185
186 auto old_state = ms->giveStateVector();
187 auto new_state = old_state;
188 FloatMatrixF<6,6> mfront_jacobian;
189
190 // Times and increment
191 double dtime = tStep->giveTimeIncrement();
192
193 // Change the component order
194 auto mfront_stress = old_stress[mfront2oo6];
195 auto mfront_old_strain = old_strain[mfront2oo6];
196 auto mfront_new_strain = strain[mfront2oo6];
197
198 // Beware of MFront conventions here !!!!
199 mfront_stress[3] *= 2.;
200 mfront_stress[4] *= 2.;
201 mfront_stress[5] *= 2.;
202 mfront_old_strain[3] /= 2.;
203 mfront_old_strain[4] /= 2.;
204 mfront_old_strain[5] /= 2.;
205 mfront_new_strain[3] /= 2.;
206 mfront_new_strain[4] /= 2.;
207 mfront_new_strain[5] /= 2.;
208
209 //
210 double externalStateVariables[1] = {293.15};
211 double stored_energy = 0;
212 double dissipated_energy = 0;
213
214 mgis::behaviour::BehaviourDataView v;
215 v.dt = dtime;
216
217// modifications du to API changes in MGIS
218#ifdef MGIS_BEHAVIOUR_API_VERSION
219#if MGIS_BEHAVIOUR_API_VERSION == 1
220 auto rdt = double{};
221 v.rdt = &rdt;
222 v.speed_of_sound = nullptr;
223#else /* MGIS_BEHAVIOUR_API_VERSION == 1 */
224#error "Unsupported MGIS' behaviour API"
225#endif /* MGIS_BEHAVIOUR_API_VERSION == 1 */
226#else /* MGIS_BEHAVIOUR_API_VERSION */
227 v.rdt = 1;
228#endif /* MGIS_BEHAVIOUR_API_VERSION */
229
230 v.K = &mfront_jacobian(0, 0);
231 // perform an integration with computation of the consistent tangent operator
232 v.K[0] = 4;
233 // setting the initial state
234 v.s0.gradients = &mfront_old_strain[0];
235 v.s0.thermodynamic_forces = &old_stress[0];
236 v.s0.material_properties = nullptr; // &(this->properties[0])
237 v.s0.internal_state_variables = &old_state[0]; // shall be null if numState==0
238 v.s0.external_state_variables = externalStateVariables;
239 v.s0.stored_energy = &stored_energy;
240 v.s0.dissipated_energy = &dissipated_energy;
241 // setting the state at the end of the time step
242 v.s1.gradients = &mfront_new_strain[0];
243 v.s1.thermodynamic_forces = &mfront_stress[0];
244 v.s1.material_properties = nullptr; // &(this->properties[0])
245 v.s1.internal_state_variables = &new_state[0]; // shall be null if numState==0
246 v.s1.external_state_variables = externalStateVariables;
247 v.s1.stored_energy = &stored_energy;
248 v.s1.dissipated_energy = &dissipated_energy;
249
250 integrate(v, *(this->behaviour));
251
252 // Change to OOFEM's component order
253 auto jacobian = mfront_jacobian(mfront2oo6, mfront2oo6);
254 // subtracking the initial stress
255 auto stress = mfront_stress[mfront2oo6] - initialStress;
256 // Here MFront->OOFEM conventions for the strain **and** the jacobian
257 //
258
259 ms->letTempStrainVectorBe(strain);
260 ms->letTempStressVectorBe(stress);
261 ms->letTempStateVectorBe(new_state);
262 ms->letTempTangentBe(jacobian);
263 return stress;
264}
265
266
267int MFrontUserMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
268{
269 auto ms = static_cast<MFrontUserMaterialStatus *>(this->giveStatus(gp));
270 if ( type == IST_Undefined || type == IST_AbaqusStateVector ) {
271 // The undefined value is used to just dump the entire state vector.
272 answer = ms->giveStateVector();
273 return 1;
274 } else if (type == IST_StressTensor) {
275 answer = ms->giveStressVector();
276 answer.add(initialStress);
277 return 1;
278 } else {
279 return StructuralMaterial :: giveIPValue(answer, gp, type, tStep);
280 }
281}
282
283void MFrontUserMaterialStatus :: initTempStatus()
284{
285 StructuralMaterialStatus :: initTempStatus();
287}
288
289MFrontUserMaterialStatus :: MFrontUserMaterialStatus(GaussPoint *gp, const mgis::behaviour::Behaviour &b) :
291{
292 strainVector.resize(6);
293 strainVector.zero();
294 // getting number of state variables
295 const auto numState = mgis::behaviour::getArraySize(b.isvs, b.hypothesis);
296 // allocating number of state variables
297 this->stateVector.resize(numState);
298 this->tempStateVector.resize(numState);
299 this->stateVector.zero(); // ??
300 this->tempStateVector.zero(); // ??
301}
302
303void MFrontUserMaterialStatus :: updateYourself(TimeStep *tStep)
304{
305 StructuralMaterialStatus :: updateYourself(tStep);
307}
308
309void MFrontUserMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) const
310{
311 StructuralMaterialStatus :: printOutputAt(File, tStep);
312
313 fprintf(File, " stateVector ");
314 FloatArray state = this->giveStateVector();
315 for ( auto &var : state ) {
316 fprintf( File, " % .4e", var );
317 }
318
319 fprintf(File, "\n");
320}
321
322} // end namespace oofem
#define REGISTER_Material(class)
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void add(const FloatArray &src)
Definition floatarray.C:218
void subtract(const FloatArray &src)
Definition floatarray.C:320
void times(double s)
Definition floatarray.C:834
void setColumn(const FloatArrayF< N > &src, std::size_t c)
void setColumn(const FloatArray &src, int c)
IntegrationPointStatus * giveMaterialStatus(IntegrationPointStatusIDType key=IPSID_Default)
Definition gausspoint.h:204
GaussPoint * gp
Associated integration point.
FloatArray stateVector
General state vector.
const FloatArray & giveStateVector() const
bool hasTangentFlag
Checker to see if tangent has been computed.
FloatArray tempStateVector
Temporary state vector.
std::unique_ptr< mgis::behaviour::Behaviour > behaviour
pointer to the MGIS behaviour
FloatArrayF< 6 > giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const override
Default implementation relies on giveRealStressVector for second Piola-Kirchoff stress.
static int const mfront2oo6[6]
MFrontUserMaterial(int n, Domain *d)
Constructor.
FloatArray properties
Material properties.
FloatArrayF< 6 > initialStress
Initial stress.
FloatMatrixF< 9, 9 > give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Definition material.C:206
const FloatArray & giveTempStressVector() const
Returns the const pointer to receiver's temporary stress vector.
StructuralMaterialStatus(GaussPoint *g)
Constructor. Creates new StructuralMaterialStatus with IntegrationPoint g.
const FloatArray & giveTempStrainVector() const
Returns the const pointer to receiver's temporary strain vector.
FloatArray strainVector
Equilibrated strain vector in reduced form.
StructuralMaterial(int n, Domain *d)
virtual FloatArrayF< 9 > giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const
Default implementation relies on giveRealStressVector for second Piola-Kirchoff stress.
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define _IFT_MFrontUserMaterial_properties
#define _IFT_MFrontUserMaterial_libpath
#define _IFT_MFrontUserMaterial_modelname
FloatArrayF< N > zeros()
For more readable code.

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011