OOFEM 3.0
Loading...
Searching...
No Matches
enrichmentitem.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 "xfemmanager.h"
36#include "floatmatrix.h"
37#include "enrichmentitem.h"
38#include "element.h"
39#include "enrichmentfunction.h"
40#include "cltypes.h"
41#include "connectivitytable.h"
42#include "classfactory.h"
43#include "fracturemanager.h"
44#include "mathfem.h"
45#include "feinterpol.h"
46#include "masterdof.h"
47#include "propagationlaw.h"
48#include "dynamicinputrecord.h"
49#include "XFEMDebugTools.h"
50#include "xfemtolerances.h"
51#include "spatiallocalizer.h"
52#include "gausspoint.h"
55#include "engngm.h"
56
57#include <algorithm>
58#include <limits>
59#include <sstream>
60#include <string>
61
62
63namespace oofem {
64const double EnrichmentItem :: mLevelSetTol = 1.0e-12;
65const double EnrichmentItem :: mLevelSetRelTol = 1.0e-3;
66
67
68EnrichmentItem :: EnrichmentItem(int n, XfemManager *xMan, Domain *aDomain) : FEMComponent(n, aDomain),
77 mLevelSetTol2(1.0e-12)
78{}
79
80EnrichmentItem :: ~EnrichmentItem()
81{
82}
83
84void EnrichmentItem :: initializeFrom(InputRecord &ir)
85{
86 thisIr=ir.clone();
87 mEnrFrontIndex = ir.giveGroupCount(_IFT_EnrichmentItem_front,"EnrichmentFront",/*optional*/true);
88 mPropLawIndex = ir.hasChild(_IFT_EnrichmentItem_propagationlaw,"PropagationLaw",/*optional*/true);
89
92 }
95 }
96}
97
98
99int
100EnrichmentItem :: giveDofPoolSize() const
101{
102 return this->giveEnrichesDofsWithIdArray()->giveSize() * this->giveNumberOfEnrDofs();
103}
104
105int
106EnrichmentItem :: giveNumberOfEnrDofs() const
107{
108 int numEnrDofs = mpEnrichmentFunc->giveNumberOfDofs();
109
111 numEnrDofs = max( numEnrDofs, mpEnrichmentFrontStart->giveMaxNumEnrichments() );
112 }
113
114 if ( mpEnrichmentFrontEnd ) {
115 numEnrDofs = max( numEnrDofs, mpEnrichmentFrontEnd->giveMaxNumEnrichments() );
116 }
117
118 return numEnrDofs;
119}
120
121bool EnrichmentItem :: isElementEnriched(const Element *element) const
122{
123 for ( int i = 1; i <= element->giveNumberOfDofManagers(); i++ ) {
124 if ( this->isDofManEnriched( * ( element->giveDofManager(i) ) ) ) {
125 return true;
126 }
127 }
128
129 return false;
130}
131
132int EnrichmentItem :: giveNumDofManEnrichments(const DofManager &iDMan) const
133{
134 int nodeInd = iDMan.giveGlobalNumber();
135 auto res = mNodeEnrMarkerMap.find(nodeInd);
136
137 if ( res != mNodeEnrMarkerMap.end() ) {
138 switch ( res->second ) {
139 case NodeEnr_NONE:
140 return 0;
141
142 break;
143 case NodeEnr_BULK:
144 return 1;
145
146 break;
148 return mpEnrichmentFrontStart->giveNumEnrichments(iDMan);
149
150 break;
151 case NodeEnr_END_TIP:
152 return mpEnrichmentFrontEnd->giveNumEnrichments(iDMan);
153
154 break;
156 return mpEnrichmentFrontStart->giveNumEnrichments(iDMan) + mpEnrichmentFrontEnd->giveNumEnrichments(iDMan);
157
158 break;
159 }
160 }
161
162 return 0;
163}
164
165bool EnrichmentItem :: isMaterialModified(GaussPoint &iGP, Element &iEl, CrossSection * &opCS) const
166{
167 return false;
168}
169
170bool EnrichmentItem :: hasPropagatingFronts() const
171{
172 if ( mpPropagationLaw == nullptr ) {
173 return false;
174 }
175
176 return mpPropagationLaw->hasPropagation();
177}
178
179void
180EnrichmentItem :: computeEnrichedDofManDofIdArray(IntArray &oDofIdArray, DofManager &iDMan)
181{
182 // Gives an array containing the dofId's that
183 // are candidates for enrichment. At the moment,
184 // regular dofs are considered as candidates. In
185 // the future, we may also consider enriching
186 // enriched dofs from other enrichment items.
187 const IntArray *enrichesDofsWithIdArray = this->giveEnrichesDofsWithIdArray();
188
189 // Number of candidates for enrichment
190 int numEnrCand = enrichesDofsWithIdArray->giveSize();
191
192 // Number of active enrichment functions
193 int numEnrFunc = this->giveNumDofManEnrichments(iDMan);
194
195 // Go through the list of dofs that the EI supports
196 // and compare with the available dofs in the dofMan.
197 int count = 0;
198
199 for ( int i = 1; i <= numEnrFunc; i++ ) {
200 for ( int j = 1; j <= numEnrCand; j++ ) {
201 if ( iDMan.hasDofID( ( DofIDItem ) enrichesDofsWithIdArray->at(j) ) ) {
202 count++;
203 }
204 }
205 }
206
207 oDofIdArray.resize(count);
208 for ( int i = 1; i <= count; i++ ) {
209 oDofIdArray.at(i) = this->giveStartOfDofIdPool() + i - 1;
210 }
211}
212
213void
214EnrichmentItem :: giveEIDofIdArray(IntArray &answer) const
215{
216 // Returns an array containing the dof Id's of the new enrichment dofs pertinent to the ei.
217 // Note: the dof managers may not support these dofs/all potential dof id's
218 const IntArray *enrichesDofsWithIdArray = this->giveEnrichesDofsWithIdArray();
219 int eiEnrSize = enrichesDofsWithIdArray->giveSize(); // Not necessarily true: for example, we may add 8 enrichments (4 in x and 4 in y) at a crack tip where we enrich D_u and D_v. /ES
220
221 answer.resize(eiEnrSize);
222 for ( int i = 1; i <= eiEnrSize; i++ ) {
223 answer.at(i) = this->giveStartOfDofIdPool() + i - 1;
224 }
225}
226
227void EnrichmentItem :: givePotentialEIDofIdArray(IntArray &answer) const {
228 answer.clear();
229 for ( int i = this->giveStartOfDofIdPool(); i <= this->giveEndOfDofIdPool(); i++ ) {
230 answer.followedBy(i);
231 }
232}
233
234bool EnrichmentItem :: evalLevelSetNormalInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
235{
236 auto res = mLevelSetNormalDirMap.find(iNodeInd);
237 if ( res != mLevelSetNormalDirMap.end() ) {
238 oLevelSet = res->second;
239 return true;
240 } else {
241 oLevelSet = 0.0;
242 return false;
243 }
244}
245
246bool EnrichmentItem :: evalLevelSetTangInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
247{
248 auto res = mLevelSetTangDirMap.find(iNodeInd);
249 if ( res != mLevelSetTangDirMap.end() ) {
250 oLevelSet = res->second;
251 return true;
252 } else {
253 oLevelSet = 0.0;
254 return false;
255 }
256}
257
258bool EnrichmentItem :: evalNodeEnrMarkerInNode(double &oNodeEnrMarker, int iNodeInd) const
259{
260 auto res = mNodeEnrMarkerMap.find(iNodeInd);
261 if ( res != mNodeEnrMarkerMap.end() ) {
262 oNodeEnrMarker = double( res->second );
263 return true;
264 } else {
265 oNodeEnrMarker = 0.0;
266 return false;
267 }
268}
269
270void EnrichmentItem :: createEnrichedDofs()
271{
272 // Creates new dofs due to the enrichment and appends them to the dof managers
273
274 int nrDofMan = this->giveDomain()->giveNumberOfDofManagers();
275 IntArray EnrDofIdArray;
276
277 mEIDofIdArray.clear();
278
279 //int bcIndex = -1;
280 int icIndex = -1;
281
282 // Create new dofs
283 for ( int i = 1; i <= nrDofMan; i++ ) {
284 DofManager *dMan = this->giveDomain()->giveDofManager(i);
285
286 if ( isDofManEnriched(* dMan) ) {
287 //printf("dofMan %i is enriched \n", dMan->giveNumber());
288 computeEnrichedDofManDofIdArray(EnrDofIdArray, * dMan);
289
290 // Collect boundary condition ID of existing dofs
291 IntArray bcIndexArray;
292 for ( Dof *dof: *dMan ) {
293 bcIndexArray.followedBy(dof->giveBcId());
294 }
295
296 bool foundBC = false;
297 IntArray nonZeroBC;
298 if ( !bcIndexArray.containsOnlyZeroes() ) {
299 // BC is found on dofs
300 foundBC = true;
301 nonZeroBC.findNonzeros(bcIndexArray);
302 }
303
304 int iDof(1);
305 for ( auto &dofid: EnrDofIdArray ) {
306 if ( !dMan->hasDofID( ( DofIDItem ) ( dofid ) ) ) {
308
309 if ( foundBC ) {
310 // Append dof with BC
313 // Assume order type of new dofs are the same as original
314 dMan->appendDof( new MasterDof(dMan, bcIndexArray.at(iDof), icIndex, ( DofIDItem ) dofid) );
315 } else {
316 // Append enriched dofs with same BC
317 dMan->appendDof( new MasterDof(dMan, bcIndexArray.at(nonZeroBC.at(1)), icIndex, ( DofIDItem ) dofid) );
318 }
319 } else {
320 // No BC found, append enriched dof without BC
321 dMan->appendDof( new MasterDof(dMan, ( DofIDItem ) dofid) );
322 }
323 } else {
324 // Append enriched dof without BC
325 dMan->appendDof( new MasterDof(dMan, ( DofIDItem ) dofid) );
326 }
327 }
328 iDof++;
329 }
330 }
331 }
332
333 // Remove old dofs
334 int poolStart = giveStartOfDofIdPool();
335 int poolEnd = giveEndOfDofIdPool();
336
337 for ( int i = 1; i <= nrDofMan; i++ ) {
338 DofManager *dMan = this->giveDomain()->giveDofManager(i);
339
340 computeEnrichedDofManDofIdArray(EnrDofIdArray, * dMan);
341 std :: vector< DofIDItem >dofsToRemove;
342 for ( auto &dof: *dMan ) {
343 DofIDItem dofID = dof->giveDofID();
344
345 if ( dofID >= DofIDItem(poolStart) && dofID <= DofIDItem(poolEnd) ) {
346 bool dofIsInIdArray = false;
347 for ( int k = 1; k <= EnrDofIdArray.giveSize(); k++ ) {
348 if ( dofID == DofIDItem( EnrDofIdArray.at(k) ) ) {
349 dofIsInIdArray = true;
350 break;
351 }
352 }
353
354 if ( !dofIsInIdArray ) {
355 dofsToRemove.push_back(dofID);
356 }
357
358
359 if(mEIDofIdArray.findFirstIndexOf(dofID) == 0 && dofIsInIdArray) {
360 mEIDofIdArray.followedBy(dofID);
361 }
362 }
363 }
364
365 for ( size_t j = 0; j < dofsToRemove.size(); j++ ) {
366 dMan->removeDof(dofsToRemove [ j ]);
367 }
368 }
369}
370
371
372double EnrichmentItem :: calcXiZeroLevel(const double &iQ1, const double &iQ2)
373{
374 double xi = 0.0;
375
376 if ( fabs(iQ1 - iQ2) > mLevelSetTol ) {
377 xi = ( iQ1 + iQ2 ) / ( iQ1 - iQ2 );
378 }
379
380 if ( xi < -1.0 ) {
381 xi = -1.0;
382 }
383
384 if ( xi > 1.0 ) {
385 xi = 1.0;
386 }
387
388 return xi;
389}
390
391void EnrichmentItem :: calcPolarCoord(double &oR, double &oTheta, const FloatArray &iOrigin, const FloatArray &iPos, const FloatArray &iN, const FloatArray &iT, const EfInput &iEfInput, bool iFlipTangent)
392{
393 FloatArray q = Vec2(
394 iPos.at(1) - iOrigin.at(1), iPos.at(2) - iOrigin.at(2)
395 );
396
397 const double tol = 1.0e-20;
398
399 // Compute polar coordinates
400 oR = distance(iOrigin, iPos);
401
402 if ( oR > tol ) {
403 q.times(1.0 / oR);
404 }
405
406 const double pi = M_PI;
407
408 // if( q.dotProduct(iT) > 0.0 ) {
409 // oTheta = asin( q.dotProduct(iN) );
410 // } else {
411 // if ( q.dotProduct(iN) > 0.0 ) {
412 // oTheta = pi - asin( q.dotProduct(iN) );
413 // } else {
414 // oTheta = -pi - asin( q.dotProduct(iN) );
415 // }
416 // }
417
418
419 const double tol_q = 1.0e-3;
420 double phi = iEfInput.mLevelSet;
421
422 if ( iFlipTangent ) {
423 phi *= -1.0;
424 }
425
426 double phi_r = 0.0;
427 if ( oR > tol ) {
428 phi_r = fabs(phi / oR);
429 }
430
431 if ( phi_r > 1.0 - XfemTolerances :: giveApproxZero() ) {
432 phi_r = 1.0 - XfemTolerances :: giveApproxZero();
433 }
434
435 if ( iEfInput.mArcPos < tol_q || iEfInput.mArcPos > ( 1.0 - tol_q ) ) {
436 double q_dot_n = q.dotProduct(iN);
437 if ( q_dot_n > 1.0 - XfemTolerances :: giveApproxZero() ) {
438 q_dot_n = 1.0 - XfemTolerances :: giveApproxZero();
439 }
440
441 oTheta = asin(q_dot_n);
442 } else {
443 if ( phi > 0.0 ) {
444 oTheta = pi - asin( fabs(phi_r) );
445 } else {
446 oTheta = -pi + asin( fabs(phi_r) );
447 }
448 }
449}
450
451void EnrichmentItem :: setPropagationLaw(std::unique_ptr<PropagationLaw> ipPropagationLaw)
452{
453 mpPropagationLaw = std::move(ipPropagationLaw);
454 mPropLawIndex = 1;
455}
456
457void EnrichmentItem :: callGnuplotExportModule(GnuplotExportModule &iExpMod, TimeStep *tStep)
458{
459 //iExpMod.outputXFEM(*this);
460}
461
462void EnrichmentItem :: setEnrichmentFrontStart(std::unique_ptr<EnrichmentFront> ipEnrichmentFrontStart, bool iDeleteOld)
463{
464 if( ! iDeleteOld ) {
465 mpEnrichmentFrontStart.release();
466 }
467
468 mpEnrichmentFrontStart = std::move(ipEnrichmentFrontStart);
469}
470
471void EnrichmentItem :: setEnrichmentFrontEnd(std::unique_ptr<EnrichmentFront> ipEnrichmentFrontEnd, bool iDeleteOld)
472{
473 if ( !iDeleteOld ) {
474 mpEnrichmentFrontEnd.release();
475 }
476
477 mpEnrichmentFrontEnd = std::move(ipEnrichmentFrontEnd);
478}
479
480bool EnrichmentItem :: tipIsTouchingEI(const TipInfo &iTipInfo)
481{
482 double tol = 1.0e-9;
483 SpatialLocalizer *localizer = giveDomain()->giveSpatialLocalizer();
484
485 Element *tipEl = localizer->giveElementContainingPoint(iTipInfo.mGlobalCoord);
486 if ( tipEl ) {
487 // Check if the candidate tip is located on the current crack
489 FloatArray locCoord;
490 tipEl->computeLocalCoordinates(locCoord, iTipInfo.mGlobalCoord);
491 FEInterpolation *interp = tipEl->giveInterpolation();
492 interp->evalN( N, locCoord, FEIElementGeometryWrapper(tipEl) );
493
494 double normalSignDist;
495 evalLevelSetNormal( normalSignDist, iTipInfo.mGlobalCoord, N, tipEl->giveDofManArray() );
496
497 double tangSignDist;
498 evalLevelSetTangential( tangSignDist, iTipInfo.mGlobalCoord, N, tipEl->giveDofManArray() );
499
500 if ( fabs(normalSignDist) < tol && tangSignDist > tol ) {
501 return true;
502 }
503 }
504
505 return false;
506}
507} // end namespace oofem
#define N(a, b)
int giveGlobalNumber() const
Definition dofmanager.h:515
bool hasDofID(DofIDItem id) const
Definition dofmanager.C:174
void removeDof(DofIDItem id)
Definition dofmanager.C:159
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
const IntArray & giveDofManArray() const
Definition element.h:611
virtual int giveNumberOfDofManagers() const
Definition element.h:695
DofManager * giveDofManager(int i) const
Definition element.C:553
virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords)
Definition element.C:1240
static const double mLevelSetTol
int mEnrFrontIndex
mEnrFrontIndex: nonzero if an enrichment front is present, zero otherwise.
virtual void evalLevelSetNormal(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const =0
std::unique_ptr< EnrichmentFront > mpEnrichmentFrontEnd
std ::unordered_map< int, NodeEnrichmentType > mNodeEnrMarkerMap
std::unique_ptr< EnrichmentFront > mpEnrichmentFrontStart
std::unique_ptr< EnrichmentFunction > mpEnrichmentFunc
int giveNumDofManEnrichments(const DofManager &iDMan) const
int mPropLawIndex
mPropLawIndex: nonzero if a propagation law is present, zero otherwise.
std::shared_ptr< InputRecord > thisIr
std ::unordered_map< int, double > mLevelSetTangDirMap
std ::unordered_map< int, double > mLevelSetNormalDirMap
int giveNumberOfEnrDofs() const
const IntArray * giveEnrichesDofsWithIdArray() const
int giveStartOfDofIdPool() const
IntArray mpEnrichesDofsWithIdArray
Geometry associated with EnrichmentItem.
std::unique_ptr< PropagationLaw > mpPropagationLaw
bool isDofManEnriched(const DofManager &iDMan) const
virtual void computeEnrichedDofManDofIdArray(IntArray &oDofIdArray, DofManager &iDMan)
int giveEndOfDofIdPool() const
virtual void evalLevelSetTangential(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const =0
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
Domain * giveDomain() const
Definition femcmpnn.h:97
FEMComponent(int n, Domain *d)
Definition femcmpnn.h:88
double & at(Index i)
Definition floatarray.h:202
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
void times(double s)
Definition floatarray.C:834
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
virtual std::shared_ptr< InputRecord > clone() const =0
virtual int giveGroupCount(InputFieldType id, const std::string &name, bool optional)=0
virtual bool hasChild(InputFieldType id, const std::string &name, bool optional)=0
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
void resize(int n)
Definition intarray.C:73
bool containsOnlyZeroes() const
Definition intarray.C:121
void findNonzeros(const IntArray &logical)
Definition intarray.C:155
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
virtual Element * giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList=nullptr)=0
FloatArray mGlobalCoord
Definition tipinfo.h:30
#define _IFT_EnrichmentItem_inheritorderedbc
#define _IFT_EnrichmentItem_front
#define _IFT_EnrichmentItem_inheritbc
#define _IFT_EnrichmentItem_propagationlaw
#define M_PI
Definition mathfem.h:52
static FloatArray Vec2(const double &a, const double &b)
Definition floatarray.h:606
@ NodeEnr_START_TIP
@ NodeEnr_END_TIP
@ NodeEnr_START_AND_END_TIP
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
double distance(const FloatArray &x, const FloatArray &y)

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