OOFEM 3.0
Loading...
Searching...
No Matches
plhoopstresscirc.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
36
37#include "xfem/propagationlaw.h"
38#include "xfem/tipinfo.h"
39#include "classfactory.h"
40#include "mathfem.h"
41#include "dynamicinputrecord.h"
42#include "spatiallocalizer.h"
43#include "floatmatrix.h"
44#include "gausspoint.h"
46#include "xfem/enrichmentitem.h"
47#include "feinterpol.h"
48#include "xfem/xfemmanager.h"
49
50#include "xfem/XFEMDebugTools.h"
51
52namespace oofem {
54
55
56void PLHoopStressCirc :: initializeFrom(InputRecord &ir)
57{
62
63 int useRadialBasisFunc = 0;
65 if ( useRadialBasisFunc == 1 ) {
66 mUseRadialBasisFunc = true;
67 }
68}
69
84
85bool PLHoopStressCirc :: propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp)
86{
87 if ( !iEnrFront.propagationIsAllowed() ) {
88 return false;
89 }
90
91 // Fetch crack tip data
92 const TipInfo &tipInfo = iEnrFront.giveTipInfo();
93
94 SpatialLocalizer *localizer = iDomain.giveSpatialLocalizer();
95
96 // Construct circle points on an arc from -90 to 90 degrees
97 double angle = -90.0 + mAngleInc;
98 std :: vector< double >angles;
99 while ( angle <= ( 90.0 - mAngleInc ) ) {
100 angles.push_back(angle * M_PI / 180.0);
101 angle += mAngleInc;
102 }
103
104 const FloatArray &xT = tipInfo.mGlobalCoord;
105 const FloatArray &t = tipInfo.mTangDir;
106 const FloatArray &n = tipInfo.mNormalDir;
107
108 // It is meaningless to propagate a tip that is not inside any element
109 Element *el = localizer->giveElementContainingPoint(tipInfo.mGlobalCoord);
110 if ( el != NULL ) {
111 std :: vector< FloatArray >circPoints;
112
113 for ( size_t i = 0; i < angles.size(); i++ ) {
114 FloatArray tangent(2);
115 tangent.zero();
116 tangent.add(cos(angles [ i ]), t);
117 tangent.add(sin(angles [ i ]), n);
118 tangent.normalize();
119
120 FloatArray x(xT);
121 x.add(mRadius, tangent);
122 circPoints.push_back(x);
123 }
124
125
126
127 std :: vector< double >sigTTArray, sigRTArray;
128
129 // Loop over circle points
130 for ( size_t pointIndex = 0; pointIndex < circPoints.size(); pointIndex++ ) {
131 FloatArray stressVec;
132
133 if ( mUseRadialBasisFunc ) {
134 // Interpolate stress with radial basis functions
135
136 // Choose a cut-off length l:
137 // take the distance between two nodes in the element containing the
138 // crack tip multiplied by a constant factor.
139 // ( This choice implies that we hope that the element has reasonable
140 // aspect ratio.)
141 const auto &x1 = el->giveDofManager(1)->giveCoordinates();
142 const auto &x2 = el->giveDofManager(2)->giveCoordinates();
143 const double l = 1.0 * distance(x1, x2);
144
145 // Use the octree to get all elements that have
146 // at least one Gauss point in a certain region around the tip.
147 const double searchRadius = 3.0 * l;
148 IntArray elIndices;
149 localizer->giveAllElementsWithIpWithinBox(elIndices, circPoints [ pointIndex ], searchRadius);
150
151
152 // Loop over the elements and Gauss points obtained.
153 // Evaluate the interpolation.
154 FloatArray sumQiWiVi;
155 double sumWiVi = 0.0;
156 for ( int elIndex: elIndices ) {
157 Element *gpEl = iDomain.giveElement(elIndex);
158
159 for ( GaussPoint *gp_i: *gpEl->giveDefaultIntegrationRulePtr() ) {
161 // Compute global gp coordinates
163 FEInterpolation *interp = gpEl->giveInterpolation();
164 interp->evalN( N, gp_i->giveNaturalCoordinates(), FEIElementGeometryWrapper(gpEl) );
165
166
167 // Compute global coordinates of Gauss point
168 FloatArray globalCoord(2);
169 globalCoord.zero();
170
171 for ( int i = 1; i <= gpEl->giveNumberOfDofManagers(); i++ ) {
172 DofManager *dMan = gpEl->giveDofManager(i);
173 globalCoord.at(1) += N.at(i) * dMan->giveCoordinate(1);
174 globalCoord.at(2) += N.at(i) * dMan->giveCoordinate(2);
175 }
176
177
179 // Compute weight of kernel function
180
181 FloatArray tipToGP;
182 tipToGP.beDifferenceOf(globalCoord, xT);
183 bool inFrontOfCrack = true;
184 if ( tipToGP.dotProduct(t) < 0.0 ) {
185 inFrontOfCrack = false;
186 }
187
188 double r = distance(circPoints [ pointIndex ], globalCoord);
189
190 if ( r < l && inFrontOfCrack ) {
191 double w = ( ( l - r ) / ( pow(2.0 * M_PI, 1.5) * pow(l, 3) ) ) * exp( -0.5 * pow(r, 2) / pow(l, 2) );
192
193 // Compute gp volume
194 double V = gpEl->computeVolumeAround(gp_i);
195
196 // Get stress
197 StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp_i->giveMaterialStatus() );
198 if ( ms == NULL ) {
199 OOFEM_ERROR("failed to fetch MaterialStatus.");
200 }
201
202 FloatArray stressVecGP = ms->giveStressVector();
203
204 if ( sumQiWiVi.giveSize() != stressVecGP.giveSize() ) {
205 sumQiWiVi.resize( stressVecGP.giveSize() );
206 sumQiWiVi.zero();
207 }
208
209 // Add to numerator
210 sumQiWiVi.add(w * V, stressVecGP);
211
212 // Add to denominator
213 sumWiVi += w * V;
214 }
215 }
216 }
217
218
219 if ( fabs(sumWiVi) > 1.0e-12 ) {
220 stressVec.beScaled(1.0 / sumWiVi, sumQiWiVi);
221 } else {
222 // Take stress from closest Gauss point
223 int region = 1;
224 bool useCZGP = false;
225 GaussPoint &gp = * ( localizer->giveClosestIP(circPoints [ pointIndex ], region, useCZGP) );
226
227
228 // Compute stresses
230 if ( ms == NULL ) {
231 OOFEM_ERROR("failed to fetch MaterialStatus.");
232 }
233
234 stressVec = ms->giveStressVector();
235 }
236 } else {
237 // Take stress from closest Gauss point
238 int region = 1;
239 bool useCZGP = false;
240 GaussPoint &gp = * ( localizer->giveClosestIP(circPoints [ pointIndex ], region, useCZGP) );
241
242
243 // Compute stresses
245 if ( ms == NULL ) {
246 OOFEM_ERROR("failed to fetch MaterialStatus.");
247 }
248
249 stressVec = ms->giveStressVector();
250 }
251
252 FloatMatrix stress(2, 2);
253
254 int shearPos = stressVec.giveSize();
255
256 stress.at(1, 1) = stressVec.at(1);
257 stress.at(1, 2) = stressVec.at(shearPos);
258 stress.at(2, 1) = stressVec.at(shearPos);
259 stress.at(2, 2) = stressVec.at(2);
260
261
262 // Rotation matrix
263 FloatMatrix rot(2, 2);
264 rot.at(1, 1) = cos(angles [ pointIndex ]);
265 rot.at(1, 2) = -sin(angles [ pointIndex ]);
266 rot.at(2, 1) = sin(angles [ pointIndex ]);
267 rot.at(2, 2) = cos(angles [ pointIndex ]);
268
269 FloatArray tRot, nRot;
270 tRot.beProductOf(rot, t);
271 nRot.beProductOf(rot, n);
272
273 FloatMatrix rotTot(2, 2);
274 rotTot.setColumn(tRot, 1);
275 rotTot.setColumn(nRot, 2);
276
277
278 FloatMatrix tmp, stressRot;
279
280 tmp.beTProductOf(rotTot, stress);
281 stressRot.beProductOf(tmp, rotTot);
282
283
284 const double sigThetaTheta = stressRot.at(2, 2);
285 sigTTArray.push_back(sigThetaTheta);
286
287 const double sigRTheta = stressRot.at(1, 2);
288 sigRTArray.push_back(sigRTheta);
289 }
290
292 // Compute propagation angle
293
294 // Find angles that fulfill sigRT = 0
295 const double stressTol = 1.0e-9;
296 double maxSigTT = 0.0, maxAngle = 0.0;
297 bool foundZeroLevel = false;
298 for ( size_t segIndex = 0; segIndex < ( circPoints.size() - 1 ); segIndex++ ) {
299 // If the shear stress sigRT changes sign over the segment
300 if ( sigRTArray [ segIndex ] * sigRTArray [ segIndex + 1 ] < stressTol ) {
301 // Compute location of zero level
302 double xi = EnrichmentItem :: calcXiZeroLevel(sigRTArray [ segIndex ], sigRTArray [ segIndex + 1 ]);
303
304 double theta = 0.5 * ( 1.0 - xi ) * angles [ segIndex ] + 0.5 * ( 1.0 + xi ) * angles [ segIndex + 1 ];
305 double sigThetaTheta = 0.5 * ( 1.0 - xi ) * sigTTArray [ segIndex ] + 0.5 * ( 1.0 + xi ) * sigTTArray [ segIndex + 1 ];
306
307 //printf("Found candidate: theta: %e sigThetaTheta: %e\n", theta, sigThetaTheta);
308
309 if ( sigThetaTheta > maxSigTT ) {
310 foundZeroLevel = true;
311 maxSigTT = sigThetaTheta;
312 maxAngle = theta;
313 }
314 }
315 }
316
317 if ( !foundZeroLevel ) {
318 return false;
319 }
320
321 if ( iDomain.giveXfemManager()->giveVtkDebug() ) {
322 XFEMDebugTools :: WriteArrayToMatlab("sigTTvsAngle.m", angles, sigTTArray);
323 XFEMDebugTools :: WriteArrayToMatlab("sigRTvsAngle.m", angles, sigRTArray);
324
325 XFEMDebugTools :: WriteArrayToGnuplot("sigTTvsAngle.dat", angles, sigTTArray);
326 XFEMDebugTools :: WriteArrayToGnuplot("sigRTvsAngle.dat", angles, sigRTArray);
327 }
328
329 // Compare with threshold
330 printf("maxSigTT: %e mHoopStressThreshold: %e\n", maxSigTT, mHoopStressThreshold);
331 if ( maxSigTT > mHoopStressThreshold && foundZeroLevel ) {
332 // Rotation matrix
333 FloatMatrix rot(2, 2);
334 rot.at(1, 1) = cos(maxAngle);
335 rot.at(1, 2) = -sin(maxAngle);
336 rot.at(2, 1) = sin(maxAngle);
337 rot.at(2, 2) = cos(maxAngle);
338
339 FloatArray dir;
340 dir.beProductOf(rot, tipInfo.mTangDir);
341
342 // Fill up struct
343 oTipProp.mTipIndex = tipInfo.mTipIndex;
344 oTipProp.mPropagationDir = dir;
346
347 return true;
348 }
349 }
350
351
352 return false;
353}
354} // end namespace oofem
#define N(a, b)
#define REGISTER_PropagationLaw(class)
double giveCoordinate(int i) const
Definition dofmanager.h:383
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
SpatialLocalizer * giveSpatialLocalizer()
Definition domain.C:1255
Element * giveElement(int n)
Definition domain.C:165
XfemManager * giveXfemManager()
Definition domain.C:378
void setRecordKeywordField(std ::string keyword, int number)
void setField(int item, InputFieldType id)
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
virtual int giveNumberOfDofManagers() const
Definition element.h:695
DofManager * giveDofManager(int i) const
Definition element.C:553
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Definition element.h:886
virtual double computeVolumeAround(GaussPoint *gp)
Definition element.h:530
const TipInfo & giveTipInfo() const
virtual bool propagationIsAllowed() const
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Definition floatarray.C:403
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void beScaled(double s, const FloatArray &b)
Definition floatarray.C:208
void add(const FloatArray &src)
Definition floatarray.C:218
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void setColumn(const FloatArray &src, int c)
double at(std::size_t i, std::size_t j) const
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
IntegrationPointStatus * giveMaterialStatus(IntegrationPointStatusIDType key=IPSID_Default)
Definition gausspoint.h:204
const char * giveInputRecordName() const override
virtual GaussPoint * giveClosestIP(const FloatArray &coords, int region, bool iCohesiveZoneGP=false)=0
virtual Element * giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList=nullptr)=0
virtual void giveAllElementsWithIpWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius)=0
const FloatArray & giveStressVector() const
Returns the const pointer to receiver's stress vector.
FloatArray mTangDir
Definition tipinfo.h:32
FloatArray mNormalDir
Definition tipinfo.h:33
FloatArray mGlobalCoord
Definition tipinfo.h:30
bool giveVtkDebug() const
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define M_PI
Definition mathfem.h:52
double distance(const FloatArray &x, const FloatArray &y)
#define _IFT_PLHoopStressCirc_AngleInc
Angle between sampling points on the circle.
#define _IFT_PLHoopStressCirc_RadialBasisFunc
If radial basis functions should be used for stress interpolation.
#define _IFT_PLHoopStressCirc_Radius
Radius of circle used for stress sampling points.
#define _IFT_PLHoopStressCirc_IncLength
Increment length per time step.
#define _IFT_PLHoopStressCirc_HoopStressThreshold
Threshold for crack propagation.
double mPropagationLength
Definition tipinfo.h:45
FloatArray mPropagationDir
Definition tipinfo.h:44

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