OOFEM 3.0
Loading...
Searching...
No Matches
geometrybasedei.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#include "xfemmanager.h"
37
38#include "spatiallocalizer.h"
39#include "classfactory.h"
40#include "element.h"
41#include "node.h"
42#include "mathfem.h"
43#include "feinterpol.h"
44#include "gausspoint.h"
45#include "dynamicinputrecord.h"
46#include "dynamicdatareader.h"
47#include "geometry.h"
48
50#include "xfem/propagationlaw.h"
52
53#include "engngm.h"
54#include "timestep.h"
55
56#include <string>
57#include <algorithm>
58#include <set>
59#include <memory>
60#include <cassert>
61
62namespace oofem {
63//REGISTER_EnrichmentItem(GeometryBasedEI)
64
65GeometryBasedEI :: GeometryBasedEI(int n, XfemManager *xm, Domain *aDomain) :
66 EnrichmentItem(n, xm, aDomain)
67{}
68
69GeometryBasedEI :: ~GeometryBasedEI()
70{}
71
72int GeometryBasedEI :: instanciateYourself(DataReader &dr)
73{
74 std :: string name;
75
76 // Instantiate enrichment function
77 {
79 mir->giveRecordKeywordField(name);
80
81 mpEnrichmentFunc = classFactory.createEnrichmentFunction( name.c_str(), 1, this->giveDomain() );
82 if ( mpEnrichmentFunc ) {
83 mpEnrichmentFunc->initializeFrom(*mir);
84 } else {
85 OOFEM_ERROR( "failed to create enrichment function (%s)", name.c_str() );
86 }
87 }
88
89 // Instantiate geometry
90 {
92 // auto &mir = dr.giveInputRecord(DataReader :: IR_geoRec, 1);
93 mir->giveRecordKeywordField(name);
94 mpBasicGeometry = classFactory.createGeometry( name.c_str() );
95 if ( !mpBasicGeometry ) {
96 OOFEM_ERROR( "unknown geometry domain (%s)", name.c_str() );
97 }
98
99 mpBasicGeometry->initializeFrom(*mir);
100 }
101 // Instantiate EnrichmentFront
102 if ( mEnrFrontIndex == 0 ) {
103 mpEnrichmentFrontStart = std::make_unique<EnrFrontDoNothing>();
104 mpEnrichmentFrontEnd = std::make_unique<EnrFrontDoNothing>();
105 } else {
106 int i=0;
107 for(InputRecord& efIr: dr.giveGroupRecords("EnrichmentFront",DataReader :: IR_enrichFrontRec,/*numRequired*/2)){
108 std::string enrFrontName;
109 efIr.giveRecordKeywordField(enrFrontName);
110 auto ef = classFactory.createEnrichmentFront( enrFrontName.c_str() );
111 if ( ef ) {
112 assert(i==0 || i==1);
113 ef->initializeFrom(efIr);
114 (i==0?mpEnrichmentFrontStart:mpEnrichmentFrontEnd)=std::move(ef);
115 } else {
116 OOFEM_ERROR( "Failed to create enrichment front (%s)", enrFrontName.c_str() );
117 }
118 i++;
119 }
120 }
121
122
123 // Instantiate PropagationLaw
124 if ( mPropLawIndex == 0 ) {
125 mpPropagationLaw = std::make_unique<PLDoNothing>();
126 } else {
127 std :: string propLawName;
128
129 auto propLawir = dr.giveChildRecord(thisIr,"",DataReader::InputRecordTags[DataReader::IR_propagationLawRec],DataReader :: IR_propagationLawRec,/*optional*/false);
130 propLawir->giveRecordKeywordField(propLawName);
131
132 mpPropagationLaw = classFactory.createPropagationLaw( propLawName.c_str() );
133 if ( mpPropagationLaw ) {
134 mpPropagationLaw->initializeFrom(*propLawir);
135 } else {
136 OOFEM_ERROR( "Failed to create propagation law (%s)", propLawName.c_str() );
137 }
138 }
139
140 // Set start of the enrichment dof pool for the given EI
141 int xDofPoolAllocSize = this->giveDofPoolSize();
142 this->startOfDofIdPool = this->giveDomain()->giveNextFreeDofID(xDofPoolAllocSize);
143 this->endOfDofIdPool = this->startOfDofIdPool + xDofPoolAllocSize - 1;
144
145
146
147 // mpEnrichmentDomain->CallNodeEnrMarkerUpdate(* this, * xMan);
148 // this->updateNodeEnrMarker(* xMan); // moved to postInitialize
149
150// writeVtkDebug();
151
152 return 1;
153}
154
155void GeometryBasedEI :: postInitialize()
156{
157 XfemManager *xMan = this->giveDomain()->giveXfemManager();
158 this->updateNodeEnrMarker(* xMan);
159}
160
161void GeometryBasedEI :: updateDofIdPool()
162{
163 // Set start of the enrichment dof pool for the given EI
164 int xDofPoolAllocSize = this->giveDofPoolSize();
165 this->startOfDofIdPool = this->giveDomain()->giveNextFreeDofID(xDofPoolAllocSize);
166 this->endOfDofIdPool = this->startOfDofIdPool + xDofPoolAllocSize - 1;
167
168// printf("startOfDofIdPool: %d\n", startOfDofIdPool);
169// printf("endOfDofIdPool: %d\n", endOfDofIdPool);
170
171 XfemManager *xMan = this->giveDomain()->giveXfemManager();
172 // mpEnrichmentDomain->CallNodeEnrMarkerUpdate(* this, * xMan);
173 this->updateNodeEnrMarker(* xMan);
174}
175
176void GeometryBasedEI :: appendInputRecords(DynamicDataReader &oDR)
177{
178 auto eiRec = std::make_unique<DynamicInputRecord>();
179
180 FEMComponent :: giveInputRecord(* eiRec);
181
184
186 eiRec->setField(_IFT_EnrichmentItem_inheritbc);
187 }
190 }
191
192 oDR.insertInputRecord(DataReader :: IR_enrichItemRec, std::move(eiRec));
193
194 // Enrichment function
195 auto efRec = std::unique_ptr<DynamicInputRecord>();
196 mpEnrichmentFunc->giveInputRecord(* efRec);
197 oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, std::move(efRec));
198
199 // Geometry
200 auto geoRec = std::unique_ptr<DynamicInputRecord>();
201 mpBasicGeometry->giveInputRecord(* geoRec);
202 oDR.insertInputRecord(DataReader :: IR_geoRec, std::move(geoRec));
203
204
205 // Enrichment front
206 if ( mEnrFrontIndex != 0 ) {
207 auto efrRecStart = std::unique_ptr<DynamicInputRecord>();
208 mpEnrichmentFrontStart->giveInputRecord(* efrRecStart);
209 oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, std::move(efrRecStart));
210
211 auto efrRecEnd = std::unique_ptr<DynamicInputRecord>();
212 mpEnrichmentFrontEnd->giveInputRecord(* efrRecEnd);
213 oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, std::move(efrRecEnd));
214 }
215
216 // Propagation law
217 if ( mPropLawIndex != 0 ) {
218 auto plRec = std::unique_ptr<DynamicInputRecord>();
219 this->mpPropagationLaw->giveInputRecord(* plRec);
220 oDR.insertInputRecord(DataReader :: IR_propagationLawRec, std::move(plRec));
221 }
222}
223
224void GeometryBasedEI :: updateGeometry()
225{
226 // Update enrichments ...
227 XfemManager *xMan = this->giveDomain()->giveXfemManager();
228
229 this->updateNodeEnrMarker(* xMan);
230 // ... and create new dofs if necessary.
232}
233
234void GeometryBasedEI :: updateNodeEnrMarker(XfemManager &ixFemMan)
235{
236 updateLevelSets(ixFemMan);
237
239 SpatialLocalizer *localizer = domain->giveSpatialLocalizer();
240
241 mNodeEnrMarkerMap.clear();
242 TipInfo tipInfoStart, tipInfoEnd;
243 bool foundTips = mpBasicGeometry->giveTips(tipInfoStart, tipInfoEnd);
244
245
246 FloatArray center;
247 double radius = 0.0;
248 giveBoundingSphere(center, radius);
249
250
251 IntArray elList;
252 localizer->giveAllElementsWithNodesWithinBox(elList, center, radius);
253
254 // Loop over elements and use the level sets to mark nodes belonging to completely cut elements.
255 for ( int elNum: elList ) {
256 Element *el = domain->giveElement(elNum);
257 int nElNodes = el->giveNumberOfNodes();
258
259 double minSignPhi = 1, maxSignPhi = -1;
260 double minPhi = std :: numeric_limits< double > :: max();
261 double maxPhi = std :: numeric_limits< double > :: min();
262
263 FloatArray elCenter(2);
264 elCenter.zero();
265
266 for ( int elNodeInd = 1; elNodeInd <= nElNodes; elNodeInd++ ) {
267 int nGlob = el->giveNode(elNodeInd)->giveGlobalNumber();
268
269 double levelSetNormalNode = 0.0;
270 if ( evalLevelSetNormalInNode( levelSetNormalNode, nGlob, el->giveNode(elNodeInd)->giveCoordinates() ) ) {
271 minSignPhi = std :: min( sgn(minSignPhi), sgn(levelSetNormalNode) );
272 maxSignPhi = std :: max( sgn(maxSignPhi), sgn(levelSetNormalNode) );
273
274 minPhi = std :: min(minPhi, levelSetNormalNode);
275 maxPhi = std :: max(maxPhi, levelSetNormalNode);
276 }
277
278 elCenter.at(1) += el->giveDofManager(elNodeInd)->giveCoordinate(1) / double ( nElNodes );
279 elCenter.at(2) += el->giveDofManager(elNodeInd)->giveCoordinate(2) / double ( nElNodes );
280 }
281
282
283 int numEdgeIntersec = 0;
284
285 if ( minPhi * maxPhi < mLevelSetTol ) { // If the level set function changes sign within the element.
286 // Count the number of element edges intersected by the interface
287 //int numEdges = nElNodes; // TODO: Is this assumption always true?
288 int numEdges = el->giveInterpolation()->giveNumberOfEdges(el->giveGeometryType()); //JIM
289
290 for ( int edgeIndex = 1; edgeIndex <= numEdges; edgeIndex++ ) {
291 const auto &bNodes = el->giveInterpolation()->boundaryGiveNodes(edgeIndex, el->giveGeometryType());
292
293 int niLoc = bNodes.at(1);
294 int niGlob = el->giveNode(niLoc)->giveGlobalNumber();
295 const auto &nodePosI = el->giveNode(niLoc)->giveCoordinates();
296 int njLoc = bNodes.at(2);
297 int njGlob = el->giveNode(njLoc)->giveGlobalNumber();
298 const auto &nodePosJ = el->giveNode(njLoc)->giveCoordinates();
299
300 double levelSetNormalNodeI = 0.0;
301 double levelSetNormalNodeJ = 0.0;
302 if ( evalLevelSetNormalInNode(levelSetNormalNodeI, niGlob, nodePosI) && evalLevelSetNormalInNode(levelSetNormalNodeJ, njGlob, nodePosJ) ) {
303 if ( levelSetNormalNodeI * levelSetNormalNodeJ < mLevelSetTol ) {
304 double xi = calcXiZeroLevel(levelSetNormalNodeI, levelSetNormalNodeJ);
305
306 // Compute the exact value of the tangential level set
307 // from the discretized geometry instead of interpolating.
308 double tangDist = 0.0, arcPos = 0.0;
309 const auto &posI = el->giveDofManager(niLoc)->giveCoordinates();
310 const auto &posJ = el->giveDofManager(njLoc)->giveCoordinates();
311 FloatArray pos;
312 pos.add(0.5 * ( 1.0 - xi ), posI);
313 pos.add(0.5 * ( 1.0 + xi ), posJ);
314 pos.resizeWithValues(2);
315
316 mpBasicGeometry->computeTangentialSignDist(tangDist, pos, arcPos);
317
318 double gamma = tangDist;
319
320 if ( gamma > 0.0 ) {
321 numEdgeIntersec++;
322 }
323 }
324 }
325 }
326
327
328 if ( numEdgeIntersec >= 1 ) {
329 // If we captured a cut element.
330 for ( int elNodeInd = 1; elNodeInd <= nElNodes; elNodeInd++ ) {
331 int nGlob = el->giveNode(elNodeInd)->giveGlobalNumber();
332
333 auto res = mNodeEnrMarkerMap.find(nGlob);
334 if ( res == mNodeEnrMarkerMap.end() ) {
336 }
337 }
338 }
339 }
340 }
341
342 // Mark tip nodes for special treatment.
343 if(foundTips) {
344 XfemManager *xMan = this->giveDomain()->giveXfemManager();
347 }
348}
349
350void GeometryBasedEI :: updateLevelSets(XfemManager &ixFemMan)
351{
352 mLevelSetNormalDirMap.clear();
353 mLevelSetTangDirMap.clear();
354
355 FloatArray center;
356 double radius = 0.0;
357 giveBoundingSphere(center, radius);
358
360 SpatialLocalizer *localizer = domain->giveSpatialLocalizer();
361
362 std :: list< int >nodeList;
363 localizer->giveAllNodesWithinBox(nodeList, center, radius);
364
365 for ( int nodeNum: nodeList ) {
366 Node *node = ixFemMan.giveDomain()->giveNode(nodeNum);
367
368 // Extract node coord
369 FloatArray pos( node->giveCoordinates() );
370 pos.resizeWithValues(2);
371
372 // Calc normal sign dist
373 double phi = 0.0;
374 mpBasicGeometry->computeNormalSignDist(phi, pos);
375 mLevelSetNormalDirMap [ nodeNum ] = phi;
376
377 // Calc tangential sign dist
378 double gamma = 0.0, arcPos = -1.0;
379 mpBasicGeometry->computeTangentialSignDist(gamma, pos, arcPos);
380 mLevelSetTangDirMap [ nodeNum ] = gamma;
381 }
382
383 mLevelSetsNeedUpdate = false;
384}
385
386void GeometryBasedEI :: evaluateEnrFuncInNode(std :: vector< double > &oEnrFunc, const Node &iNode) const
387{
388 double levelSetGP = 0.0;
389 const FloatArray &globalCoord = iNode.giveCoordinates();
390 int nodeInd = iNode.giveNumber();
391 this->evalLevelSetNormalInNode(levelSetGP, nodeInd, globalCoord);
392
393 // const int dim = this->giveDomain()->giveNumberOfSpatialDimensions();
394 // FloatArray gradLevelSetGP(dim);
395
396 double tangDist = 0.0, minDistArcPos = 0.0;
397 mpBasicGeometry->computeTangentialSignDist(tangDist, globalCoord, minDistArcPos);
398
399 FloatArray edGlobalCoord, localTangDir;
400
401 mpBasicGeometry->giveGlobalCoordinates(edGlobalCoord, minDistArcPos);
402 mpBasicGeometry->giveTangent(localTangDir, minDistArcPos);
403
404
405 const EfInput efInput(globalCoord, levelSetGP, nodeInd, edGlobalCoord, minDistArcPos, localTangDir);
406
407
408 if ( nodeInd == -1 ) {
409 // Bulk enrichment
410 oEnrFunc.resize(1, 0.0);
411 mpEnrichmentFunc->evaluateEnrFuncAt(oEnrFunc [ 0 ], globalCoord, levelSetGP);
412 } else {
413 auto res = mNodeEnrMarkerMap.find(nodeInd);
414 if ( res != mNodeEnrMarkerMap.end() ) {
415 switch ( res->second ) {
416 case NodeEnr_NONE:
417 break;
418 case NodeEnr_BULK:
419 // Bulk enrichment
420 oEnrFunc.resize(1, 0.0);
421 mpEnrichmentFunc->evaluateEnrFuncAt(oEnrFunc [ 0 ], globalCoord, levelSetGP);
422 break;
424 mpEnrichmentFrontStart->evaluateEnrFuncAt(oEnrFunc, efInput);
425 break;
426 case NodeEnr_END_TIP:
427 mpEnrichmentFrontEnd->evaluateEnrFuncAt(oEnrFunc, efInput);
428 break;
430 mpEnrichmentFrontStart->evaluateEnrFuncAt(oEnrFunc, efInput);
431 mpEnrichmentFrontEnd->evaluateEnrFuncAt(oEnrFunc, efInput);
432 break;
433 }
434 } else {
435 printf("In EnrichmentItem :: evaluateEnrFuncAt: mNodeEnrMarkerMap not found for iNodeInd %d\n", nodeInd);
436 }
437 }
438}
439
440void GeometryBasedEI :: evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const
441{
443 iEl.giveInterpolation()->evalN( N, iLocalCoord, FEIElementGeometryWrapper(& iEl) );
444
445 evaluateEnrFuncAt( oEnrFunc, iGlobalCoord, iLocalCoord, iNodeInd, iEl, N, iEl.giveDofManArray() );
446}
447
448void GeometryBasedEI :: evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const IntArray &iElNodes) const
449{
450 double levelSetGP = 0.0;
451 evalLevelSetNormal(levelSetGP, iGlobalCoord, iN, iElNodes);
452
453 // const int dim = this->giveDomain()->giveNumberOfSpatialDimensions();
454 // FloatArray gradLevelSetGP(dim);
455
456 double tangDist = 0.0, minDistArcPos = 0.0;
457 const FloatArray globalCoord = Vec2(
458 iGlobalCoord [ 0 ], iGlobalCoord [ 1 ]
459 );
460 mpBasicGeometry->computeTangentialSignDist(tangDist, globalCoord, minDistArcPos);
461
462 FloatArray edGlobalCoord, localTangDir;
463
464 mpBasicGeometry->giveGlobalCoordinates(edGlobalCoord, minDistArcPos);
465 mpBasicGeometry->giveTangent(localTangDir, minDistArcPos);
466
467
468 const EfInput efInput(iGlobalCoord, levelSetGP, iNodeInd, edGlobalCoord, minDistArcPos, localTangDir);
469
470
471 if ( iNodeInd == -1 ) {
472 // Bulk enrichment
473 oEnrFunc.resize(1, 0.0);
474 mpEnrichmentFunc->evaluateEnrFuncAt(oEnrFunc [ 0 ], iGlobalCoord, levelSetGP);
475 } else {
476 auto res = mNodeEnrMarkerMap.find(iNodeInd);
477 if ( res != mNodeEnrMarkerMap.end() ) {
478 switch ( res->second ) {
479 case NodeEnr_NONE:
480 break;
481 case NodeEnr_BULK:
482 // Bulk enrichment
483 oEnrFunc.resize(1, 0.0);
484 mpEnrichmentFunc->evaluateEnrFuncAt(oEnrFunc [ 0 ], iGlobalCoord, levelSetGP);
485 break;
487 mpEnrichmentFrontStart->evaluateEnrFuncAt(oEnrFunc, efInput);
488 break;
489 case NodeEnr_END_TIP:
490 mpEnrichmentFrontEnd->evaluateEnrFuncAt(oEnrFunc, efInput);
491 break;
493 mpEnrichmentFrontStart->evaluateEnrFuncAt(oEnrFunc, efInput);
494 mpEnrichmentFrontEnd->evaluateEnrFuncAt(oEnrFunc, efInput);
495 break;
496 }
497 } else {
498 printf("In EnrichmentItem :: evaluateEnrFuncAt: mNodeEnrMarkerMap not found for iNodeInd %d\n", iNodeInd);
499 }
500 }
501}
502
503void GeometryBasedEI :: evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const
504{
505 FloatMatrix dNdx;
507 FEInterpolation *interp = iEl.giveInterpolation();
508 const FEIElementGeometryWrapper geomWrapper(& iEl);
509 interp->evaldNdx(dNdx, iLocalCoord, geomWrapper);
510 interp->evalN(N, iLocalCoord, geomWrapper);
511
512 evaluateEnrFuncDerivAt( oEnrFuncDeriv, iGlobalCoord, iLocalCoord, iNodeInd, iEl, N, dNdx, iEl.giveDofManArray() );
513}
514
515void GeometryBasedEI :: evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const FloatMatrix &idNdX, const IntArray &iElNodes) const
516{
517 auto res = mNodeEnrMarkerMap.find(iNodeInd);
518 if ( res != mNodeEnrMarkerMap.end() ) {
519 double levelSetGP = 0.0;
520 evalLevelSetNormal(levelSetGP, iGlobalCoord, iN, iElNodes);
521
522 const int dim = 2;
523 FloatArray gradLevelSetGP(dim);
524 evalGradLevelSetNormal(gradLevelSetGP, iGlobalCoord, idNdX, iElNodes);
525
526 double tangDist = 0.0, minDistArcPos = 0.0;
527 mpBasicGeometry->computeTangentialSignDist(tangDist, iGlobalCoord, minDistArcPos);
528
529 FloatArray edGlobalCoord, localTangDir;
530
531
532 mpBasicGeometry->giveGlobalCoordinates(edGlobalCoord, minDistArcPos);
533 mpBasicGeometry->giveTangent(localTangDir, minDistArcPos);
534
535 const EfInput efInput(iGlobalCoord, levelSetGP, iNodeInd, edGlobalCoord, minDistArcPos, localTangDir);
536
537 switch ( res->second ) {
538 case NodeEnr_NONE:
539 break;
540 case NodeEnr_BULK:
541 oEnrFuncDeriv.resize(1);
542 mpEnrichmentFunc->evaluateEnrFuncDerivAt(oEnrFuncDeriv [ 0 ], iGlobalCoord, levelSetGP, gradLevelSetGP);
543 break;
545 mpEnrichmentFrontStart->evaluateEnrFuncDerivAt(oEnrFuncDeriv, efInput, gradLevelSetGP);
546 break;
547 case NodeEnr_END_TIP:
548 mpEnrichmentFrontEnd->evaluateEnrFuncDerivAt(oEnrFuncDeriv, efInput, gradLevelSetGP);
549 break;
551 mpEnrichmentFrontStart->evaluateEnrFuncDerivAt(oEnrFuncDeriv, efInput, gradLevelSetGP);
552 mpEnrichmentFrontEnd->evaluateEnrFuncDerivAt(oEnrFuncDeriv, efInput, gradLevelSetGP);
553 break;
554 }
555 } else {
556 printf("In EnrichmentItem :: evaluateEnrFuncDerivAt: mNodeEnrMarkerMap not found for iNodeInd %d\n", iNodeInd);
557 }
558}
559
560void GeometryBasedEI :: evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, int iNodeInd, GaussPoint &iGP, bool iGPLivesOnCurrentCrack) const
561{
562 double normalSignDist = 0.0;
563
564 SpatialLocalizer *localizer = this->giveDomain()->giveSpatialLocalizer();
565
567 if ( el != NULL ) {
569 FEInterpolation *interp = el->giveInterpolation();
571 //el->computeLocalCoordinates(locCoord, iGlobalCoord);
572
573 evalLevelSetNormal( normalSignDist, iGP.giveGlobalCoordinates(), N, el->giveDofManArray() );
574 }
575
576 // this->interpLevelSet(normalSignDist, iGP.giveGlobalCoordinates() );
577
578 auto res = mNodeEnrMarkerMap.find(iNodeInd);
579 if ( res != mNodeEnrMarkerMap.end() ) {
580 switch ( res->second ) {
581 case NodeEnr_NONE:
582 break;
583 case NodeEnr_BULK:
584 oEnrFuncJumps.resize(1);
585 mpEnrichmentFunc->giveJump(oEnrFuncJumps);
586 break;
588 mpEnrichmentFrontStart->evaluateEnrFuncJumps(oEnrFuncJumps, iGP, iNodeInd, iGPLivesOnCurrentCrack, normalSignDist);
589 break;
590 case NodeEnr_END_TIP:
591 mpEnrichmentFrontEnd->evaluateEnrFuncJumps(oEnrFuncJumps, iGP, iNodeInd, iGPLivesOnCurrentCrack, normalSignDist);
592 break;
594 mpEnrichmentFrontStart->evaluateEnrFuncJumps(oEnrFuncJumps, iGP, iNodeInd, iGPLivesOnCurrentCrack, normalSignDist);
595 mpEnrichmentFrontEnd->evaluateEnrFuncJumps(oEnrFuncJumps, iGP, iNodeInd, iGPLivesOnCurrentCrack, normalSignDist);
596 break;
597 }
598 } else {
599 printf("In EnrichmentItem :: evaluateEnrFuncDerivAt: evaluateEnrFuncJumps not found for iNodeInd %d\n", iNodeInd);
600 }
601}
602
603void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &oIntersectionPoints, std :: vector< int > &oIntersectedEdgeInd, Element *element, std :: vector< double > &oMinDistArcPos) const
604{
605 if ( isElementEnriched(element) ) {
606 // Use the level set functions to compute intersection points
607
608 // Loop over element edges; an edge is intersected if the
609 // node values of the level set functions have different signs
610
611 // int numEdges = element->giveNumberOfBoundarySides();
612 //int numEdges = element->giveNumberOfNodes(); // TODO: Is this assumption always true?
613 int numEdges = element->giveInterpolation()->giveNumberOfEdges(element->giveGeometryType());
614
615 for ( int edgeIndex = 1; edgeIndex <= numEdges; edgeIndex++ ) {
616 const auto &bNodes = element->giveInterpolation()->boundaryGiveNodes(edgeIndex, element->giveGeometryType());
617
618 int nsLoc = bNodes.at(1);
619 int nsGlob = element->giveNode(nsLoc)->giveGlobalNumber();
620 int neLoc = bNodes.at(2);
621 int neGlob = element->giveNode(neLoc)->giveGlobalNumber();
622
623 double phiS = 1.0;
624 bool foundPhiS = evalLevelSetNormalInNode( phiS, nsGlob, element->giveNode(nsLoc)->giveCoordinates() );
625
626 double phiE = 1.0;
627 bool foundPhiE = evalLevelSetNormalInNode( phiE, neGlob, element->giveNode(neLoc)->giveCoordinates() );
628
629 const auto &xS = element->giveNode(nsLoc)->giveCoordinates();
630 const auto &xE = element->giveNode(neLoc)->giveCoordinates();
631 const double edgeLength2 = distance_square(xS, xE);
632 const double gammaRelTol = 1.0e-2;
633
634 if ( ( foundPhiS && foundPhiE ) && phiS * phiE < mLevelSetRelTol * mLevelSetRelTol * edgeLength2 ) {
635 // Intersection detected
636
637 double xi = calcXiZeroLevel(phiS, phiE);
638
639 // Compute the exact value of the tangential level set
640 // from the discretized geometry instead of interpolating.
641 double tangDist = 0.0, arcPos = 0.0;
642 const auto &posI = element->giveDofManager(nsLoc)->giveCoordinates();
643 const auto &posJ = element->giveDofManager(neLoc)->giveCoordinates();
644 FloatArray pos;
645 pos.add(0.5 * ( 1.0 - xi ), posI);
646 pos.add(0.5 * ( 1.0 + xi ), posJ);
647 pos.resizeWithValues(2);
648 mpBasicGeometry->computeTangentialSignDist(tangDist, pos, arcPos);
649 double gamma = tangDist;
650
651
652 // If we are inside in tangential direction
653 if ( gamma > -gammaRelTol * sqrt(edgeLength2) ) {
654 if ( fabs(phiS - phiE) < mLevelSetTol ) {
655 // If the crack is parallel to the edge.
656
657 FloatArray ps( element->giveDofManager(nsLoc)->giveCoordinates() );
658 ps.resizeWithValues(2);
659 FloatArray pe( element->giveDofManager(neLoc)->giveCoordinates() );
660 pe.resizeWithValues(2);
661
662 // Check that the intersection points have not already been identified.
663 // This may happen if the crack intersects the element exactly at a node,
664 // so that intersection is detected for both element edges in that node.
665
666 bool alreadyFound = false;
667
668 int numPointsOld = oIntersectionPoints.size();
669 for ( int k = 1; k <= numPointsOld; k++ ) {
670 double dist = distance(ps, oIntersectionPoints [ k - 1 ]);
671
672 if ( dist < mLevelSetTol ) {
673 alreadyFound = true;
674 break;
675 }
676 }
677
678 if ( !alreadyFound ) {
679 oIntersectionPoints.push_back(ps);
680
681 double arcPos = 0.0, tangDist = 0.0;
682 mpBasicGeometry->computeTangentialSignDist(tangDist, ps, arcPos);
683 oMinDistArcPos.push_back(arcPos);
684
685 oIntersectedEdgeInd.push_back(edgeIndex);
686 }
687
688 alreadyFound = false;
689
690 numPointsOld = oIntersectionPoints.size();
691 for ( int k = 1; k <= numPointsOld; k++ ) {
692 double dist = distance(pe, oIntersectionPoints [ k - 1 ]);
693
694 if ( dist < mLevelSetTol ) {
695 alreadyFound = true;
696 break;
697 }
698 }
699
700 if ( !alreadyFound ) {
701 oIntersectionPoints.push_back(pe);
702
703 double arcPos = 0.0, tangDist = 0.0;
704 mpBasicGeometry->computeTangentialSignDist(tangDist, pe, arcPos);
705 oMinDistArcPos.push_back(arcPos);
706
707 oIntersectedEdgeInd.push_back(edgeIndex);
708 }
709 } else {
710 const auto &ps = element->giveDofManager(nsLoc)->giveCoordinates();
711 const auto &pe = element->giveDofManager(neLoc)->giveCoordinates();
712
713 FloatArray p(2);
714
715 for ( int i = 1; i <= 2; i++ ) {
716 ( p.at(i) ) = 0.5 * ( 1.0 - xi ) * ( ( ps.at(i) ) ) + 0.5 * ( 1.0 + xi ) * ( ( pe.at(i) ) );
717 }
718
719
720 // Check that the intersection point has not already been identified.
721 // This may happen if the crack intersects the element exactly at a node,
722 // so that intersection is detected for both element edges in that node.
723
724 bool alreadyFound = false;
725
726
727 int numPointsOld = oIntersectionPoints.size();
728 for ( int k = 1; k <= numPointsOld; k++ ) {
729 double dist = distance(p, oIntersectionPoints [ k - 1 ]);
730
731 if ( dist < mLevelSetTol ) {
732 alreadyFound = true;
733 break;
734 }
735 }
736
737 if ( !alreadyFound ) {
738 oIntersectionPoints.push_back(p);
739
740 double arcPos = 0.0, tangDist = 0.0;
741 mpBasicGeometry->computeTangentialSignDist(tangDist, p, arcPos);
742 oMinDistArcPos.push_back(arcPos);
743
744 oIntersectedEdgeInd.push_back(edgeIndex);
745 }
746 }
747 }
748 }
749 }
750 }
751}
752
753void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &oIntersectionPoints, std :: vector< int > &oIntersectedEdgeInd, Element *element, const Triangle &iTri, std :: vector< double > &oMinDistArcPos) const
754{
755 // Use the level set functions to compute intersection points
756
757 // Loop over element edges; an edge is intersected if the
758 // node values of the level set functions have different signs
759
760 const int numEdges = 3;
761
762 for ( int edgeIndex = 1; edgeIndex <= numEdges; edgeIndex++ ) {
763 FloatArray xS, xE;
764
765 // Global coordinates of vertices
766 switch ( edgeIndex ) {
767 case 1:
768 xS = iTri.giveVertex(1);
769 xE = iTri.giveVertex(2);
770 break;
771 case 2:
772 xS = iTri.giveVertex(2);
773 xE = iTri.giveVertex(3);
774 break;
775
776 case 3:
777 xS = iTri.giveVertex(3);
778 xE = iTri.giveVertex(1);
779 break;
780 default:
781 break;
782 }
783
784 // Local coordinates of vertices
785 FloatArray xiS;
786 element->computeLocalCoordinates(xiS, xS);
787 FloatArray xiE;
788 element->computeLocalCoordinates(xiE, xE);
789
790 const IntArray &elNodes = element->giveDofManArray();
791 FloatArray Ns, Ne;
792 FEInterpolation *interp = element->giveInterpolation();
793
794 interp->evalN( Ns, xiS, FEIElementGeometryWrapper(element) );
795 interp->evalN( Ne, xiE, FEIElementGeometryWrapper(element) );
796
797
798 double phiS = 0.0, phiE = 0.0;
799 double gammaS = 0.0, gammaE = 0.0;
800
801 bool levelSetDefinedInAllNodes = true;
802 for ( int i = 1; i <= Ns.giveSize(); i++ ) {
803 double phiSNode = 0.0;
804 if ( evalLevelSetNormalInNode( phiSNode, elNodes [ i - 1 ], element->giveNode(i)->giveCoordinates() ) ) {
805 phiS += Ns.at(i) * phiSNode;
806 } else {
807 levelSetDefinedInAllNodes = false;
808 }
809
810 double gammaSNode = 0.0;
811 if ( evalLevelSetTangInNode( gammaSNode, elNodes [ i - 1 ], element->giveNode(i)->giveCoordinates() ) ) {
812 gammaS += Ns.at(i) * gammaSNode;
813 } else {
814 levelSetDefinedInAllNodes = false;
815 }
816
817 double phiENode = 0.0;
818 if ( evalLevelSetNormalInNode( phiENode, elNodes [ i - 1 ], element->giveNode(i)->giveCoordinates() ) ) {
819 phiE += Ne.at(i) * phiENode;
820 } else {
821 levelSetDefinedInAllNodes = false;
822 }
823
824 double gammaENode = 0.0;
825 if ( evalLevelSetTangInNode( gammaENode, elNodes [ i - 1 ], element->giveNode(i)->giveCoordinates() ) ) {
826 gammaE += Ne.at(i) * gammaENode;
827 } else {
828 levelSetDefinedInAllNodes = false;
829 }
830 }
831
832 if ( phiS * phiE < mLevelSetTol2 && levelSetDefinedInAllNodes ) {
833 // Intersection detected
834
835 double xi = calcXiZeroLevel(phiS, phiE);
836 double gamma = 0.5 * ( 1.0 - xi ) * gammaS + 0.5 * ( 1.0 + xi ) * gammaE;
837
838 // If we are inside in tangential direction
839 if ( gamma > 0.0 ) {
840 if ( fabs(phiS - phiE) < mLevelSetTol ) {
841 // If the crack is parallel to the edge.
842
843 FloatArray ps(xS);
844 ps.resizeWithValues(2);
845 FloatArray pe(xE);
846 pe.resizeWithValues(2);
847
848 // Check that the intersection points have not already been identified.
849 // This may happen if the crack intersects the element exactly at a node,
850 // so that intersection is detected for both element edges in that node.
851
852 bool alreadyFound = false;
853
854 int numPointsOld = oIntersectionPoints.size();
855 for ( int k = 1; k <= numPointsOld; k++ ) {
856 double dist = distance(ps, oIntersectionPoints [ k - 1 ]);
857
858 if ( dist < mLevelSetTol ) {
859 alreadyFound = true;
860 break;
861 }
862 }
863
864 if ( !alreadyFound ) {
865 oIntersectionPoints.push_back(ps);
866
867 double arcPos = 0.0, tangDist = 0.0;
868 mpBasicGeometry->computeTangentialSignDist(tangDist, ps, arcPos);
869 oMinDistArcPos.push_back(arcPos);
870
871 oIntersectedEdgeInd.push_back(edgeIndex);
872 }
873
874 alreadyFound = false;
875
876 numPointsOld = oIntersectionPoints.size();
877 for ( int k = 1; k <= numPointsOld; k++ ) {
878 double dist = distance(pe, oIntersectionPoints [ k - 1 ]);
879
880 if ( dist < mLevelSetTol ) {
881 alreadyFound = true;
882 break;
883 }
884 }
885
886 if ( !alreadyFound ) {
887 oIntersectionPoints.push_back(pe);
888
889 double arcPos = 0.0, tangDist = 0.0;
890 mpBasicGeometry->computeTangentialSignDist(tangDist, pe, arcPos);
891 oMinDistArcPos.push_back(arcPos);
892
893 oIntersectedEdgeInd.push_back(edgeIndex);
894 }
895 } else {
896 FloatArray ps(xS);
897 FloatArray pe(xE);
898
899 int nDim = std :: min( ps.giveSize(), pe.giveSize() );
900 FloatArray p;
901 p.resize(nDim);
902
903 for ( int i = 1; i <= nDim; i++ ) {
904 ( p.at(i) ) = 0.5 * ( 1.0 - xi ) * ( ( ps.at(i) ) ) + 0.5 * ( 1.0 + xi ) * ( ( pe.at(i) ) );
905 }
906
907
908 // Check that the intersection point has not already been identified.
909 // This may happen if the crack intersects the element exactly at a node,
910 // so that intersection is detected for both element edges in that node.
911
912 bool alreadyFound = false;
913
914
915 int numPointsOld = oIntersectionPoints.size();
916 for ( int k = 1; k <= numPointsOld; k++ ) {
917 double dist = distance(p, oIntersectionPoints [ k - 1 ]);
918
919 if ( dist < mLevelSetTol ) {
920 alreadyFound = true;
921 break;
922 }
923 }
924
925 if ( !alreadyFound ) {
926 oIntersectionPoints.push_back(p);
927
928 double arcPos = 0.0, tangDist = 0.0;
929 p.resizeWithValues(2);
930 mpBasicGeometry->computeTangentialSignDist(tangDist, p, arcPos);
931 oMinDistArcPos.push_back(arcPos);
932
933 oIntersectedEdgeInd.push_back(edgeIndex);
934 }
935 }
936 }
937 }
938 }
939}
940
941void GeometryBasedEI :: writeVtkDebug() const
942{
943 // For debugging only
944 int tStepInd = 0;
945 TimeStep *tStep = domain->giveEngngModel()->giveCurrentStep(false);
946 if(tStep != NULL) {
947 tStepInd = tStep->giveNumber();
948 }
949 this->mpBasicGeometry->printVTK(tStepInd, number);
950}
951
952void GeometryBasedEI :: giveSubPolygon(std :: vector< FloatArray > &oPoints, const double &iXiStart, const double &iXiEnd) const
953{
954 mpBasicGeometry->giveSubPolygon(oPoints, iXiStart, iXiEnd);
955}
956
957void GeometryBasedEI :: propagateFronts(bool &oFrontsHavePropagated)
958{
959 oFrontsHavePropagated = false;
960
961 TipPropagation tipPropStart;
962 if ( mpPropagationLaw->propagateInterface(* giveDomain(), * mpEnrichmentFrontStart, tipPropStart) ) {
963 // mpEnrichmentDomain->propagateTip(tipPropStart);
964 // TODO: Generalize
965 // Propagate start point
966 FloatArray pos( mpBasicGeometry->giveVertex(1) );
967 pos.add(tipPropStart.mPropagationLength, tipPropStart.mPropagationDir);
968 mpBasicGeometry->insertVertexFront(pos);
969
970 oFrontsHavePropagated = true;
971 }
972
973 TipPropagation tipPropEnd;
974 if ( mpPropagationLaw->propagateInterface(* giveDomain(), * mpEnrichmentFrontEnd, tipPropEnd) ) {
975 // mpEnrichmentDomain->propagateTip(tipPropEnd);
976 // TODO: Generalize
977 // Propagate end point
978 FloatArray pos( mpBasicGeometry->giveVertex( mpBasicGeometry->giveNrVertices() ) );
979 pos.add(tipPropEnd.mPropagationLength, tipPropEnd.mPropagationDir);
980 mpBasicGeometry->insertVertexBack(pos);
981
982 oFrontsHavePropagated = true;
983 }
984
985#if 0
986 // For debugging only
987 if ( mpEnrichmentDomain->getVtkDebug() ) {
988 int tStepInd = this->domain->giveEngngModel()->giveCurrentStep()->giveNumber();
989
990 EnrichmentDomain_BG *enrDomBG = dynamic_cast< EnrichmentDomain_BG * >( mpEnrichmentDomain );
991
992 if ( enrDomBG != NULL ) {
993 PolygonLine *pl = dynamic_cast< PolygonLine * >( enrDomBG->bg );
994 if ( pl != NULL ) {
995 pl->printVTK(tStepInd, number);
996 }
997 }
998 }
999#endif
1001
1002// if( domain->giveEngngModel()->giveProblemScale() == macroScale ) {
1003// writeVtkDebug();
1004// }
1005}
1006
1007bool GeometryBasedEI :: giveElementTipCoord(FloatArray &oCoord, double &oArcPos, Element &iEl, const FloatArray &iElCenter) const
1008{
1009 TipInfo tipInfoStart, tipInfoEnd;
1010 mpBasicGeometry->giveTips(tipInfoStart, tipInfoEnd);
1011
1012
1013 std :: vector< TipInfo >tipInfos = {
1014 tipInfoStart, tipInfoEnd
1015 };
1016
1017 double minDist2 = std :: numeric_limits< double > :: max();
1018 size_t minIndex = 0;
1019 bool foundTip = false;
1020
1021 for ( size_t i = 0; i < tipInfos.size(); i++ ) {
1022 double d2 = distance_square(tipInfos [ i ].mGlobalCoord, iElCenter);
1023 if ( d2 < minDist2 ) {
1024 minDist2 = d2;
1025 minIndex = i;
1026 foundTip = true;
1027 }
1028 }
1029
1030 if ( !foundTip ) {
1031 return false;
1032 } else {
1033 // Check if the tip point is inside the element
1034 const FloatArray &globCoord = tipInfos [ minIndex ].mGlobalCoord;
1035 FloatArray locCoord;
1036 if ( !iEl.computeLocalCoordinates(locCoord, globCoord) ) {
1037 return false;
1038 }
1039
1040 oCoord = tipInfos [ minIndex ].mGlobalCoord;
1041 oArcPos = tipInfos [ minIndex ].mArcPos;
1042 return true;
1043 }
1044}
1045
1046void GeometryBasedEI :: giveBoundingSphere(FloatArray &oCenter, double &oRadius)
1047{
1048 // Compute bounding sphere from enrichment domain ...
1049 mpBasicGeometry->giveBoundingSphere(oCenter, oRadius);
1050
1051 // ... increase the radius to cover the support of
1052 // the enrichment front ...
1053 oRadius += max( mpEnrichmentFrontStart->giveSupportRadius(), mpEnrichmentFrontEnd->giveSupportRadius() );
1054
1055
1056 if ( domain->giveNumberOfSpatialDimensions() == 2 ) {
1057 // Compute mean area if applicable
1058 double meanArea = domain->giveArea() / domain->giveNumberOfElements();
1059 double meanLength = sqrt(meanArea);
1060 //printf("meanLength: %e\n", meanLength );
1061
1062 oRadius = max(oRadius, meanLength);
1063 }
1064
1065 // ... and make sure that all nodes of partly cut elements are included.
1066 oRadius *= 2.0; // TODO: Compute a better estimate based on maximum element size. /ES
1067}
1068} /* namespace oofem */
#define N(a, b)
const FloatArray & giveVertex(int n) const
Definition geometry.h:124
GroupRecords giveGroupRecords(const std::shared_ptr< InputRecord > &ir, InputFieldType ift, const std::string &name, InputRecordType irType, bool optional)
Definition datareader.C:46
static constexpr const char * InputRecordTags[]
Definition datareader.h:76
InputRecord * giveChildRecord(const std::shared_ptr< InputRecord > &ir, InputFieldType ift, const std::string &name, InputRecordType irType, bool optional)
Return pointer to subrecord of given type (must be exactly one); if not present, returns nullptr.
Definition datareader.C:40
int giveGlobalNumber() const
Definition dofmanager.h:515
double giveCoordinate(int i) const
Definition dofmanager.h:383
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
Node * giveNode(int n)
Definition domain.h:398
void insertInputRecord(InputRecordType type, std::unique_ptr< InputRecord > record)
Node * giveNode(int i) const
Definition element.h:629
virtual FEInterpolation * giveInterpolation() const
Definition element.h:648
virtual int giveNumberOfNodes() const
Definition element.h:703
const IntArray & giveDofManArray() const
Definition element.h:611
DofManager * giveDofManager(int i) const
Definition element.C:553
virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords)
Definition element.C:1240
virtual Element_Geometry_Type giveGeometryType() const =0
static const double mLevelSetRelTol
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
bool evalLevelSetTangInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
std::unique_ptr< EnrichmentFront > mpEnrichmentFrontStart
virtual int giveDofPoolSize() const
std::unique_ptr< EnrichmentFunction > mpEnrichmentFunc
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
virtual void evalGradLevelSetNormal(FloatArray &oGradLevelSet, const FloatArray &iGlobalCoord, const FloatMatrix &idNdX, const IntArray &iNodeInd) const =0
std::unique_ptr< PropagationLaw > mpPropagationLaw
bool isElementEnriched(const Element *element) const
static double calcXiZeroLevel(const double &iQ1, const double &iQ2)
EnrichmentItem(int n, XfemManager *xm, Domain *aDomain)
Constructor / destructor.
bool evalLevelSetNormalInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
virtual void createEnrichedDofs()
virtual IntArray boundaryGiveNodes(int boundary, const Element_Geometry_Type) const =0
virtual int giveNumberOfEdges(const Element_Geometry_Type) const
Definition feinterpol.h:550
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int number
Component number.
Definition femcmpnn.h:77
int giveNumber() const
Definition femcmpnn.h:104
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void resizeWithValues(Index s, std::size_t allocChunk=0)
Definition floatarray.C:103
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void add(const FloatArray &src)
Definition floatarray.C:218
const FloatArray & giveGlobalCoordinates()
Definition gausspoint.h:159
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
void evaluateEnrFuncAt(std ::vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const override
void updateGeometry() override
void giveBoundingSphere(FloatArray &oCenter, double &oRadius) override
std ::unique_ptr< BasicGeometry > mpBasicGeometry
void updateLevelSets(XfemManager &ixFemMan)
void updateNodeEnrMarker(XfemManager &ixFemMan) override
void evaluateEnrFuncDerivAt(std ::vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const override
virtual void giveRecordKeywordField(std ::string &answer, int &value)=0
Reads the record id field (type of record) and its corresponding number.
int & at(std::size_t i)
Definition intarray.h:104
void printVTK(int iTStepIndex, int iLineIndex) override
Definition geometry.C:1633
virtual Element * giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList=nullptr)=0
virtual void giveAllNodesWithinBox(nodeContainerType &nodeList, const FloatArray &coords, const double radius)=0
virtual void giveAllElementsWithNodesWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius)
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
Domain * giveDomain()
#define _IFT_EnrichmentItem_inheritorderedbc
#define _IFT_EnrichmentItem_front
#define _IFT_EnrichmentItem_inheritbc
#define _IFT_EnrichmentItem_propagationlaw
#define OOFEM_ERROR(...)
Definition error.h:79
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 sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1).
Definition mathfem.h:104
ClassFactory & classFactory
double distance(const FloatArray &x, const FloatArray &y)
double distance_square(const FloatArray &x, const FloatArray &y)
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