OOFEM 3.0
Loading...
Searching...
No Matches
structuralpythonmaterial.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#include <Python.h>
36
38#include "gausspoint.h"
39#include "classfactory.h"
40#include "dynamicinputrecord.h"
41
42namespace oofem {
44
45StructuralPythonMaterial :: StructuralPythonMaterial(int n, Domain *d) :
47{}
48
49
50void StructuralPythonMaterial :: initializeFrom(InputRecord &ir)
51{
52 StructuralMaterial :: initializeFrom(ir);
53
55
56 module = bp::import(moduleName.c_str());
57 if ( !module ) {
58 throw ValueInputException(ir, _IFT_StructuralPythonMaterial_moduleName, "Module not importable.");
59 }
60 // lambda for finding function and checking that it is callable
61 // returns true (OK) if the function was not found, or was found and it callable
62 // returns false (not OK) if the function was found but is not callable
63 auto tryDef=[&](const std::string& attr, bp::object& callable)->bool{
64 if(PyObject_HasAttrString(module.ptr(),attr.c_str())){
65 callable=module.attr(attr.c_str());
66 if(!PyCallable_Check(callable.ptr())){ OOFEM_WARNING("Object %s is not callable",attr.c_str()); return false; }
67 } else callable=bp::object();
68 return true;
69 };
70 // try to find all necessary functions; false means the function is not callable, in which case warning was already printed above
71 if ( !(tryDef("computeStress",smallDef) && tryDef("computePK1Stress",largeDef) && tryDef("computeStressTangent",smallDefTangent) && tryDef("computePK1StressTangent",largeDefTangent))) {
73 }
74 if ( !smallDefTangent && !!smallDef ){ OOFEM_WARNING("Using numerical tangent for small deformations."); }
75 if ( !largeDefTangent && !!largeDef ){ OOFEM_WARNING("Using numerical tangent for large deformations."); }
76 if ( !smallDef && !largeDef ) {
77 throw ValueInputException(ir, _IFT_StructuralPythonMaterial_moduleName, "No functions for small/large deformations found.");
78 }
79
80 pert = 1e-12;
81}
82
83void StructuralPythonMaterial :: giveInputRecord(DynamicInputRecord &input)
84{
85 StructuralMaterial :: giveInputRecord(input);
86
88}
89
90MaterialStatus *StructuralPythonMaterial :: CreateStatus(GaussPoint *gp) const
91{
92 return new StructuralPythonMaterialStatus(gp);
93}
94
95FloatArray StructuralPythonMaterial :: callStressFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, const FloatArray &strain, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const
96{
97 // pass mutable args via bp::ref
98 // pass "const" args without, which by default results in a new copy, ensuring the original won't be modified
99 return bp::extract<FloatArray>(func(oldStrain, oldStress, strain, stateDict, tempStateDict, tStep->giveTargetTime()));
100}
101
102FloatMatrix StructuralPythonMaterial :: callTangentFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const
103{
104 return bp::extract<FloatMatrix>(func(oldStrain, oldStress, stateDict, tempStateDict, tStep->giveTargetTime()));
105}
106
107void StructuralPythonMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
108{
110
111 if ( this->smallDefTangent ) {
113 } else {
114 FloatArray vE_h, stress, stressh;
115 const auto &vE = ms->giveTempStrainVector();
116// const auto &stress = ms->giveTempStressVector();
117 stress = ms->giveTempStressVector();
118 answer.resize(6, 6);
119 for ( int i = 1; i <= 6; ++i ) {
120 vE_h = vE;
121 vE_h.at(i) += pert;
122 this->giveRealStressVector_3d(stressh, gp, vE_h, tStep);
123 stressh.subtract(stress);
124 stressh.times(1.0 / pert);
125 answer.setColumn(stressh, i);
126 }
127
128 // Reset the stress internal variables
129 this->giveRealStressVector_3d(stress, gp, vE, tStep);
130 }
131}
132
133
134FloatMatrixF<9,9> StructuralPythonMaterial :: give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const
135{
137
138 if ( this->largeDefTangent ) {
140 } else {
141 const FloatArrayF<9> vF = ms->giveTempFVector();
142 const FloatArrayF<9> vP = ms->giveTempPVector();
143 FloatMatrixF<9,9> tangent;
144 for ( int i = 1; i <= 9; ++i ) {
145 auto vF_h = vF;
146 vF_h.at(i) += pert;
147 auto vPh = this->giveFirstPKStressVector_3d(vF_h, gp, tStep);
148 auto dvP = (vPh - vP) / pert;
149 tangent.setColumn(dvP, i);
150 }
151
152 // Reset the internal variables
153 this->giveFirstPKStressVector_3d(vF, gp, tStep);
154 return tangent;
155 }
156}
157
158
159void StructuralPythonMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp,
160 const FloatArray &strain, TimeStep *tStep)
161{
162 auto ms = static_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) );
163
165
166 answer = this->callStressFunction(this->smallDef,
167 ms->giveStrainVector(), ms->giveStressVector(), strain,
168 ms->giveStateDictionary(), ms->giveTempStateDictionary(), tStep);
169
170 ms->letTempStrainVectorBe(strain);
171 ms->letTempStressVectorBe(answer);
172}
173
174
175FloatArrayF<9> StructuralPythonMaterial :: giveFirstPKStressVector_3d(const FloatArrayF<9> &vF, GaussPoint *gp, TimeStep *tStep) const
176{
177 auto ms = static_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) );
178
179 ms->reinitTempStateDictionary(); // Resets the temp dictionary to the equilibrated values
180
181 auto vP = this->callStressFunction(this->smallDef,
182 ms->giveFVector(), ms->givePVector(), vF,
183 ms->giveStateDictionary(), ms->giveTempStateDictionary(), tStep);
184
185 auto F = from_voigt_form(vF);
186 auto Finv = inv(F);
187 auto E = 0.5 * (Tdot(F, F) - eye<3>());
188 auto vE = to_voigt_strain(E);
189 // Convert from P to S
190 auto P = from_voigt_form(vP);
191 auto S = dot(Finv, P);
192 auto vS = to_voigt_stress(S);
193
194 ms->letTempStrainVectorBe(vE);
195 ms->letTempStressVectorBe(vS);
196 ms->letTempPVectorBe(vP);
197 ms->letTempFVectorBe(vF);
198
199 return vF;//TODO - Check what is returned
200}
201
202
203int StructuralPythonMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
204{
205 auto ms = static_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) );
206 bp::object val = ms->giveStateDictionary()[std::to_string(type).c_str()];
207 // call parent if we don't have this type in our records
208 if ( !val ) {
209 return StructuralMaterial::giveIPValue(answer, gp, type, tStep);
210 }
211 bp::extract<double> exNum(val);
212 bp::extract<FloatArray> exMat(val);
213 if ( exNum.check() ) {
214 answer = FloatArray{exNum()};
215 return 1;
216 } else if ( exMat.check() ) {
217 answer=exMat();
218 return 1;
219 }
220 OOFEM_WARNING("Dictionary entry of material state not float or something convertible to FloatArray");
221 return 0;
222}
223
224
225
226
227
228void StructuralPythonMaterialStatus :: initTempStatus()
229{
230 StructuralMaterialStatus :: initTempStatus();
232}
233
234
235StructuralPythonMaterialStatus :: StructuralPythonMaterialStatus(GaussPoint *gp) :
237{
238}
239
240
241void StructuralPythonMaterialStatus :: updateYourself(TimeStep *tStep)
242{
243 StructuralMaterialStatus :: updateYourself(tStep);
244 // Copy the temp dict to the equilibrated one
245 this->stateDict = this->tempStateDict.copy();
246}
247
248
249void StructuralPythonMaterialStatus :: reinitTempStateDictionary()
250{
251 tempStateDict = stateDict.copy();
252}
253
254
255} // end namespace oofem
#define E(a, b)
#define REGISTER_Material(class)
void setField(int item, InputFieldType id)
double & at(std::size_t i)
double & at(Index i)
Definition floatarray.h:202
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 resize(Index rows, Index cols)
Definition floatmatrix.C:79
void setColumn(const FloatArray &src, int c)
GaussPoint * gp
Associated integration point.
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Definition material.C:206
const FloatArray & giveTempFVector() const
Returns the const pointer to receiver's temporary deformation gradient vector.
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 & giveTempPVector() const
Returns the const pointer to receiver's temporary first Piola-Kirchhoff stress vector.
const FloatArray & giveTempStrainVector() const
Returns the const pointer to receiver's temporary strain vector.
StructuralMaterial(int n, Domain *d)
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
bp::dict stateDict
Internal state variables.
bp::object module
module containing functions (created from moduleName)
FloatArrayF< 9 > giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const override
Default implementation relies on giveRealStressVector for second Piola-Kirchoff stress.
std::string moduleName
Name of the file that contains the python function.
FloatMatrix callTangentFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const
double pert
Numerical pertubation for numerical tangents.
void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep)
bp::object smallDef
callable for small deformations
FloatArray callStressFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, const FloatArray &strain, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const
double giveTargetTime()
Returns target time.
Definition timestep.h:164
#define OOFEM_WARNING(...)
Definition error.h:80
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define S(p)
Definition mdm.C:469
FloatMatrixF< N, P > Tdot(const FloatMatrixF< M, N > &a, const FloatMatrixF< M, P > &b)
Computes .
double dot(const FloatArray &x, const FloatArray &y)
FloatMatrixF< N, N > inv(const FloatMatrixF< N, N > &mat, double zeropiv=1e-24)
Computes the inverse.
FloatMatrixF< N, N > eye()
Constructs an identity matrix.
#define _IFT_StructuralPythonMaterial_moduleName

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