OOFEM 3.0
Loading...
Searching...
No Matches
xfemelementinterface.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 "enrichmentitem.h"
37#include "geometrybasedei.h"
38#include "engngm.h"
39#include "gausspoint.h"
40#include "materialmode.h"
41#include "fei2dquadlin.h"
43#include "delaunay.h"
44#include "xfemmanager.h"
45#include "floatarray.h"
46#include "floatmatrix.h"
47#include "dynamicinputrecord.h"
48#include "mathfem.h"
49#include "parametermanager.h"
50#include "paramkey.h"
51
52#include "XFEMDebugTools.h"
53#include <string>
54#include <sstream>
55
56namespace oofem {
57
61
62
63XfemElementInterface :: XfemElementInterface(Element *e) :
64 Interface(),
65 element(e),
66 mUsePlaneStrain(false)
67{
70}
71
72XfemElementInterface :: ~XfemElementInterface()
73{}
74
75void XfemElementInterface :: XfemElementInterface_createEnrBmatrixAt(FloatMatrix &oAnswer, GaussPoint &iGP, Element &iEl)
76{
77 ComputeBOrBHMatrix(oAnswer, iGP, iEl, false, iGP.giveNaturalCoordinates());
78}
79
80void XfemElementInterface :: XfemElementInterface_createEnrBHmatrixAt(FloatMatrix &oAnswer, GaussPoint &iGP, Element &iEl)
81{
82 ComputeBOrBHMatrix(oAnswer, iGP, iEl, true, iGP.giveNaturalCoordinates());
83}
84
85void XfemElementInterface :: ComputeBOrBHMatrix(FloatMatrix &oAnswer, GaussPoint &iGP, Element &iEl, bool iComputeBH, const FloatArray &iNaturalGpCoord)
86{
87 /*
88 * Computes the B or BH matrix.
89 * iComputeBH = true implies that BH is computed,
90 * while B is computed if iComputeBH = false.
91 *
92 * We could take the natural coordinates directly from the Gauss point instead of entering them separately.
93 * However, there are situations where one wants to add a small perturbation to the coordinates and hence
94 * it is easier to enter them separately.
95 */
96 const int dim = 2;
97 const int nDofMan = iEl.giveNumberOfDofManagers();
98
99 int shearInd = 3, numRows = 3;
100 if ( mUsePlaneStrain ) {
101 shearInd = 4;
102 numRows = 4;
103 }
104
105 if ( iComputeBH ) {
106 numRows++;
107 }
108
109 FloatMatrix dNdx;
111 FEInterpolation *interp = iEl.giveInterpolation();
112 const FEIElementGeometryWrapper geomWrapper(& iEl);
113 interp->evaldNdx(dNdx, iNaturalGpCoord, geomWrapper);
114 interp->evalN(N, iNaturalGpCoord, geomWrapper);
115
116 const IntArray &elNodes = iEl.giveDofManArray();
117
118 // Compute global coordinates of Gauss point
119 FloatArray globalCoord = Vec2(
120 0.0, 0.0
121 );
122
123 for ( int i = 1; i <= nDofMan; i++ ) {
124 const Node *node = iEl.giveNode(i);
125 const auto &nodeCoord = node->giveCoordinates();
126 globalCoord.at(1) += N.at(i) * nodeCoord [ 0 ];
127 globalCoord.at(2) += N.at(i) * nodeCoord [ 1 ];
128 }
129
130
131 // Standard FE part of B-matrix
132 std :: vector< FloatMatrix >Bc(nDofMan);
133 for ( int i = 1; i <= nDofMan; i++ ) {
134 FloatMatrix &BNode = Bc [ i - 1 ];
135 BNode.resize(numRows, 2);
136 BNode.at(1, 1) = dNdx.at(i, 1);
137 BNode.at(2, 2) = dNdx.at(i, 2);
138 BNode.at(shearInd, 1) = dNdx.at(i, 2);
139
140 if ( iComputeBH ) {
141 BNode.at(shearInd + 1, 2) = dNdx.at(i, 1);
142 } else {
143 BNode.at(shearInd, 2) = dNdx.at(i, 1);
144 }
145 }
146
147
148 // XFEM part of B-matrix
149 double enrDofsScaleFactor = 1.0;
150 XfemManager *xMan = nullptr;
151 if ( iEl.giveDomain()->hasXfemManager() ) {
152 xMan = iEl.giveDomain()->giveXfemManager();
153 enrDofsScaleFactor = xMan->giveEnrDofScaleFactor();
154 }
155
156 std :: vector< FloatMatrix >Bd(nDofMan); // One Bd per node
157
158 int counter = nDofMan * dim;
159
160 int numEnrNode = 0;
161
162 for ( int j = 1; j <= nDofMan; j++ ) {
163 DofManager *dMan = iEl.giveDofManager(j);
164 const Node *node = iEl.giveNode(j);
165
166 // Compute the total number of enrichments for node j
167 if ( iEl.giveDomain()->hasXfemManager() ) {
168 numEnrNode = XfemElementInterface_giveNumDofManEnrichments(* dMan, * xMan);
169 }
170
171 if ( numEnrNode > 0 ) {
172 FloatMatrix &BdNode = Bd [ j - 1 ];
173 BdNode.resize(numRows, numEnrNode * dim);
174
175
176 const int globalNodeInd = dMan->giveGlobalNumber();
177
178 int nodeEnrCounter = 0;
179
180 const std :: vector< int > &nodeEiIndices = xMan->giveNodeEnrichmentItemIndices(globalNodeInd);
181 for ( size_t i = 0; i < nodeEiIndices.size(); i++ ) {
182 EnrichmentItem *ei = xMan->giveEnrichmentItem(nodeEiIndices [ i ]);
183
184 if ( ei->isDofManEnriched(* dMan) ) {
185// int numEnr = ei->giveNumDofManEnrichments(* dMan);
186
187 // Enrichment function derivative in Gauss point
188 std :: vector< FloatArray >efgpD;
189 ei->evaluateEnrFuncDerivAt(efgpD, globalCoord, iNaturalGpCoord, globalNodeInd, * element, N, dNdx, elNodes);
190 // Enrichment function in Gauss Point
191 std :: vector< double >efGP;
192 ei->evaluateEnrFuncAt(efGP, globalCoord, iNaturalGpCoord, globalNodeInd, * element, N, elNodes);
193
194
195 const auto &nodePos = node->giveCoordinates();
196
197// double levelSetNode = 0.0;
198// ei->evalLevelSetNormalInNode(levelSetNode, globalNodeInd, nodePos);
199
200 std :: vector< double >efNode;
201 FloatArray nodeNaturalCoord;
202 iEl.computeLocalCoordinates(nodeNaturalCoord, nodePos);
203 ei->evaluateEnrFuncInNode(efNode, * node);
204
205 int numEnr = efGP.size();
206 for ( int k = 0; k < numEnr; k++ ) {
207 // matrix to be added anytime a node is enriched
208 // Creates nabla*(ef*N)
209 FloatArray grad_ef_N;
210 grad_ef_N.resize(dim);
211 for ( int p = 1; p <= dim; p++ ) {
212 grad_ef_N.at(p) = dNdx.at(j, p) * ( efGP [ k ] - efNode [ k ] ) + N.at(j) * efgpD [ k ].at(p);
213 }
214
215 BdNode.at(1, nodeEnrCounter + 1) = grad_ef_N.at(1);
216 BdNode.at(2, nodeEnrCounter + 2) = grad_ef_N.at(2);
217 BdNode.at(shearInd, nodeEnrCounter + 1) = grad_ef_N.at(2);
218
219 if ( iComputeBH ) {
220 BdNode.at(shearInd + 1, nodeEnrCounter + 2) = grad_ef_N.at(1);
221 } else {
222 BdNode.at(shearInd, nodeEnrCounter + 2) = grad_ef_N.at(1);
223 }
224
225 nodeEnrCounter += 2;
226 counter += 2;
227 }
228 }
229 }
230 }
231 }
232
233
234 // Create the total B-matrix by appending each contribution to B after one another.
235 oAnswer.resize(numRows, counter);
236
237 int column = 1;
238 for ( int i = 0; i < nDofMan; i++ ) {
239 oAnswer.setSubMatrix(Bc [ i ], 1, column);
240 column += 2;
241 if ( Bd [ i ].isNotEmpty() ) {
242 Bd[i].times(enrDofsScaleFactor);
243 oAnswer.setSubMatrix(Bd [ i ], 1, column);
244
245 column += Bd [ i ].giveNumberOfColumns();
246 }
247 }
248}
249
250void XfemElementInterface :: XfemElementInterface_createEnrNmatrixAt(FloatMatrix &oAnswer, const FloatArray &iLocCoord, Element &iEl, bool iSetDiscontContribToZero)
251{
252 std :: vector< int >elNodes;
253
254 int numElNodes = iEl.giveNumberOfDofManagers();
255
256 for ( int i = 0; i < numElNodes; i++ ) {
257 elNodes.push_back(i + 1);
258 }
259
260 XfemElementInterface_createEnrNmatrixAt(oAnswer, iLocCoord, iEl, elNodes, iSetDiscontContribToZero);
261}
262
263void XfemElementInterface :: XfemElementInterface_createEnrNmatrixAt(FloatMatrix &oAnswer, const FloatArray &iLocCoord, Element &iEl, const std :: vector< int > &iLocNodeInd, bool iSetDiscontContribToZero)
264{
265 const int dim = 2;
266 const int nDofMan = iEl.giveNumberOfDofManagers();
267
268 FloatArray Nc;
269 FEInterpolation *interp = iEl.giveInterpolation();
270 interp->evalN( Nc, iLocCoord, FEIElementGeometryWrapper(& iEl) );
271
272 const IntArray &elNodes = iEl.giveDofManArray();
273
274 // Compute global coordinates of Gauss point
275 FloatArray globalCoord(2);
276 globalCoord.zero();
277
278 for ( int i = 1; i <= nDofMan; i++ ) {
279 DofManager *dMan = iEl.giveDofManager(i);
280 globalCoord.at(1) += Nc.at(i) * dMan->giveCoordinate(1);
281 globalCoord.at(2) += Nc.at(i) * dMan->giveCoordinate(2);
282 }
283
284
285 // XFEM part of N-matrix
286 XfemManager *xMan = iEl.giveDomain()->giveXfemManager();
287 double enrDofsScaleFactor = xMan->giveEnrDofScaleFactor();
288
289 [[maybe_unused]] int counter = iLocNodeInd.size() * dim;
290
291 std :: vector< std :: vector< double > >Nd( iLocNodeInd.size() );
292 for ( int j = 1; j <= int( iLocNodeInd.size() ); j++ ) {
293 DofManager *dMan = iEl.giveDofManager(iLocNodeInd [ j - 1 ]);
294 Node *node = dynamic_cast< Node * >( dMan );
295
296 // Compute the total number of enrichments for node j
297 int numEnrNode = XfemElementInterface_giveNumDofManEnrichments(* dMan, * xMan);
298 std :: vector< double > &NdNode = Nd [ j - 1 ];
299 NdNode.assign(numEnrNode, 0.0);
300
301
302 int globalNodeInd = dMan->giveGlobalNumber();
303
304 size_t nodeCounter = 0;
305
306 int placeInArray = element->giveDomain()->giveDofManPlaceInArray(globalNodeInd);
307 const std :: vector< int > &nodeEiIndices = xMan->giveNodeEnrichmentItemIndices(placeInArray);
308 for ( size_t i = 0; i < nodeEiIndices.size(); i++ ) {
309 EnrichmentItem *ei = xMan->giveEnrichmentItem(nodeEiIndices [ i ]);
310
311 if ( ei->isDofManEnriched(* dMan) ) {
312// int numEnr = ei->giveNumDofManEnrichments(* dMan);
313
314
315 // Enrichment function in Gauss Point
316 std :: vector< double >efGP;
317 ei->evaluateEnrFuncAt(efGP, globalCoord, iLocCoord, globalNodeInd, iEl, Nc, elNodes);
318
319
320 const auto &nodePos = dMan->giveCoordinates();
321
322 std :: vector< double >efNode;
323
324 FloatArray nodePosLocCoord;
325 iEl.computeLocalCoordinates(nodePosLocCoord, nodePos);
326 ei->evaluateEnrFuncInNode(efNode, * node);
327
328
329 int numEnr = efGP.size();
330 for ( int k = 0; k < numEnr; k++ ) {
331 if ( iSetDiscontContribToZero ) {
332 NdNode [ nodeCounter ] = 0.0;
333 } else {
334 NdNode [ nodeCounter ] = ( efGP [ k ] - efNode [ k ] ) * Nc.at(j);
335 }
336 counter++;
337 nodeCounter++;
338 }
339 }
340 }
341 }
342
343 int numN = iLocNodeInd.size();
344
345 for ( int j = 1; j <= int( iLocNodeInd.size() ); j++ ) {
346 numN += Nd [ j - 1 ].size();
347 }
348
349 FloatArray NTot;
350 NTot.resize(numN);
351 NTot.zero();
352 int column = 1;
353
354 for ( int i = 1; i <= int( iLocNodeInd.size() ); i++ ) {
355 NTot.at(column) = Nc.at(iLocNodeInd [ i - 1 ]);
356 column++;
357
358 const std :: vector< double > &NdNode = Nd [ i - 1 ];
359 for ( size_t j = 1; j <= NdNode.size(); j++ ) {
360 NTot.at(column) = NdNode [ j - 1 ]*enrDofsScaleFactor;
361 column++;
362 }
363 }
364
365 oAnswer.beNMatrixOf(NTot, 2);
366}
367
368int XfemElementInterface :: XfemElementInterface_giveNumDofManEnrichments(const DofManager &iDMan, XfemManager &iXMan) const
369{
370 int numEnrNode = 0;
371 int globalNodeInd = iDMan.giveGlobalNumber();
372 int placeInArray = element->giveDomain()->giveDofManPlaceInArray(globalNodeInd);
373 const std :: vector< int > &nodeEiIndices = iXMan.giveNodeEnrichmentItemIndices(placeInArray);
374 for ( size_t i = 0; i < nodeEiIndices.size(); i++ ) {
375 EnrichmentItem *ei = iXMan.giveEnrichmentItem(nodeEiIndices [ i ]);
376 if ( ei->isDofManEnriched(iDMan) ) {
377 numEnrNode += ei->giveNumDofManEnrichments(iDMan);
378 }
379 }
380
381 return numEnrNode;
382}
383
384void XfemElementInterface :: XfemElementInterface_partitionElement(std :: vector< Triangle > &oTriangles, const std :: vector< FloatArray > &iPoints)
385{
386 Delaunay dl;
387 dl.triangulate(iPoints, oTriangles);
388}
389
390
391
392bool XfemElementInterface :: XfemElementInterface_updateIntegrationRule()
393{
394 bool partitionSucceeded = false;
395
396 XfemManager *xMan = this->element->giveDomain()->giveXfemManager();
397 if ( xMan->isElementEnriched(element) ) {
398 MaterialMode matMode = element->giveMaterialMode();
399
400 bool firstIntersection = true;
401
402 std :: vector< std :: vector< FloatArray > >pointPartitions;
403 std :: vector< Triangle >allTri;
404
405 std :: vector< int >enrichingEIs;
406 int elPlaceInArray = xMan->giveDomain()->giveElementPlaceInArray( element->giveGlobalNumber() );
407 xMan->giveElementEnrichmentItemIndices(enrichingEIs, elPlaceInArray);
408
409
410 for ( size_t p = 0; p < enrichingEIs.size(); p++ ) {
411 int eiIndex = enrichingEIs [ p ];
412
413 if ( firstIntersection ) {
414 // Get the points describing each subdivision of the element
415 double startXi, endXi;
416 bool intersection = false;
417 this->XfemElementInterface_prepareNodesForDelaunay(pointPartitions, startXi, endXi, eiIndex, intersection);
418
419 if ( intersection ) {
420 firstIntersection = false;
421
422 // Use XfemElementInterface_partitionElement to subdivide the element
423 for ( int i = 0; i < int ( pointPartitions.size() ); i++ ) {
424 // Triangulate the subdivisions
425 this->XfemElementInterface_partitionElement(allTri, pointPartitions [ i ]);
426 }
427
428 partitionSucceeded = true;
429 }
430 } // if(firstIntersection)
431 else {
432 // Loop over triangles
433 std :: vector< Triangle >allTriCopy;
434 for ( size_t triIndex = 0; triIndex < allTri.size(); triIndex++ ) {
435 // Call alternative version of XfemElementInterface_prepareNodesForDelaunay
436 std :: vector< std :: vector< FloatArray > >pointPartitionsTri;
437 double startXi, endXi;
438 bool intersection = false;
439 XfemElementInterface_prepareNodesForDelaunay(pointPartitionsTri, startXi, endXi, allTri [ triIndex ], eiIndex, intersection);
440
441 if ( intersection ) {
442 // Use XfemElementInterface_partitionElement to subdivide triangle j
443 for ( int i = 0; i < int ( pointPartitionsTri.size() ); i++ ) {
444 this->XfemElementInterface_partitionElement(allTriCopy, pointPartitionsTri [ i ]);
445 }
446 } else {
447 allTriCopy.push_back(allTri [ triIndex ]);
448 }
449 }
450
451 allTri = allTriCopy;
452 }
453 }
454
456 // When we reach this point, we have a
457 // triangulation that is adapted to all
458 // cracks passing through the element.
459 // Therefore, we can set up integration
460 // points on each triangle.
461
462 if ( xMan->giveVtkDebug() ) {
463 std :: stringstream str3;
464 int elIndex = this->element->giveGlobalNumber();
465 str3 << "TriEl" << elIndex << ".vtk";
466 std :: string name3 = str3.str();
467
468 if ( allTri.size() > 0 ) {
469 XFEMDebugTools :: WriteTrianglesToVTK(name3, allTri);
470 }
471 }
472
473
474 int ruleNum = 1;
475 if ( partitionSucceeded ) {
476 std :: vector< std :: unique_ptr< IntegrationRule > >intRule;
477 intRule.emplace_back( new PatchIntegrationRule(ruleNum, element, allTri) );
478 intRule [ 0 ]->SetUpPointsOnTriangle(xMan->giveNumGpPerTri(), matMode);
479 element->setIntegrationRules( std :: move(intRule) );
480 }
481 }
482
483 return partitionSucceeded;
484}
485
486void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: vector< std :: vector< FloatArray > > &oPointPartitions, double &oCrackStartXi, double &oCrackEndXi, int iEnrItemIndex, bool &oIntersection)
487{
488 int dim = element->giveDofManager(1)->giveCoordinates().giveSize();
489
490 FloatArray elCenter( element->giveDofManager(1)->giveCoordinates().giveSize() );
491 elCenter.zero();
492 std :: vector< const FloatArray * >nodeCoord;
493 for ( int i = 1; i <= this->element->giveNumberOfDofManagers(); i++ ) {
494 nodeCoord.push_back( &element->giveDofManager(i)->giveCoordinates() );
495 elCenter.add( element->giveDofManager(i)->giveCoordinates() );
496 }
497 elCenter.times( 1.0 / double( element->giveNumberOfDofManagers() ) );
498
499 XfemManager *xMan = this->element->giveDomain()->giveXfemManager();
500 GeometryBasedEI *ei = dynamic_cast< GeometryBasedEI * >( xMan->giveEnrichmentItem(iEnrItemIndex) );
501
502 if ( ei == nullptr ) {
503 oIntersection = false;
504 return;
505 }
506
507 std :: vector< FloatArray >intersecPoints;
508 std :: vector< int >intersecEdgeInd;
509
510 std :: vector< double >minDistArcPos;
511 ei->computeIntersectionPoints(intersecPoints, intersecEdgeInd, element, minDistArcPos);
512
513 for ( size_t i = 0; i < intersecPoints.size(); i++ ) {
514 intersecPoints [ i ].resizeWithValues(dim);
515 }
516
517
518 if ( intersecPoints.size() == 2 ) {
519 // The element is completely cut in two.
520 // Therefore, we create two subpartitions:
521 // one on each side of the interface.
522 oPointPartitions.resize(2);
523
524 putPointsInCorrectPartition(oPointPartitions, intersecPoints, nodeCoord);
525
526 // Export start and end points of
527 // the intersection line.
528 oCrackStartXi = std :: min(minDistArcPos [ 0 ], minDistArcPos [ 1 ]);
529 oCrackEndXi = std :: max(minDistArcPos [ 0 ], minDistArcPos [ 1 ]);
530
531 oIntersection = true;
532 return;
533 } else if ( intersecPoints.size() == 1 ) {
534 std :: vector< FloatArray >edgeCoords;
535
536 FloatArray tipCoord;
537 tipCoord.resize(dim);
538
539 bool foundTip = false;
540 double tipArcPos = -1.0;
541
542 if ( ei->giveElementTipCoord(tipCoord, tipArcPos, * element, elCenter) ) {
543 foundTip = true;
544 tipCoord.resizeWithValues(dim);
545 }
546 int nEdges = this->element->giveInterpolation()->giveNumberOfEdges(element->giveGeometryType());
547 if ( foundTip ) {
548 oPointPartitions.clear();
549
550 // Divide into subdomains
551 int triPassed = 0;
552 for ( int i = 1; i <= nEdges; i++ ) {
553 const auto &bNodes = this->element->giveInterpolation()->boundaryGiveNodes(i, element->giveGeometryType());
554
555 if ( bNodes.giveSize() == 2 ) {
556
557 int nsLoc = bNodes.at(1);
558 int neLoc = bNodes.at( bNodes.giveSize() );
559
560 const auto &coordS = element->giveDofManager(nsLoc)->giveCoordinates();
561 const auto &coordE = element->giveDofManager(neLoc)->giveCoordinates();
562
563 if ( i == intersecEdgeInd [ 0 ] ) {
564 oPointPartitions.push_back( std :: vector< FloatArray >() );
565 oPointPartitions [ triPassed ].push_back(tipCoord);
566 oPointPartitions [ triPassed ].push_back(intersecPoints [ 0 ]);
567 oPointPartitions [ triPassed ].push_back(coordE);
568 triPassed++;
569
570 oPointPartitions.push_back( std :: vector< FloatArray >() );
571 oPointPartitions [ triPassed ].push_back(tipCoord);
572 oPointPartitions [ triPassed ].push_back(coordS);
573 oPointPartitions [ triPassed ].push_back(intersecPoints [ 0 ]);
574 triPassed++;
575 } else {
576 oPointPartitions.push_back( std :: vector< FloatArray >() );
577 oPointPartitions [ triPassed ].push_back(tipCoord);
578 oPointPartitions [ triPassed ].push_back(coordS);
579 oPointPartitions [ triPassed ].push_back(coordE);
580 triPassed++;
581 }
582 } else if( bNodes.giveSize() == 3 ) {
583
584 // Start
585 const auto &coordS = element->giveDofManager(bNodes[0])->giveCoordinates();
586
587 // Center
588 const auto &coordC = element->giveDofManager(bNodes[2])->giveCoordinates();
589
590 // End
591 const auto &coordE = element->giveDofManager(bNodes[1])->giveCoordinates();
592
593
594 if ( i == intersecEdgeInd [ 0 ] ) {
595
596 // Check if the intersection point is closer to the start or end, compared to the center point.
597 double dist_S_2 = distance_square(intersecPoints[0], coordS);
598// double dist_E_2 = distance_square(intersecPoints[0], coordE);
599 double dist_C_2 = distance_square(coordC, coordS);
600
601 if( dist_S_2 < dist_C_2 ) {
602 oPointPartitions.push_back( std :: vector< FloatArray >() );
603 oPointPartitions [ triPassed ].push_back(intersecPoints [ 0 ]);
604 oPointPartitions [ triPassed ].push_back(tipCoord);
605 oPointPartitions [ triPassed ].push_back(coordS);
606 triPassed++;
607
608 oPointPartitions.push_back( std :: vector< FloatArray >() );
609 oPointPartitions [ triPassed ].push_back(coordC);
610 oPointPartitions [ triPassed ].push_back(tipCoord);
611 oPointPartitions [ triPassed ].push_back(intersecPoints [ 0 ]);
612 triPassed++;
613
614 oPointPartitions.push_back( std :: vector< FloatArray >() );
615 oPointPartitions [ triPassed ].push_back(coordE);
616 oPointPartitions [ triPassed ].push_back(tipCoord);
617 oPointPartitions [ triPassed ].push_back(coordC);
618 triPassed++;
619
620 } else {
621
622 oPointPartitions.push_back( std :: vector< FloatArray >() );
623 oPointPartitions [ triPassed ].push_back(coordC);
624 oPointPartitions [ triPassed ].push_back(tipCoord);
625 oPointPartitions [ triPassed ].push_back(coordS);
626 triPassed++;
627
628
629 oPointPartitions.push_back( std :: vector< FloatArray >() );
630 oPointPartitions [ triPassed ].push_back(intersecPoints [ 0 ]);
631 oPointPartitions [ triPassed ].push_back(tipCoord);
632 oPointPartitions [ triPassed ].push_back(coordC);
633 triPassed++;
634
635 oPointPartitions.push_back( std :: vector< FloatArray >() );
636 oPointPartitions [ triPassed ].push_back(coordE);
637 oPointPartitions [ triPassed ].push_back(tipCoord);
638 oPointPartitions [ triPassed ].push_back(coordC);
639 triPassed++;
640
641 }
642
643
644 } else {
645 oPointPartitions.push_back( std :: vector< FloatArray >() );
646 oPointPartitions [ triPassed ].push_back(tipCoord);
647 oPointPartitions [ triPassed ].push_back(coordS);
648 oPointPartitions [ triPassed ].push_back(coordC);
649 triPassed++;
650
651 oPointPartitions.push_back( std :: vector< FloatArray >() );
652 oPointPartitions [ triPassed ].push_back(tipCoord);
653 oPointPartitions [ triPassed ].push_back(coordC);
654 oPointPartitions [ triPassed ].push_back(coordE);
655 triPassed++;
656 }
657
658 }
659 else {
660 printf("bNodes.giveSize(): %d\n", bNodes.giveSize() );
661 OOFEM_ERROR("Unsupported size of bNodes.")
662 }
663 }
664
665 // Export start and end points of
666 // the intersection line.
667 oCrackStartXi = std :: min(minDistArcPos [ 0 ], tipArcPos);
668 oCrackEndXi = std :: max(minDistArcPos [ 0 ], tipArcPos);
669 } // If a tip was found
670 else {
671 // printf( "Warning: no tip found in element %d with only one edge intersection.\n", element->giveGlobalNumber() );
672
673 oPointPartitions.resize(1);
674
675 for ( int i = 1; i <= this->element->giveNumberOfDofManagers(); i++ ) {
676 const auto &nodeCoord = element->giveDofManager(i)->giveCoordinates();
677 oPointPartitions [ 0 ].push_back(nodeCoord);
678 }
679
680 // test Jim
681 // Add first intersection point
682 oPointPartitions [ 0 ].push_back(intersecPoints [ 0 ]);
683
684 // want to add the extrapolated intersection point
685 //FloatArray test;
686 //test.setValues(2, 0.0, 0.4);
687 //oPointPartitions [ 0 ].push_back( test );
688
689 // Export start and end points of
690 // the intersection line.
691 oCrackStartXi = minDistArcPos [ 0 ];
692 oCrackEndXi = tipArcPos;
693 }
694
695 oIntersection = true;
696
697
698 //oPointPartitions.resize(0);
699 //oIntersection = true;
700 //false;
701 return;
702 }
703
704 oIntersection = false;
705}
706
707void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: vector< std :: vector< FloatArray > > &oPointPartitions, double &oCrackStartXi, double &oCrackEndXi, const Triangle &iTri, int iEnrItemIndex, bool &oIntersection)
708{
709 int dim = element->giveDofManager(1)->giveCoordinates().giveSize();
710
711 FloatArray elCenter( iTri.giveVertex(1).giveSize() );
712 elCenter.zero();
713 std :: vector< const FloatArray * >nodeCoord;
714 for ( int i = 1; i <= 3; i++ ) {
715 nodeCoord.push_back( & iTri.giveVertex(i) );
716 elCenter.add( iTri.giveVertex(i) );
717 }
718 elCenter.times(1.0 / 3.0);
719
720
721 XfemManager *xMan = this->element->giveDomain()->giveXfemManager();
722 GeometryBasedEI *ei = dynamic_cast< GeometryBasedEI * >( xMan->giveEnrichmentItem(iEnrItemIndex) );
723
724 if ( ei == nullptr ) {
725 oIntersection = false;
726 return;
727 }
728
729 std :: vector< FloatArray >intersecPoints;
730 std :: vector< int >intersecEdgeInd;
731
732 std :: vector< double >minDistArcPos;
733 ei->computeIntersectionPoints(intersecPoints, intersecEdgeInd, element, iTri, minDistArcPos);
734 for ( size_t i = 0; i < intersecPoints.size(); i++ ) {
735 intersecPoints [ i ].resizeWithValues(dim);
736 }
737
738 if ( intersecPoints.size() == 2 ) {
739 // The element is completely cut in two.
740 // Therefore, we create two subpartitions:
741 // one on each side of the interface.
742
743 oPointPartitions.resize(2);
744
745 putPointsInCorrectPartition(oPointPartitions, intersecPoints, nodeCoord);
746
747 // Export start and end points of
748 // the intersection line.
749 oCrackStartXi = std :: min(minDistArcPos [ 0 ], minDistArcPos [ 1 ]);
750 oCrackEndXi = std :: max(minDistArcPos [ 0 ], minDistArcPos [ 1 ]);
751
752 oIntersection = true;
753 return;
754 } else if ( intersecPoints.size() == 1 ) {
755 int nEdges = 3;
756 std :: vector< FloatArray >edgeCoords, nodeCoords;
757
758 FloatArray tipCoord;
759 int dim = element->giveDofManager(1)->giveCoordinates().giveSize();
760 tipCoord.resize(dim);
761
762 bool foundTip = false;
763 double tipArcPos = -1.0;
764
765 if ( ei->giveElementTipCoord(tipCoord, tipArcPos, * element, elCenter) ) {
766 tipCoord.resizeWithValues(dim);
767 foundTip = true;
768 }
769
770 if ( foundTip ) {
771 oPointPartitions.resize( ( nEdges + 1 ) );
772
773 // Divide into subdomains
774 int triPassed = 0;
775 for ( int i = 1; i <= nEdges; i++ ) {
776 const FloatArray &coordS = iTri.giveVertex(i);
777
778 int endInd = i + 1;
779 if ( i == nEdges ) {
780 endInd = 1;
781 }
782 const FloatArray &coordE = iTri.giveVertex(endInd);
783
784 if ( i == intersecEdgeInd [ 0 ] ) {
785 oPointPartitions [ triPassed ].push_back(tipCoord);
786 oPointPartitions [ triPassed ].push_back(intersecPoints [ 0 ]);
787 oPointPartitions [ triPassed ].push_back(coordE);
788 triPassed++;
789
790 oPointPartitions [ triPassed ].push_back(tipCoord);
791 oPointPartitions [ triPassed ].push_back(coordS);
792 oPointPartitions [ triPassed ].push_back(intersecPoints [ 0 ]);
793 triPassed++;
794 } else {
795 oPointPartitions [ triPassed ].push_back(tipCoord);
796 oPointPartitions [ triPassed ].push_back(coordS);
797 oPointPartitions [ triPassed ].push_back(coordE);
798 triPassed++;
799 }
800 }
801
802 // Export start and end points of
803 // the intersection line.
804 oCrackStartXi = std :: min(minDistArcPos [ 0 ], tipArcPos);
805 oCrackEndXi = std :: max(minDistArcPos [ 0 ], tipArcPos);
806 } // If a tip was found
807 else {
808 oPointPartitions.resize(1);
809
810 for ( int i = 1; i <= 3; i++ ) {
811 const FloatArray &nodeCoord = iTri.giveVertex(i);
812 oPointPartitions [ 0 ].push_back(nodeCoord);
813 }
814
815 // Export start and end points of
816 // the intersection line.
817 oCrackStartXi = minDistArcPos [ 0 ];
818 oCrackEndXi = tipArcPos;
819 }
820
821 oIntersection = true;
822 return;
823 }
824
825 oIntersection = false;
826}
827
828void XfemElementInterface :: putPointsInCorrectPartition(std :: vector< std :: vector< FloatArray > > &oPointPartitions,
829 const std :: vector< FloatArray > &iIntersecPoints,
830 const std :: vector< const FloatArray * > &iNodeCoord) const
831{
832 for ( size_t i = 0; i < iIntersecPoints.size(); i++ ) {
833 oPointPartitions [ 0 ].push_back(iIntersecPoints [ i ]);
834 oPointPartitions [ 1 ].push_back(iIntersecPoints [ i ]);
835 }
836
837 // Check on which side of the interface each node is located.
838 const double &x1 = iIntersecPoints [ 0 ].at(1);
839 const double &x2 = iIntersecPoints [ 1 ].at(1);
840 const double &y1 = iIntersecPoints [ 0 ].at(2);
841 const double &y2 = iIntersecPoints [ 1 ].at(2);
842
843 for ( size_t i = 1; i <= iNodeCoord.size(); i++ ) {
844 const double &x = iNodeCoord [ i - 1 ]->at(1);
845 const double &y = iNodeCoord [ i - 1 ]->at(2);
846 double det = ( x1 - x ) * ( y2 - y ) - ( x2 - x ) * ( y1 - y );
847
848 if ( det > 0.0 ) {
849 oPointPartitions [ 0 ].push_back(* iNodeCoord [ i - 1 ]);
850 } else {
851 oPointPartitions [ 1 ].push_back(* iNodeCoord [ i - 1 ]);
852 }
853 }
854}
855
856void XfemElementInterface :: partitionEdgeSegment(int iBndIndex, std :: vector< Line > &oSegments, std :: vector< FloatArray > &oIntersectionPoints, const double &iTangDistPadding)
857{
858 const double levelSetTol2 = 1.0e-12;
859 // const double gammaPadding = 0.001;
860
861 XfemManager *xMan = this->element->giveDomain()->giveXfemManager();
862
863 FEInterpolation *interp = element->giveInterpolation(); // Geometry interpolation
864 FEInterpolation2d *interp2d = dynamic_cast< FEInterpolation2d * >( interp );
865 if ( interp2d == nullptr ) {
866 OOFEM_ERROR("In XfemElementInterface :: partitionEdgeSegment: failed to cast to FEInterpolation2d.\n")
867 }
868 const auto &edgeNodes = interp2d->computeLocalEdgeMapping(iBndIndex);
869
870 // Fetch start and end points.
871 const auto &xS = element->giveDofManager( edgeNodes.at(1) )->giveCoordinates();
872 const auto &xE = element->giveDofManager( edgeNodes.at(2) )->giveCoordinates();
873
874 // The point of departure is the original edge segment.
875 // This segment will be subdivided as many times as necessary.
876 Line seg1(xS, xE);
877 // oSegments.clear();
878 oSegments.push_back(seg1);
879
880
881 // Loop over enrichment items
882 int numEI = xMan->giveNumberOfEnrichmentItems();
883 for ( int eiIndex = 1; eiIndex <= numEI; eiIndex++ ) {
884 EnrichmentItem *ei = xMan->giveEnrichmentItem(eiIndex);
885
886 std :: vector< Line >newSegments;
887
888 // Loop over segments
889 size_t numSeg = oSegments.size();
890 for ( size_t segInd = 0; segInd < numSeg; segInd++ ) {
891 // Check if the segment is cut by the current enrichment item
892
893 const auto &seg_xS = oSegments [ segInd ].giveVertex(1);
894 const auto &seg_xE = oSegments [ segInd ].giveVertex(2);
895
896
897 // Local coordinates of vertices
898 FloatArray xiS;
899 bool evaluationSucceeded = true;
900 if ( !element->computeLocalCoordinates(xiS, seg_xS) ) {
901 //TODO: Check for numerical round-off error
902 // printf("xiS: "); xiS.printYourself();
903 // evaluationSucceeded = false;
904 }
905 FloatArray xiE;
906 if ( !element->computeLocalCoordinates(xiE, seg_xE) ) {
907 // printf("xiE: "); xiE.printYourself();
908 // evaluationSucceeded = false;
909 }
910
911 const IntArray &elNodes = element->giveDofManArray();
912 FloatArray Ns, Ne;
913 interp->evalN( Ns, xiS, FEIElementGeometryWrapper(element) );
914 interp->evalN( Ne, xiE, FEIElementGeometryWrapper(element) );
915
916 double phiS = 0.0, phiE = 0.0;
917 double gammaS = 0.0, gammaE = 0.0;
918
919
920 for ( int i = 1; i <= Ns.giveSize(); i++ ) {
921 const auto &nodePos = element->giveNode(i)->giveCoordinates();
922 double phiNode = 0.0;
923 if ( !ei->evalLevelSetNormalInNode(phiNode, elNodes [ i - 1 ], nodePos) ) {
924 evaluationSucceeded = false;
925 }
926
927 double gammaNode = 0.0;
928 if ( !ei->evalLevelSetTangInNode(gammaNode, elNodes [ i - 1 ], nodePos) ) {
929 evaluationSucceeded = false;
930 }
931
932 phiS += Ns.at(i) * phiNode;
933 gammaS += Ns.at(i) * gammaNode;
934
935 phiE += Ne.at(i) * phiNode;
936 gammaE += Ne.at(i) * gammaNode;
937 }
938
939
940 if ( phiS * phiE < levelSetTol2 && evaluationSucceeded ) {
941 double xi = EnrichmentItem :: calcXiZeroLevel(phiS, phiE);
942 double gamma = 0.5 * ( 1.0 - xi ) * gammaS + 0.5 * ( 1.0 + xi ) * gammaE;
943
944 // If we are inside in tangential direction
945 if ( gamma > -iTangDistPadding ) {
946 // If so, subdivide it ...
947
948 // Compute global coordinates of the intersection point
949 int nDim = std :: min( seg_xS.giveSize(), seg_xE.giveSize() );
950 FloatArray p;
951 p.resize(nDim);
952
953 for ( int i = 1; i <= nDim; i++ ) {
954 ( p.at(i) ) = 0.5 * ( 1.0 - xi ) * ( ( seg_xS.at(i) ) ) + 0.5 * ( 1.0 + xi ) * ( ( seg_xE.at(i) ) );
955 }
956
957 Line segA(seg_xS, p);
958 newSegments.push_back(segA);
959 Line segB(p, seg_xE);
960 newSegments.push_back(segB);
961
962 // Export the intersection point
963 oIntersectionPoints.push_back(p);
964 } else {
965 newSegments.push_back(oSegments [ segInd ]);
966 }
967 } else {
968 // ... else keep the segment.
969 newSegments.push_back(oSegments [ segInd ]);
970 }
971 }
972
973 oSegments = newSegments;
974 }
975}
976
977MaterialMode XfemElementInterface :: giveMaterialMode()
978{
979 if ( mUsePlaneStrain ) {
980 return _PlaneStrain;
981 } else {
982 return _PlaneStress;
983 }
984}
985
986void XfemElementInterface :: updateYourselfCZ(TimeStep *tStep)
987{
988 size_t numSeg = mpCZIntegrationRules.size();
989
990 for ( size_t i = 0; i < numSeg; i++ ) {
991 if ( mpCZIntegrationRules [ i ] != nullptr ) {
992 mpCZIntegrationRules [ i ]->updateYourself(tStep);
993 }
994 }
995
996 numSeg = mpCZExtraIntegrationRules.size();
997 for ( size_t i = 0; i < numSeg; i++ ) {
998 if ( mpCZExtraIntegrationRules [ i ] != nullptr ) {
999 mpCZExtraIntegrationRules [ i ]->updateYourself(tStep);
1000 }
1001 }
1002
1003}
1004
1005void XfemElementInterface :: computeDisplacementJump(oofem :: GaussPoint &iGP, oofem :: FloatArray &oJump, const oofem :: FloatArray &iSolVec, const oofem :: FloatMatrix &iNMatrix)
1006{
1007 const int dim = 2;
1008 oJump.resize(dim);
1009 oJump.beProductOf(iNMatrix, iSolVec);
1010}
1011
1012void XfemElementInterface :: computeNCohesive(FloatMatrix &oN, GaussPoint &iGP, int iEnrItemIndex, const std :: vector< int > &iTouchingEnrItemIndices)
1013{
1014 const int dim = 2;
1015
1016 FloatArray Nc, globalCoord, localCoord;
1017 globalCoord = iGP.giveGlobalCoordinates();
1018 element->computeLocalCoordinates(localCoord, globalCoord);
1019 FEInterpolation *interp = element->giveInterpolation();
1020 interp->evalN( Nc, localCoord, FEIElementGeometryWrapper(element) );
1021
1022 const int nDofMan = element->giveNumberOfDofManagers();
1023
1024 // XFEM part of N-matrix
1025 XfemManager *xMan = element->giveDomain()->giveXfemManager();
1026 double enrDofsScaleFactor = xMan->giveEnrDofScaleFactor();
1027
1028
1029 [[maybe_unused]] int counter = nDofMan * dim;
1030
1031 std :: vector< std :: vector< double > >Nd(nDofMan);
1032
1033 for ( int j = 1; j <= nDofMan; j++ ) {
1034 DofManager *dMan = element->giveDofManager(j);
1035
1036 // Compute the total number of enrichments for node j
1037 int numEnrNode = XfemElementInterface_giveNumDofManEnrichments(* dMan, * xMan);
1038 std :: vector< double > &NdNode = Nd [ j - 1 ];
1039 NdNode.assign(numEnrNode, 0.0);
1040
1041
1042 int globalNodeInd = dMan->giveGlobalNumber();
1043
1044
1045 int ndNodeInd = 0;
1046 const std :: vector< int > &nodeEiIndices = xMan->giveNodeEnrichmentItemIndices(globalNodeInd);
1047 for ( size_t i = 0; i < nodeEiIndices.size(); i++ ) {
1048 EnrichmentItem *ei = xMan->giveEnrichmentItem(nodeEiIndices [ i ]);
1049
1050 GeometryBasedEI *geoEI = dynamic_cast< GeometryBasedEI * >( ei );
1051
1052 if ( geoEI != nullptr ) {
1053 if ( geoEI->isDofManEnriched(* dMan) ) {
1054 int numEnr = geoEI->giveNumDofManEnrichments(* dMan);
1055
1056 std :: vector< double >efJumps;
1057 bool gpLivesOnCurrentCrack = ( nodeEiIndices [ i ] == iEnrItemIndex );
1058
1059 bool gpLivesOnInteractingCrack = false;
1060 for ( int touchingEIIndex : iTouchingEnrItemIndices ) {
1061 if ( nodeEiIndices [ i ] == touchingEIIndex ) {
1062 gpLivesOnInteractingCrack = true;
1063 }
1064 }
1065
1066 if ( nodeEiIndices [ i ] == iEnrItemIndex || gpLivesOnInteractingCrack ) {
1067 geoEI->evaluateEnrFuncJumps(efJumps, globalNodeInd, iGP, gpLivesOnCurrentCrack);
1068 }
1069
1070 for ( int k = 0; k < numEnr; k++ ) {
1071 if ( nodeEiIndices [ i ] == iEnrItemIndex || gpLivesOnInteractingCrack ) {
1072 NdNode [ ndNodeInd ] = efJumps [ k ] * Nc.at(j);
1073 } else {
1074 NdNode [ ndNodeInd ] = 0.0;
1075 }
1076
1077 counter++;
1078 ndNodeInd++;
1079 }
1080 }
1081 }
1082 }
1083 }
1084
1085 int numN = nDofMan;
1086
1087 for ( int j = 1; j <= nDofMan; j++ ) {
1088 numN += Nd [ j - 1 ].size();
1089 }
1090
1091 FloatArray NTot;
1092 NTot.resize(numN);
1093 NTot.zero();
1094 int column = 1;
1095
1096 for ( int i = 1; i <= nDofMan; i++ ) {
1097 // NTot.at(column) = Nc.at(i); // We do not want the continuous part.
1098 column++;
1099
1100 const std :: vector< double > &NdNode = Nd [ i - 1 ];
1101 for ( size_t j = 1; j <= NdNode.size(); j++ ) {
1102 NTot.at(column) = NdNode [ j - 1 ]*enrDofsScaleFactor;
1103 column++;
1104 }
1105 }
1106
1107 oN.beNMatrixOf(NTot, 2);
1108}
1109} // end namespace oofem
#define N(a, b)
const FloatArray & giveVertex(int n) const
Definition geometry.h:124
void triangulate(const std ::vector< FloatArray > &iVertices, std ::vector< Triangle > &oTriangles) const
Definition delaunay.C:80
int giveGlobalNumber() const
Definition dofmanager.h:515
double giveCoordinate(int i) const
Definition dofmanager.h:383
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
int giveElementPlaceInArray(int iGlobalElNum) const
Definition domain.C:188
XfemManager * giveXfemManager()
Definition domain.C:378
bool hasXfemManager()
Definition domain.C:389
Node * giveNode(int i) const
Definition element.h:629
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
bool evalLevelSetTangInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
virtual void evaluateEnrFuncInNode(std ::vector< double > &oEnrFunc, const Node &iNode) const =0
int giveNumDofManEnrichments(const DofManager &iDMan) const
virtual void evaluateEnrFuncDerivAt(std ::vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const =0
bool isDofManEnriched(const DofManager &iDMan) const
virtual void evaluateEnrFuncAt(std ::vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const =0
bool evalLevelSetNormalInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
virtual IntArray computeLocalEdgeMapping(int iedge) const =0
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
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
void times(double s)
Definition floatarray.C:834
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void beNMatrixOf(const FloatArray &n, int nsd)
void setSubMatrix(const FloatMatrix &src, int sr, int sc)
double at(std::size_t i, std::size_t j) const
const FloatArray & giveGlobalCoordinates()
Definition gausspoint.h:159
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
void evaluateEnrFuncJumps(std ::vector< double > &oEnrFuncJumps, int iNodeInd, GaussPoint &iGP, bool iGPLivesOnCurrentCrack) const
virtual void computeIntersectionPoints(std ::vector< FloatArray > &oIntersectionPoints, std ::vector< int > &oIntersectedEdgeInd, Element *element, std ::vector< double > &oMinDistArcPos) const
bool giveElementTipCoord(FloatArray &oCoord, double &oArcPos, Element &iEl, const FloatArray &iElCenter) const override
Interface()
Constructor.
Definition interface.h:86
static ParamKey IPK_XfemElementInterface_CohesiveZoneMaterial
std ::vector< std ::unique_ptr< IntegrationRule > > mpCZExtraIntegrationRules
virtual void XfemElementInterface_partitionElement(std ::vector< Triangle > &oTriangles, const std ::vector< FloatArray > &iPoints)
Partitions the element into patches by a triangulation.
void ComputeBOrBHMatrix(FloatMatrix &oAnswer, GaussPoint &iGP, Element &iEl, bool iComputeBH, const FloatArray &iNaturalGpCoord)
void putPointsInCorrectPartition(std ::vector< std ::vector< FloatArray > > &oPointPartitions, const std ::vector< FloatArray > &iIntersecPoints, const std ::vector< const FloatArray * > &iNodeCoord) const
virtual void XfemElementInterface_prepareNodesForDelaunay(std ::vector< std ::vector< FloatArray > > &oPointPartitions, double &oCrackStartXi, double &oCrackEndXi, int iEnrItemIndex, bool &oIntersection)
Returns an array of array of points. Each array of points defines the points of a subregion of the el...
static ParamKey IPK_XfemElementInterface_NumIntPointsCZ
std ::vector< std ::unique_ptr< IntegrationRule > > mpCZIntegrationRules
void XfemElementInterface_createEnrNmatrixAt(FloatMatrix &oAnswer, const FloatArray &iLocCoord, Element &iEl, bool iSetDiscontContribToZero)
Creates enriched N-matrix.
bool mUsePlaneStrain
Flag that tells if plane stress or plane strain is assumed.
int XfemElementInterface_giveNumDofManEnrichments(const DofManager &iDMan, XfemManager &iXMan) const
static ParamKey IPK_XfemElementInterface_PlaneStrain
bool isElementEnriched(const Element *elem)
bool giveVtkDebug() const
void giveElementEnrichmentItemIndices(std ::vector< int > &oElemEnrInd, int iElementIndex) const
int giveNumGpPerTri() const
Domain * giveDomain()
const std ::vector< int > & giveNodeEnrichmentItemIndices(int iNodeIndex) const
EnrichmentItem * giveEnrichmentItem(int n)
double giveEnrDofScaleFactor() const
int giveNumberOfEnrichmentItems() const
#define OOFEM_ERROR(...)
Definition error.h:79
static FloatArray Vec2(const double &a, const double &b)
Definition floatarray.h:606
double det(const FloatMatrixF< 2, 2 > &mat)
Computes the determinant.
double distance_square(const FloatArray &x, const FloatArray &y)
FloatArrayF< N > column(const FloatMatrixF< N, M > &mat, std::size_t col)

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