OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
xfemstructuralelementinterface.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 - 2013 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 "../sm/Materials/InterfaceMaterials/structuralinterfacematerial.h"
37 #include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h"
38 #include "../sm/Elements/structuralelement.h"
39 #include "../sm/CrossSections/structuralcrosssection.h"
40 #include "gaussintegrationrule.h"
41 #include "gausspoint.h"
42 #include "dynamicinputrecord.h"
43 #include "feinterpol.h"
44 #include "spatiallocalizer.h"
45 #include "engngm.h"
47 #include "mathfem.h"
48 
51 
54 #include "xfem/XFEMDebugTools.h"
55 #include "xfem/xfemtolerances.h"
56 
59 
60 #include "vtkxmlexportmodule.h"
61 
63 #include "mathfem.h"
64 #include <cmath>
65 
66 #include <string>
67 #include <sstream>
68 
69 
71 //
72 // Alt. I : include_bulk_jump = 1 and include_bulk_corr = 1
73 //
74 // Alt. II : include_bulk_jump = 1 and include_bulk_corr = 0
75 //
76 // Alt. III: include_bulk_jump = 0 and include_bulk_corr = 0
77 
78 
79 namespace oofem {
82  mpCZMat(NULL),
83  mCZMaterialNum(-1),
84  mCSNumGaussPoints(4),
85  mIncludeBulkJump(true),
86  mIncludeBulkCorr(true)
87 {
88 
89 
90 }
91 
93 
95 {
96  const double tol2 = 1.0e-18;
97 
98  bool partitionSucceeded = false;
99 
100 
101  if ( mpCZMat != NULL ) {
102  mpCZIntegrationRules_tmp.clear();
104  mIntRule_tmp.clear();
105  mCZEnrItemIndices.clear();
107  }
108 
109  XfemManager *xMan = this->element->giveDomain()->giveXfemManager();
110  if ( xMan->isElementEnriched(element) ) {
111  if ( mpCZMat == NULL && mCZMaterialNum > 0 ) {
113  }
114 
115 
117 
118  bool firstIntersection = true;
119 
120  std :: vector< std :: vector< FloatArray > >pointPartitions;
121  mSubTri.clear();
122 
123  std :: vector< int >enrichingEIs;
124  int elPlaceInArray = xMan->giveDomain()->giveElementPlaceInArray( element->giveGlobalNumber() );
125  xMan->giveElementEnrichmentItemIndices(enrichingEIs, elPlaceInArray);
126 
127 
128  for ( size_t p = 0; p < enrichingEIs.size(); p++ ) {
129  // Index of current ei
130  int eiIndex = enrichingEIs [ p ];
131 
132  // Indices of other ei interaction with this ei through intersection enrichment fronts.
133  std :: vector< int >touchingEiIndices;
134  giveIntersectionsTouchingCrack(touchingEiIndices, enrichingEIs, eiIndex, * xMan);
135 
136  if ( firstIntersection ) {
137 
138  // Get the points describing each subdivision of the element
139  double startXi, endXi;
140  bool intersection = false;
141  this->XfemElementInterface_prepareNodesForDelaunay(pointPartitions, startXi, endXi, eiIndex, intersection);
142 
143  if ( intersection ) {
144  firstIntersection = false;
145 
146  // Use XfemElementInterface_partitionElement to subdivide the element
147  for ( int i = 0; i < int ( pointPartitions.size() ); i++ ) {
148  // Triangulate the subdivisions
149  this->XfemElementInterface_partitionElement(mSubTri, pointPartitions [ i ]);
150  }
151 
152 
153  if ( mpCZMat != NULL ) {
154  Crack *crack = dynamic_cast< Crack * >( xMan->giveEnrichmentItem(eiIndex) );
155  if ( crack == NULL ) {
156  OOFEM_ERROR("Cohesive zones are only available for cracks.")
157  }
158 
159  // We have xi_s and xi_e. Fetch sub polygon.
160  std :: vector< FloatArray >crackPolygon;
161  crack->giveSubPolygon(crackPolygon, startXi, endXi);
162 
164  // Add cohesive zone Gauss points
165  size_t numSeg = crackPolygon.size() - 1;
166 
167  for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) {
168  int czRuleNum = 1;
169  mpCZIntegrationRules_tmp.emplace_back( new GaussIntegrationRule(czRuleNum, element) );
170 
171  if(mIncludeBulkCorr) {
172  mpCZExtraIntegrationRules_tmp.emplace_back( new GaussIntegrationRule(czRuleNum, element) );
173  }
174 
175  size_t cz_rule_ind = mpCZIntegrationRules_tmp.size() - 1;
176 
177  // Add index of current ei
178  mCZEnrItemIndices.push_back(eiIndex);
179 
180  // Add indices of other ei, that cause interaction through
181  // intersection enrichment fronts
182  mCZTouchingEnrItemIndices.push_back(touchingEiIndices);
183 
184  // Compute crack normal
185  FloatArray crackTang;
186  crackTang.beDifferenceOf(crackPolygon [ segIndex + 1 ], crackPolygon [ segIndex ]);
187 
188  if ( crackTang.computeSquaredNorm() > tol2 ) {
189  crackTang.normalize();
190  }
191  else {
192  // Oops, we got a segment of length zero.
193  // These Gauss weights will be zero, so we can
194  // set the tangent to anything reasonable
195  crackTang = {0.0, 1.0};
196 
197  }
198 
199  FloatArray crackNormal = {
200  -crackTang.at(2), crackTang.at(1)
201  };
202 
203  mpCZIntegrationRules_tmp [ cz_rule_ind ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode,
204  crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]);
205 
206  if(mIncludeBulkCorr) {
207  mpCZExtraIntegrationRules_tmp [ cz_rule_ind ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode,
208  crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]);
209  }
210 
211  for ( GaussPoint *gp: *mpCZIntegrationRules_tmp [ cz_rule_ind ] ) {
212  double gw = gp->giveWeight();
213  double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]);
214  gw *= 0.5 * segLength;
215  gp->setWeight(gw);
216 
217  // Fetch material status and set normal
219  if ( ms ) {
220  ms->letNormalBe(crackNormal);
221  }
222  else {
224 
225  if(fe2ms) {
226  fe2ms->letNormalBe(crackNormal);
227 
228  PrescribedGradientBCWeak *bc = dynamic_cast<PrescribedGradientBCWeak*>( fe2ms->giveBC() );
229 
230  if(bc) {
231  FloatArray periodicityNormal = crackNormal;
232 
233  periodicityNormal.normalize();
234 
235  if( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) {
236  // Rotate 90 degrees (works equally well for periodicity)
237  periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)};
238  }
239 
240  bc->setPeriodicityNormal(periodicityNormal);
241  bc->recomputeTractionMesh();
242  }
243  }
244  else {
245  OOFEM_ERROR("Failed to fetch material status.");
246  }
247  }
248 
249 
250  // Give Gauss point reference to the enrichment item
251  // to simplify post processing.
252  crack->AppendCohesiveZoneGaussPoint(gp);
253  }
254 
255 
256  if(mIncludeBulkCorr) {
257 
258  for ( GaussPoint *gp: *mpCZExtraIntegrationRules_tmp [ cz_rule_ind ] ) {
259  double gw = gp->giveWeight();
260  double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]);
261  gw *= 0.5 * segLength;
262  gp->setWeight(gw);
263 
264  // Fetch material status and set normal
265  StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( gp->giveMaterialStatus() );
266  if ( ms ) {
267  ms->letNormalBe(crackNormal);
268  }
269  else {
270  StructuralFE2MaterialStatus *fe2ms = dynamic_cast<StructuralFE2MaterialStatus*>( gp->giveMaterialStatus() );
271 
272  if(fe2ms) {
273  fe2ms->letNormalBe(crackNormal);
274 
275  PrescribedGradientBCWeak *bc = dynamic_cast<PrescribedGradientBCWeak*>( fe2ms->giveBC() );
276 
277  if(bc) {
278  FloatArray periodicityNormal = crackNormal;
279  periodicityNormal.normalize();
280 
281  if( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) {
282  // Rotate 90 degrees (works equally well for periodicity)
283  periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)};
284  }
285 
286  bc->setPeriodicityNormal(periodicityNormal);
287  bc->recomputeTractionMesh();
288 
289  }
290  }
291  else {
292  // Macroscale material model: nothing needs to be done.
293  }
294  }
295 
296  }
297 
298  }
299 
300  }
301  }
302 
303  partitionSucceeded = true;
304  }
305  } // if(firstIntersection)
306  else {
307  // Loop over triangles
308  std :: vector< Triangle >allTriCopy;
309  for ( size_t triIndex = 0; triIndex < mSubTri.size(); triIndex++ ) {
310  // Call alternative version of XfemElementInterface_prepareNodesForDelaunay
311  std :: vector< std :: vector< FloatArray > >pointPartitionsTri;
312  double startXi, endXi;
313  bool intersection = false;
314  XfemElementInterface_prepareNodesForDelaunay(pointPartitionsTri, startXi, endXi, mSubTri [ triIndex ], eiIndex, intersection);
315 
316  if ( intersection ) {
317  // Use XfemElementInterface_partitionElement to subdivide triangle j
318  for ( int i = 0; i < int ( pointPartitionsTri.size() ); i++ ) {
319  this->XfemElementInterface_partitionElement(allTriCopy, pointPartitionsTri [ i ]);
320  }
321 
322 
323  // Add cohesive zone Gauss points
324 
325  if ( mpCZMat != NULL ) {
326  Crack *crack = dynamic_cast< Crack * >( xMan->giveEnrichmentItem(eiIndex) );
327  if ( crack == NULL ) {
328  OOFEM_ERROR("Cohesive zones are only available for cracks.")
329  }
330 
331  // We have xi_s and xi_e. Fetch sub polygon.
332  std :: vector< FloatArray >crackPolygon;
333  crack->giveSubPolygon(crackPolygon, startXi, endXi);
334 
335  int numSeg = crackPolygon.size() - 1;
336 
337  for ( int segIndex = 0; segIndex < numSeg; segIndex++ ) {
338  int czRuleNum = 1;
339  mpCZIntegrationRules_tmp.emplace_back( new GaussIntegrationRule(czRuleNum, element) );
340 
341  if(mIncludeBulkCorr) {
342  mpCZExtraIntegrationRules_tmp.emplace_back( new GaussIntegrationRule(czRuleNum, element) );
343  }
344 
345  size_t newRuleInd = mpCZIntegrationRules_tmp.size() - 1;
346  mCZEnrItemIndices.push_back(eiIndex);
347 
348  mCZTouchingEnrItemIndices.push_back(touchingEiIndices);
349 
350  // Compute crack normal
351  FloatArray crackTang;
352  crackTang.beDifferenceOf(crackPolygon [ segIndex + 1 ], crackPolygon [ segIndex ]);
353 
354  if ( crackTang.computeSquaredNorm() > tol2 ) {
355  crackTang.normalize();
356  }
357  else {
358  // Oops, we got a segment of length zero.
359  // These Gauss weights will be zero, so we can
360  // set the tangent to anything reasonable
361  crackTang = {0.0, 1.0};
362 
363  }
364 
365  FloatArray crackNormal = {
366  -crackTang.at(2), crackTang.at(1)
367  };
368 
369  mpCZIntegrationRules_tmp [ newRuleInd ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode,
370  crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]);
371 
372  if(mIncludeBulkCorr) {
373  mpCZExtraIntegrationRules_tmp [ newRuleInd ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode,
374  crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]);
375  }
376 
377  for ( GaussPoint *gp: *mpCZIntegrationRules_tmp [ newRuleInd ] ) {
378  double gw = gp->giveWeight();
379  double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]);
380  gw *= 0.5 * segLength;
381  gp->setWeight(gw);
382 
383  // Fetch material status and set normal
385  if ( ms ) {
386  ms->letNormalBe(crackNormal);
387  }
388  else {
390 
391  if(fe2ms) {
392  fe2ms->letNormalBe(crackNormal);
393 
394  PrescribedGradientBCWeak *bc = dynamic_cast<PrescribedGradientBCWeak*>( fe2ms->giveBC() );
395 
396  if(bc) {
397  FloatArray periodicityNormal = crackNormal;
398 
399  periodicityNormal.normalize();
400 
401  if( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) {
402  // Rotate 90 degrees (works equally well for periodicity)
403  periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)};
404  }
405 
406  bc->setPeriodicityNormal(periodicityNormal);
407  bc->recomputeTractionMesh();
408  }
409  }
410  else {
411  OOFEM_ERROR("Failed to fetch material status.");
412  }
413  }
414 
415 
416  // Give Gauss point reference to the enrichment item
417  // to simplify post processing.
418  crack->AppendCohesiveZoneGaussPoint(gp);
419  }
420 
421  if(mIncludeBulkCorr) {
422 
423  for ( GaussPoint *gp: *mpCZExtraIntegrationRules_tmp [ newRuleInd ] ) {
424  double gw = gp->giveWeight();
425  double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]);
426  gw *= 0.5 * segLength;
427  gp->setWeight(gw);
428 
429 
430  // Fetch material status and set normal
432  if ( ms ) {
433  ms->letNormalBe(crackNormal);
434  }
435  else {
437 
438  if(fe2ms) {
439  fe2ms->letNormalBe(crackNormal);
440 
441  PrescribedGradientBCWeak *bc = dynamic_cast<PrescribedGradientBCWeak*>( fe2ms->giveBC() );
442 
443  if(bc) {
444  FloatArray periodicityNormal = crackNormal;
445 
446  periodicityNormal.normalize();
447 
448  if( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) {
449  // Rotate 90 degrees (works equally well for periodicity)
450  periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)};
451  }
452 
453  bc->setPeriodicityNormal(periodicityNormal);
454  bc->recomputeTractionMesh();
455  }
456  }
457  else {
458  OOFEM_ERROR("Failed to fetch material status.");
459  }
460  }
461 
462 
463  // Give Gauss point reference to the enrichment item
464  // to simplify post processing.
465  crack->AppendCohesiveZoneGaussPoint(gp);
466  }
467  }
468  }
469  }
470  } else {
471  allTriCopy.push_back(mSubTri [ triIndex ]);
472  }
473  }
474 
475  mSubTri = allTriCopy;
476  }
477  }
478 
479  // Refine triangles if desired
480  int numRefs = xMan->giveNumTriRefs();
481 
482  for(int i = 0; i < numRefs; i++) {
483 
484  std :: vector< Triangle > triRef;
485 
486  for(const Triangle &tri : mSubTri) {
487  Triangle::refineTriangle(triRef, tri);
488  }
489 
490  mSubTri = triRef;
491  }
492 
494  // When we reach this point, we have a
495  // triangulation that is adapted to all
496  // cracks passing through the element.
497  // Therefore, we can set up integration
498  // points on each triangle.
499 
500 // printf("totalCrackLengthInEl: %e\n", totalCrackLengthInEl);
501 
502  if ( xMan->giveVtkDebug() ) {
503  std :: stringstream str3;
504  int elIndex = this->element->giveGlobalNumber();
505  str3 << "TriEl" << elIndex << ".vtk";
506  std :: string name3 = str3.str();
507 
508  if ( mSubTri.size() > 0 ) {
510  }
511  }
512 
513 
514  int ruleNum = 1;
515 
516  if ( partitionSucceeded ) {
517  std :: vector< std :: unique_ptr< IntegrationRule > >intRule;
518  mIntRule_tmp.emplace_back( new PatchIntegrationRule(ruleNum, element, mSubTri) );
519  mIntRule_tmp [ 0 ]->SetUpPointsOnTriangle(xMan->giveNumGpPerTri(), matMode);
520  }
521 
522 
523  if ( xMan->giveVtkDebug() ) {
525  // Write CZ GP to VTK
526 
527  std :: vector< FloatArray >czGPCoord;
528 
529  for ( size_t czRulInd = 0; czRulInd < mpCZIntegrationRules_tmp.size(); czRulInd++ ) {
530  for ( GaussPoint *gp: *mpCZIntegrationRules_tmp [ czRulInd ] ) {
531  czGPCoord.push_back( gp->giveGlobalCoordinates() );
532  }
533  }
534 
535  double time = 0.0;
536 
537  Domain *dom = element->giveDomain();
538  if ( dom != NULL ) {
539  EngngModel *em = dom->giveEngngModel();
540  if ( em != NULL ) {
541  TimeStep *ts = em->giveCurrentStep();
542  if ( ts != NULL ) {
543  time = ts->giveTargetTime();
544  }
545  }
546  }
547 
548  std :: stringstream str;
549  int elIndex = this->element->giveGlobalNumber();
550  str << "CZGaussPointsTime" << time << "El" << elIndex << ".vtk";
551  std :: string name = str.str();
552 
553  XFEMDebugTools :: WritePointsToVTK(name, czGPCoord);
555  }
556 
557 
558 
559  bool map_state_variables = true;
560  if(map_state_variables) {
561 
563  // Copy bulk GPs
564  int num_ir_new = mIntRule_tmp.size();
565  for( int i = 0; i < num_ir_new; i++ ) {
566 
567  for(GaussPoint *gp_new : *(mIntRule_tmp[i]) ) {
568 
569 
570  // Fetch new material status. Create it if it does not exist.
571  MaterialStatus *ms_new = dynamic_cast<MaterialStatus*>( gp_new->giveMaterialStatus() );
572  if(!ms_new) {
573  StructuralElement *s_el = dynamic_cast<StructuralElement*>(element);
575  cs->createMaterialStatus(*gp_new);
576  ms_new = dynamic_cast<MaterialStatus*>( gp_new->giveMaterialStatus() );
577  }
578 
579 
580 
581  // Find closest old GP.
582  double closest_dist = 0.0;
583  MaterialStatus *ms_old = giveClosestGP_MatStat( closest_dist, element->giveIntegrationRulesArray() , gp_new->giveGlobalCoordinates());
584 
585  if(ms_old) {
586 
587  // Copy state variables.
588  MaterialStatusMapperInterface *mapper_interface = dynamic_cast<MaterialStatusMapperInterface*>( ms_new );
589 
590  if(mapper_interface) {
591 // printf("Successfully casted to MaterialStatusMapperInterface.\n");
592  mapper_interface->copyStateVariables(*ms_old);
593  }
594  else {
595  OOFEM_ERROR("Failed casting to MaterialStatusMapperInterface.")
596  }
597  }
598 
599  }
600 
601  }
603 
604 
605 
607  // Copy CZ GPs
608  if( mCZMaterialNum > 0 ) {
609 
610  num_ir_new = mpCZIntegrationRules_tmp.size();
611  for( int i = 0; i < num_ir_new; i++ ) {
612 
613  for(GaussPoint *gp_new : *(mpCZIntegrationRules_tmp[i]) ) {
614 
615  // Fetch new material status. Create it if it does not exist.
616  MaterialStatus *ms_new = dynamic_cast<MaterialStatus*>( gp_new->giveMaterialStatus() );
617  if(!ms_new) {
618  ms_new = mpCZMat->CreateStatus(gp_new);
619  }
620 
621  // Find closest old GP.
622  double closest_dist_cz = 0.0;
623  MaterialStatus *ms_old = giveClosestGP_MatStat(closest_dist_cz, mpCZIntegrationRules , gp_new->giveGlobalCoordinates());
624 
625  // If we are using the nonstandard cz formulation, we
626  // also consider mapping from bulk GPs.
628  bool non_std_cz = false;
629  if(xsMan) {
630  non_std_cz = xsMan->giveUseNonStdCz();
631  }
632 
633  if(non_std_cz) {
634  double closest_dist_bulk = 0.0;
635  MaterialStatus *ms_old_bulk = giveClosestGP_MatStat(closest_dist_bulk, element->giveIntegrationRulesArray() , gp_new->giveGlobalCoordinates());
636  if( closest_dist_bulk < closest_dist_cz ) {
637  printf("Bulk is closest. Dist: %e\n", closest_dist_bulk);
638  ms_old = ms_old_bulk;
639  }
640  }
641 
642  if(ms_old) {
643 
644  // Copy state variables.
645  MaterialStatusMapperInterface *mapper_interface = dynamic_cast<MaterialStatusMapperInterface*>( ms_new );
646 
647  if(mapper_interface) {
648  mapper_interface->copyStateVariables(*ms_old);
649  }
650  else {
651  OOFEM_ERROR("Failed casting to MaterialStatusMapperInterface.")
652  }
653  }
654 
655  }
656  }
657  }
658 
660 
661 
662 
663 
665  // Copy "extra" CZ GPs (Used for non-standard CZ model)
666  if( mCZMaterialNum > 0 && mIncludeBulkCorr ) {
667 
668  num_ir_new = mpCZExtraIntegrationRules_tmp.size();
669  for( int i = 0; i < num_ir_new; i++ ) {
670 
671  for(GaussPoint *gp_new : *(mpCZExtraIntegrationRules_tmp[i]) ) {
672 
673  // Fetch new material status. Create it if it does not exist.
674  MaterialStatus *ms_new = dynamic_cast<MaterialStatus*>( gp_new->giveMaterialStatus() );
675  if(!ms_new) {
676  ms_new = mpCZMat->CreateStatus(gp_new);
677  }
678 
679  // Find closest old GP.
680  double closest_dist_cz = 0.0;
681  MaterialStatus *ms_old = giveClosestGP_MatStat(closest_dist_cz, mpCZExtraIntegrationRules , gp_new->giveGlobalCoordinates());
682 
683  // If we are using the nonstandard cz formulation, we
684  // also consider mapping from bulk GPs.
686  bool non_std_cz = false;
687  if(xsMan) {
688  non_std_cz = xsMan->giveUseNonStdCz();
689  }
690 
691  if(non_std_cz) {
692  double closest_dist_bulk = 0.0;
693  MaterialStatus *ms_old_bulk = giveClosestGP_MatStat(closest_dist_bulk, element->giveIntegrationRulesArray() , gp_new->giveGlobalCoordinates());
694  if( closest_dist_bulk < closest_dist_cz ) {
695  printf("Bulk is closest. Dist: %e\n", closest_dist_bulk);
696  ms_old = ms_old_bulk;
697  }
698  }
699 
700  if(ms_old) {
701 
702  // Copy state variables.
703  MaterialStatusMapperInterface *mapper_interface = dynamic_cast<MaterialStatusMapperInterface*>( ms_new );
704 
705  if(mapper_interface) {
706  mapper_interface->copyStateVariables(*ms_old);
707  }
708  else {
709  OOFEM_ERROR("Failed casting to MaterialStatusMapperInterface.")
710  }
711  }
712 
713  }
714  }
715  }
716  else {
717 // printf("No extra CZ GPs to map.\n");
718  }
719 
721 
722 
723  }
724 
725 
726  }
727 
728 
729  if ( partitionSucceeded ) {
731 
732  if(mIncludeBulkCorr) {
734  }
735 
736  element->setIntegrationRules( std :: move(mIntRule_tmp) );
737  }
738 
739  return partitionSucceeded;
740 }
741 
742 MaterialStatus* XfemStructuralElementInterface :: giveClosestGP_MatStat(double &oClosestDist, std :: vector< std :: unique_ptr< IntegrationRule > > &iRules, const FloatArray &iCoord)
743 {
744 
745  double min_dist2 = std::numeric_limits<double>::max();
746  MaterialStatus *closest_ms = NULL;
747 
748  for(size_t i = 0; i < iRules.size(); i++) {
749  for(GaussPoint *gp : *(iRules[i]) ) {
750 
751  const FloatArray &x = gp->giveGlobalCoordinates();
752  if( x.distance_square(iCoord) < min_dist2 ) {
753  min_dist2 = x.distance_square(iCoord);
754 // printf("min_dist2: %e\n", min_dist2 );
755  closest_ms = dynamic_cast<MaterialStatus*>( gp->giveMaterialStatus() );
756  }
757 
758  }
759  }
760 
761  oClosestDist = sqrt(min_dist2);
762  return closest_ms;
763 }
764 
766 {
767 
768 #if 0
769  return 1.0*sqrt( iFe2Ms->giveBC()->domainSize() );
770 // return 2.0*sqrt( iFe2Ms->giveBC()->domainSize() );
771 
772 #else
773  // TODO: Cover also angle < 0 and angle > 90.
774 
775  const FloatArray &n = iFe2Ms->giveNormal();
776  double l_box = sqrt( iFe2Ms->giveBC()->domainSize() );
777 
778  const FloatArray t = {n(1), -n(0)};
779  double angle = atan2( t(1), t(0) );
780 
781  if( angle < 0.25*M_PI ){
782  // angle < 45 degrees
783 
784  double l_s = l_box*(cos(angle));
785  return l_s;
786  }
787  else {
788  // angle >= 45 degrees
789 
790  double l_s = l_box*(sin(angle));
791  return l_s;
792  }
793 #endif
794 
795 }
796 
798 {
799  if ( element->giveDomain()->hasXfemManager() ) {
801  CrossSection *cs = NULL;
802 
803  const std :: vector< int > &materialModifyingEnrItemIndices = xMan->giveMaterialModifyingEnrItemIndices();
804  for ( size_t i = 0; i < materialModifyingEnrItemIndices.size(); i++ ) {
805  EnrichmentItem &ei = * ( xMan->giveEnrichmentItem(materialModifyingEnrItemIndices [ i ]) );
806 
807  if ( ei.isMaterialModified(* gp, * element, cs) ) {
808  StructuralCrossSection *structCS = dynamic_cast< StructuralCrossSection * >( cs );
809 
810  if ( structCS != NULL ) {
811  if ( mUsePlaneStrain ) {
812  structCS->giveStiffnessMatrix_PlaneStrain(answer, rMode, gp, tStep);
813  } else {
814  structCS->giveStiffnessMatrix_PlaneStress(answer, rMode, gp, tStep);
815  }
816  return;
817  } else {
818  OOFEM_ERROR("failed to fetch StructuralMaterial");
819  }
820  }
821  }
822  }
823 
824  // If no enrichment modifies the material,
825  // compute stiffness based on the bulk material.
827  if ( mUsePlaneStrain ) {
828  cs->giveStiffnessMatrix_PlaneStrain(answer, rMode, gp, tStep);
829  } else {
830  cs->giveStiffnessMatrix_PlaneStress(answer, rMode, gp, tStep);
831  }
832 }
833 
835 {
837  if ( cs == NULL ) {
838  OOFEM_ERROR("cs == NULL.");
839  }
840 
841  if ( element->giveDomain()->hasXfemManager() ) {
843 
844 
845  CrossSection *csInclusion = NULL;
846  const std :: vector< int > &materialModifyingEnrItemIndices = xMan->giveMaterialModifyingEnrItemIndices();
847  for ( size_t i = 0; i < materialModifyingEnrItemIndices.size(); i++ ) {
848  EnrichmentItem &ei = * ( xMan->giveEnrichmentItem(materialModifyingEnrItemIndices [ i ]) );
849 
850  if ( ei.isMaterialModified(* gp, * element, csInclusion) ) {
851  StructuralCrossSection *structCSInclusion = dynamic_cast< StructuralCrossSection * >( csInclusion );
852 
853  if ( structCSInclusion != NULL ) {
854  if ( mUsePlaneStrain ) {
855  structCSInclusion->giveRealStress_PlaneStrain(answer, gp, strain, tStep);
856  } else {
857  structCSInclusion->giveRealStress_PlaneStress(answer, gp, strain, tStep);
858  }
859 
860  return;
861  } else {
862  OOFEM_ERROR("failed to fetch StructuralCrossSection");
863  }
864  }
865  }
866  }
867 
868  // If no enrichment modifies the material:
869  if ( mUsePlaneStrain ) {
870  cs->giveRealStress_PlaneStrain(answer, gp, strain, tStep);
871  } else {
872  cs->giveRealStress_PlaneStress(answer, gp, strain, tStep);
873  }
874 }
875 
877 {
878  if(!useNonStdCz()) {
879 
880  if ( hasCohesiveZone() ) {
881  FloatArray solVec;
882  element->computeVectorOf(VM_Total, tStep, solVec);
883 
884  size_t numSeg = mpCZIntegrationRules.size();
885  for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) {
886  for ( GaussPoint *gp: *mpCZIntegrationRules [ segIndex ] ) {
888  // Compute a (slightly modified) N-matrix
889 
890  FloatMatrix NMatrix;
891  computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]);
893 
894 
895  // Traction
896  FloatArray T2D;
897 
898 
899  // Fetch material status and get normal
901  if ( ms == NULL ) {
902  OOFEM_ERROR("Failed to fetch material status.");
903  }
904 
905  ms->setNewlyInserted(false); //TODO: Do this in a better place. /ES
906 
907  FloatArray crackNormal( ms->giveNormal() );
908 
909  // Compute jump vector
910  FloatArray jump2D;
911  computeDisplacementJump(* gp, jump2D, solVec, NMatrix);
912 
913 
914  computeGlobalCohesiveTractionVector(T2D, jump2D, crackNormal, NMatrix, * gp, tStep);
915 
916  // Add to internal force
917  FloatArray NTimesT;
918 
919  NTimesT.beTProductOf(NMatrix, T2D);
921  double thickness = cs->give(CS_Thickness, gp);
922  double dA = thickness * gp->giveWeight();
923  answer.add(dA, NTimesT);
924  }
925  }
926  }
927  }
928  else {
929  // Non-standard cz formulation.
930 // printf("Using non-standard cz formulation.\n");
931 
932  if ( hasCohesiveZone() ) {
933  FloatArray solVec;
934  element->computeVectorOf(VM_Total, tStep, solVec);
935 
936  StructuralFE2Material *fe2Mat = dynamic_cast<StructuralFE2Material*>(mpCZMat);
937  if(!fe2Mat) {
938  OOFEM_ERROR("Failed to cast StructuralFE2Material*.")
939  }
940 
941 
942  size_t numSeg = mpCZIntegrationRules.size();
943  for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) {
944  for(int gpInd = 0; gpInd < mpCZIntegrationRules[ segIndex ]->giveNumberOfIntegrationPoints(); gpInd++) {
945 
946  GaussPoint *gp = mpCZIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd);
947 
948  GaussPoint *bulk_gp = NULL;
949  if(mIncludeBulkCorr) {
950  bulk_gp = mpCZExtraIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd);
951  }
952 
953  StructuralMaterial *bulkMat = dynamic_cast<StructuralMaterial*>( element->giveCrossSection()->giveMaterial(bulk_gp) );
954  if(!bulkMat) {
955  OOFEM_ERROR("Failed to fetch bulk material.")
956  }
957 
959 
960  if(fe2ms == NULL) {
961  OOFEM_ERROR("The material status is not of an allowed type.")
962  }
963 
965  // Compute jump
966 
967  // Compute a (slightly modified) N-matrix
968  FloatMatrix NMatrix;
969  computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]);
970 
971  FloatArray jump2D;
972  computeDisplacementJump(* gp, jump2D, solVec, NMatrix);
973 
975  // Fetch normal
976  FloatArray crackNormal( fe2ms->giveNormal() );
977 
978 
980  // Fetch L_s
981  double l_s = computeEffectiveSveSize( fe2ms );
982 
983 
985  // Construct strain (only consider the smeared jump for now)
986  FloatArray smearedJumpStrain = {jump2D(0)*crackNormal(0)/l_s, jump2D(1)*crackNormal(1)/l_s, 0.0, 0.0, 0.0, (1.0/l_s)*( jump2D(0)*crackNormal(1) + jump2D(1)*crackNormal(0) )};
987 
988  FloatArray smearedBulkStrain(6);
989  smearedBulkStrain.zero();
990  FloatMatrix BAvg;
991 
992  if(mIncludeBulkJump) {
994  // Bulk contribution to SVE strain
995 
996  // Crack gp coordinates
997  const FloatArray &xC = gp->giveGlobalCoordinates();
998 
999  // For now, we will just perturb the coordinates of the GP to compute B^- and B^+ numerically.
1000  double eps = 1.0e-6;
1001  FloatArray xPert = xC;
1002 
1003  xPert.add(eps, crackNormal);
1004  FloatArray locCoordPert;
1005  element->computeLocalCoordinates(locCoordPert, xPert);
1006 
1007  FloatMatrix BPlus;
1008  this->ComputeBOrBHMatrix(BPlus, *gp, *element, false, locCoordPert);
1009 
1010  xPert = xC;
1011  xPert.add(-eps, crackNormal);
1012  element->computeLocalCoordinates(locCoordPert, xPert);
1013 
1014  FloatMatrix BMinus;
1015  this->ComputeBOrBHMatrix(BMinus, *gp, *element, false, locCoordPert);
1016 
1017  BAvg = BPlus;
1018  BAvg.add(1.0, BMinus);
1019  BAvg.times(0.5);
1020 
1021  smearedBulkStrain.beProductOf(BAvg, solVec);
1022 
1023  if( smearedBulkStrain.giveSize() == 4 ) {
1024  smearedBulkStrain = {smearedBulkStrain(0), smearedBulkStrain(1), smearedBulkStrain(2), 0.0, 0.0, smearedBulkStrain(3)};
1025  }
1026 
1027  FloatArray smearedJumpStrainTemp = smearedJumpStrain;
1028 
1029  smearedJumpStrain.add(smearedBulkStrain);
1030  }
1031 
1032 
1034  // Compute homogenized stress
1035  StructuralElement *se = dynamic_cast<StructuralElement*>(this->element);
1036  if(!se) {
1037  OOFEM_ERROR("Failed to cast StructuralElement.")
1038  }
1039 
1040  FloatArray stressVec;
1041 
1042  fe2Mat->giveRealStressVector_3d(stressVec, gp, smearedJumpStrain, tStep);
1043 // printf("stressVec: "); stressVec.printYourself();
1044 
1045 
1046  FloatArray trac = {stressVec(0)*crackNormal(0)+stressVec(5)*crackNormal(1), stressVec(5)*crackNormal(0)+stressVec(1)*crackNormal(1)};
1047 
1049  // Standard part
1050 
1051  // Add to internal force
1052  FloatArray NTimesT;
1053 
1054  NTimesT.beTProductOf(NMatrix, trac);
1056  double thickness = cs->give(CS_Thickness, gp);
1057  double dA = thickness * gp->giveWeight();
1058  answer.add(dA, NTimesT);
1059 
1060 
1061  if(mIncludeBulkCorr) {
1062 
1063  FloatArray stressVecBulk;
1064  bulkMat->giveRealStressVector_3d(stressVecBulk, bulk_gp, smearedBulkStrain, tStep);
1065 
1067  // Non-standard jump part
1068  FloatArray stressV4 = {stressVec(0)-stressVecBulk(0), stressVec(1)-stressVecBulk(1), stressVec(2)-stressVecBulk(2), stressVec(5)-stressVecBulk(5)};
1069  FloatArray BTimesT;
1070  BTimesT.beTProductOf(BAvg, stressV4);
1071  answer.add(1.0*dA*l_s, BTimesT);
1072  }
1073 
1074  }
1075  }
1076  }
1077 
1078  }
1079 }
1080 
1082 {
1083  FloatMatrix F;
1084  F.resize(3, 3);
1085  F.beUnitMatrix(); // TODO: Compute properly
1086 
1087 
1088  FloatArray jump3D = {
1089  iJump.at(1), iJump.at(2), 0.0
1090  };
1091 
1092 
1093  FloatArray crackNormal3D = {
1094  iCrackNormal.at(1), iCrackNormal.at(2), 0.0
1095  };
1096 
1097  FloatArray ez = {
1098  0.0, 0.0, 1.0
1099  };
1100  FloatArray crackTangent3D;
1101  crackTangent3D.beVectorProductOf(crackNormal3D, ez);
1102 
1103  FloatMatrix locToGlob(3, 3);
1104  locToGlob.setColumn(crackTangent3D, 1);
1105  locToGlob.setColumn(crackNormal3D, 2);
1106  locToGlob.setColumn(ez, 3);
1107 
1108  FloatArray TLoc, jump3DLoc, TLocRenumbered(3);
1109  jump3DLoc.beTProductOf(locToGlob, jump3D);
1110 
1111  FloatArray jump3DLocRenumbered = {
1112  jump3DLoc.at(3), jump3DLoc.at(1), jump3DLoc.at(2)
1113  };
1114 
1116  if(intMat) {
1117  intMat->giveFirstPKTraction_3d(TLocRenumbered, & iGP, jump3DLocRenumbered, F, tStep);
1118  }
1119  else {
1120  OOFEM_ERROR("Failed to cast StructuralInterfaceMaterial*.")
1121  }
1122 
1123  TLoc = {
1124  TLocRenumbered.at(2), TLocRenumbered.at(3), TLocRenumbered.at(1)
1125  };
1126 
1127 
1128  FloatArray T;
1129  T.beProductOf(locToGlob, TLoc);
1130 
1131  oT = {
1132  T.at(1), T.at(2)
1133  };
1134 }
1135 
1137 {
1138 
1139  if(!useNonStdCz()) {
1140 
1141  if ( hasCohesiveZone() ) {
1142  FloatArray solVec;
1143  element->computeVectorOf(VM_Total, tStep, solVec);
1144 
1145  size_t numSeg = mpCZIntegrationRules.size();
1146 
1148  if(!intMat) {
1149  OOFEM_ERROR("Failed to cast StructuralInterfaceMaterial*.")
1150  }
1151 
1152 
1153  for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) {
1154  for ( GaussPoint *gp: *mpCZIntegrationRules [ segIndex ] ) {
1156  // Compute a (slightly modified) N-matrix
1157 
1158  FloatMatrix NMatrix;
1159  computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]);
1160 
1162  // Compute jump vector
1163  FloatArray jump2D;
1164  computeDisplacementJump(* gp, jump2D, solVec, NMatrix);
1165 
1166  FloatArray jump3D = {
1167  0.0, jump2D.at(1), jump2D.at(2)
1168  };
1169 
1170  // Compute traction
1171  FloatMatrix F;
1172  F.resize(3, 3);
1173  F.beUnitMatrix(); // TODO: Compute properly
1174 
1175  FloatMatrix K3DRenumbered, K3DGlob;
1176 
1177 
1178  FloatMatrix K2D;
1179  K2D.resize(2, 2);
1180  K2D.zero();
1181 
1182  if ( intMat->hasAnalyticalTangentStiffness() ) {
1184  // Analytical tangent
1185 
1186  FloatMatrix K3D;
1187  intMat->give3dStiffnessMatrix_dTdj(K3DRenumbered, TangentStiffness, gp, tStep);
1188 
1189  K3D.resize(3, 3);
1190  K3D.zero();
1191  K3D.at(1, 1) = K3DRenumbered.at(2, 2);
1192  K3D.at(1, 2) = K3DRenumbered.at(2, 3);
1193  K3D.at(1, 3) = K3DRenumbered.at(2, 1);
1194 
1195  K3D.at(2, 1) = K3DRenumbered.at(3, 2);
1196  K3D.at(2, 2) = K3DRenumbered.at(3, 3);
1197  K3D.at(2, 3) = K3DRenumbered.at(3, 1);
1198 
1199  K3D.at(3, 1) = K3DRenumbered.at(1, 2);
1200  K3D.at(3, 2) = K3DRenumbered.at(1, 3);
1201  K3D.at(3, 3) = K3DRenumbered.at(1, 1);
1202 
1203 
1204  // Fetch material status and get normal
1206  if ( ms == NULL ) {
1207  OOFEM_ERROR("Failed to fetch material status.");
1208  }
1209 
1210  FloatArray crackNormal( ms->giveNormal() );
1211 
1212  FloatArray crackNormal3D = {
1213  crackNormal.at(1), crackNormal.at(2), 0.0
1214  };
1215 
1216  FloatArray ez = {
1217  0.0, 0.0, 1.0
1218  };
1219  FloatArray crackTangent3D;
1220  crackTangent3D.beVectorProductOf(crackNormal3D, ez);
1221 
1222  FloatMatrix locToGlob(3, 3);
1223  locToGlob.setColumn(crackTangent3D, 1);
1224  locToGlob.setColumn(crackNormal3D, 2);
1225  locToGlob.setColumn(ez, 3);
1226 
1227 
1228  FloatMatrix tmp3(3, 3);
1229  tmp3.beProductTOf(K3D, locToGlob);
1230  K3DGlob.beProductOf(locToGlob, tmp3);
1231 
1232  K2D.at(1, 1) = K3DGlob.at(1, 1);
1233  K2D.at(1, 2) = K3DGlob.at(1, 2);
1234  K2D.at(2, 1) = K3DGlob.at(2, 1);
1235  K2D.at(2, 2) = K3DGlob.at(2, 2);
1236  } else {
1238  // Numerical tangent
1239  double eps = 1.0e-9;
1240 
1241  FloatArray T, TPert;
1242 
1243  // Fetch material status and get normal
1245  if ( ms == NULL ) {
1246  OOFEM_ERROR("Failed to fetch material status.");
1247  }
1248 
1249  FloatArray crackNormal( ms->giveNormal() );
1250 
1251  computeGlobalCohesiveTractionVector(T, jump2D, crackNormal, NMatrix, * gp, tStep);
1252 
1253 
1254  FloatArray jump2DPert;
1255 
1256 
1257  jump2DPert = jump2D;
1258  jump2DPert.at(1) += eps;
1259  computeGlobalCohesiveTractionVector(TPert, jump2DPert, crackNormal, NMatrix, * gp, tStep);
1260 
1261  K2D.at(1, 1) = ( TPert.at(1) - T.at(1) ) / eps;
1262  K2D.at(2, 1) = ( TPert.at(2) - T.at(2) ) / eps;
1263 
1264  jump2DPert = jump2D;
1265  jump2DPert.at(2) += eps;
1266  computeGlobalCohesiveTractionVector(TPert, jump2DPert, crackNormal, NMatrix, * gp, tStep);
1267 
1268  K2D.at(1, 2) = ( TPert.at(1) - T.at(1) ) / eps;
1269  K2D.at(2, 2) = ( TPert.at(2) - T.at(2) ) / eps;
1270 
1271  computeGlobalCohesiveTractionVector(T, jump2D, crackNormal, NMatrix, * gp, tStep);
1272  }
1273 
1274  FloatMatrix tmp, tmp2;
1275  tmp.beProductOf(K2D, NMatrix);
1276  tmp2.beTProductOf(NMatrix, tmp);
1277 
1279  double thickness = cs->give(CS_Thickness, gp);
1280  double dA = thickness * gp->giveWeight();
1281  answer.add(dA, tmp2);
1282  }
1283  }
1284  }
1285  }
1286  else {
1287  // Non-standard cz formulation.
1288 
1289 
1290  FloatArray solVec;
1291  element->computeVectorOf(VM_Total, tStep, solVec);
1292 
1293  size_t numSeg = mpCZIntegrationRules.size();
1294 
1295  StructuralFE2Material *fe2Mat = dynamic_cast<StructuralFE2Material*>(mpCZMat);
1296  if(!fe2Mat) {
1297  OOFEM_ERROR("Failed to cast StructuralFE2Material*.")
1298  }
1299 
1300  for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) {
1301 // for ( GaussPoint *gp: *mpCZIntegrationRules [ segIndex ] ) {
1302  for(int gpInd = 0; gpInd < mpCZIntegrationRules[ segIndex ]->giveNumberOfIntegrationPoints(); gpInd++) {
1303 
1304  GaussPoint *gp = mpCZIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd);
1305 
1306  GaussPoint *bulk_gp = NULL;
1307  StructuralMaterial *bulkMat = NULL;
1308  if(mIncludeBulkCorr) {
1309  bulk_gp = mpCZExtraIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd);
1310  bulkMat = dynamic_cast<StructuralMaterial*>( element->giveCrossSection()->giveMaterial(bulk_gp) );
1311 
1312  if(!bulkMat) {
1313  OOFEM_ERROR("Failed to fetch bulk material.")
1314  }
1315 
1316  }
1317 
1318 
1320 
1321  if(fe2ms == NULL) {
1322  OOFEM_ERROR("The material status is not of an allowed type.")
1323  }
1324 
1326  // Compute a (slightly modified) N-matrix
1327 
1328  FloatMatrix NMatrix;
1329  computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]);
1330 
1331 
1333  // Fetch normal
1334  FloatArray n( fe2ms->giveNormal() );
1335 
1336  // Traction part of tangent
1337  FloatMatrix C;
1338  fe2Mat->give3dMaterialStiffnessMatrix(C, TangentStiffness, gp, tStep);
1339 
1340  FloatMatrix CBulk;
1341  if(mIncludeBulkCorr) {
1342  bulkMat->give3dMaterialStiffnessMatrix(CBulk, TangentStiffness, bulk_gp, tStep);
1343  }
1344 
1345 
1347  // Fetch L_s
1348  double l_s = computeEffectiveSveSize( fe2ms );
1349 
1350  FloatMatrix Ka(2,2);
1351  double a1 = 1.0;
1352  double a2 = 1.0;
1353  double a3 = 1.0;
1354  Ka(0,0) = (0.5/l_s)*( C(0,0)*n(0)*n(0) + a2*C(0,5)*n(0)*n(1) + a1*C(5,0)*n(1)*n(0) + a3*C(5,5)*n(1)*n(1) ) +
1355  (0.5/l_s)*( C(0,0)*n(0)*n(0) + a2*C(0,5)*n(0)*n(1) + a1*C(5,0)*n(1)*n(0) + a3*C(5,5)*n(1)*n(1) );
1356 
1357  Ka(0,1) = (0.5/l_s)*( a2*C(0,5)*n(0)*n(0) + C(0,1)*n(0)*n(1) + a3*C(5,5)*n(1)*n(0) + a1*C(5,1)*n(1)*n(1) ) +
1358  (0.5/l_s)*( a2*C(0,5)*n(0)*n(0) + C(0,1)*n(0)*n(1) + a3*C(5,5)*n(1)*n(0) + a1*C(5,1)*n(1)*n(1) );
1359 
1360 
1361  Ka(1,0) = (0.5/l_s)*( a1*C(5,0)*n(0)*n(0) + a3*C(5,5)*n(0)*n(1) + C(1,0)*n(1)*n(0) + a2*C(1,5)*n(1)*n(1) ) +
1362  (0.5/l_s)*( a1*C(5,0)*n(0)*n(0) + a3*C(5,5)*n(0)*n(1) + C(1,0)*n(1)*n(0) + a2*C(1,5)*n(1)*n(1) );
1363 
1364 
1365  Ka(1,1) = (0.5/l_s)*( a3*C(5,5)*n(0)*n(0) + a1*C(5,1)*n(0)*n(1) + a2*C(1,5)*n(1)*n(0) + C(1,1)*n(1)*n(1) ) +
1366  (0.5/l_s)*( a3*C(5,5)*n(0)*n(0) + a1*C(5,1)*n(0)*n(1) + a2*C(1,5)*n(1)*n(0) + C(1,1)*n(1)*n(1) );
1367 
1368 
1369  FloatMatrix tmp, tmp2;
1370  tmp.beProductOf(Ka, NMatrix);
1371  tmp2.beTProductOf(NMatrix, tmp);
1372 
1374  double thickness = cs->give(CS_Thickness, gp);
1375  double dA = thickness * gp->giveWeight();
1376  answer.add(dA, tmp2);
1377 
1378 
1379 
1380  FloatMatrix BAvg;
1381 
1382  if(mIncludeBulkJump) {
1384  // Bulk contribution to SVE strain
1385 
1386  // Crack gp coordinates
1387  const FloatArray &xC = gp->giveGlobalCoordinates();
1388 
1389  // For now, we will just perturb the coordinates of the GP to compute B^- and B^+ numerically.
1390  double eps = 1.0e-6;
1391  FloatArray xPert = xC;
1392 
1393  xPert.add(eps, n);
1394  FloatArray locCoordPert;
1395  element->computeLocalCoordinates(locCoordPert, xPert);
1396 
1397  FloatMatrix BPlus;
1398  this->ComputeBOrBHMatrix(BPlus, *gp, *element, false, locCoordPert);
1399 
1400  xPert = xC;
1401  xPert.add(-eps, n);
1402  element->computeLocalCoordinates(locCoordPert, xPert);
1403 
1404  FloatMatrix BMinus;
1405  this->ComputeBOrBHMatrix(BMinus, *gp, *element, false, locCoordPert);
1406 
1407  BAvg = BPlus;
1408  BAvg.add(1.0, BMinus);
1409  BAvg.times(0.5);
1410 
1411 
1412  FloatMatrix Kb(2,4); // Implicitly assumes plane strain. Fix later.
1413 
1414  Kb(0,0) = C(0,0)*n(0) + C(5,0)*n(1);
1415  Kb(0,1) = C(0,1)*n(0) + C(5,1)*n(1);
1416  Kb(0,3) = C(0,5)*n(0) + C(5,5)*n(1);
1417 
1418  Kb(1,0) = C(5,0)*n(0) + C(1,0)*n(1);
1419  Kb(1,1) = C(5,1)*n(0) + C(1,1)*n(1);
1420  Kb(1,3) = C(5,5)*n(0) + C(1,5)*n(1);
1421 
1422  tmp.beProductOf(Kb, BAvg);
1423  tmp2.beTProductOf(NMatrix, tmp);
1424  answer.add(dA, tmp2);
1425  }
1426 
1428  // Non-standard bulk contribution
1429 
1430  if(mIncludeBulkCorr) {
1431 
1432  tmp.beTranspositionOf(tmp2);
1433  answer.add(1.0*dA, tmp);
1434 
1435 
1436  FloatMatrix C4(4,4);
1437  C4(0,0) = C(0,0);
1438  C4(0,1) = C(0,1);
1439  C4(0,2) = C(0,2);
1440  C4(0,3) = C(0,5);
1441 
1442  C4(1,0) = C(1,0);
1443  C4(1,1) = C(1,1);
1444  C4(1,2) = C(1,2);
1445  C4(1,3) = C(1,5);
1446 
1447  C4(2,0) = C(2,0);
1448  C4(2,1) = C(2,1);
1449  C4(2,2) = C(2,2);
1450  C4(2,3) = C(2,5);
1451 
1452  C4(3,0) = C(5,0);
1453  C4(3,1) = C(5,1);
1454  C4(3,2) = C(5,2);
1455  C4(3,3) = C(5,5);
1456 
1457  tmp.beProductOf(C4, BAvg);
1458  tmp2.beTProductOf(BAvg, tmp);
1459  answer.add(1.0*dA*l_s, tmp2);
1460 
1461  FloatMatrix C4Bulk(4,4);
1462  C4Bulk(0,0) = CBulk(0,0);
1463  C4Bulk(0,1) = CBulk(0,1);
1464  C4Bulk(0,2) = CBulk(0,2);
1465  C4Bulk(0,3) = CBulk(0,5);
1466 
1467  C4Bulk(1,0) = CBulk(1,0);
1468  C4Bulk(1,1) = CBulk(1,1);
1469  C4Bulk(1,2) = CBulk(1,2);
1470  C4Bulk(1,3) = CBulk(1,5);
1471 
1472  C4Bulk(2,0) = CBulk(2,0);
1473  C4Bulk(2,1) = CBulk(2,1);
1474  C4Bulk(2,2) = CBulk(2,2);
1475  C4Bulk(2,3) = CBulk(2,5);
1476 
1477  C4Bulk(3,0) = CBulk(5,0);
1478  C4Bulk(3,1) = CBulk(5,1);
1479  C4Bulk(3,2) = CBulk(5,2);
1480  C4Bulk(3,3) = CBulk(5,5);
1481 
1482  tmp.beProductOf(C4Bulk, BAvg);
1483  tmp2.beTProductOf(BAvg, tmp);
1484  answer.add(-1.0*dA*l_s, tmp2);
1485  }
1486 
1487  }
1488  }
1489 
1490  }
1491 }
1492 
1494 {
1495  if ( hasCohesiveZone() ) {
1496  printf("Entering XfemElementInterface :: computeCohesiveTangentAt().\n");
1497  }
1498 }
1499 
1501 {
1502  StructuralElement *structEl = dynamic_cast< StructuralElement * >( element );
1503  if ( structEl == NULL ) {
1504  OOFEM_ERROR("Not a structural element");
1505  }
1506 
1507  int ndofs = structEl->computeNumberOfDofs();
1508  double density, dV;
1509  FloatMatrix n;
1510  IntArray mask;
1511 
1512  answer.resize(ndofs, ndofs);
1513  answer.zero();
1514  if ( !structEl->isActivated(tStep) ) {
1515  return;
1516  }
1517 
1518  structEl->giveMassMtrxIntegrationgMask(mask);
1519 
1520  mass = 0.;
1521 
1522  for ( GaussPoint *gp: *element->giveIntegrationRule(0) ) {
1523  structEl->computeNmatrixAt(gp->giveNaturalCoordinates(), n);
1524  density = structEl->giveStructuralCrossSection()->give('d', gp);
1525 
1526  if ( ipDensity != NULL ) {
1527  // Override density if desired
1528  density = * ipDensity;
1529  }
1530 
1531  dV = structEl->computeVolumeAround(gp);
1532  mass += density * dV;
1533 
1534  if ( mask.isEmpty() ) {
1535  answer.plusProductSymmUpper(n, n, density * dV);
1536  } else {
1537  for ( int i = 1; i <= ndofs; i++ ) {
1538  for ( int j = i; j <= ndofs; j++ ) {
1539  double summ = 0.;
1540  for ( int k = 1; k <= n.giveNumberOfRows(); k++ ) {
1541  if ( mask.at(k) == 0 ) {
1542  continue;
1543  }
1544 
1545  summ += n.at(k, i) * n.at(k, j);
1546  }
1547 
1548  answer.at(i, j) += summ * density * dV;
1549  }
1550  }
1551  }
1552  }
1553 
1554  answer.symmetrized();
1555 
1556  const double tol = 1.0e-9;
1557  const double regularizationCoeff = 1.0e-6;
1558  int numRows = answer.giveNumberOfRows();
1559  for ( int i = 0; i < numRows; i++ ) {
1560  if ( fabs( answer(i, i) ) < tol ) {
1561  answer(i, i) += regularizationCoeff;
1562  // printf("Found zero on diagonal.\n");
1563  }
1564  }
1565 }
1566 
1569 {
1570  IRResultType result; // Required by IR_GIVE_FIELD macro
1571 
1572  int material = -1;
1574  mCZMaterialNum = material;
1575 
1576 
1577  // Number of Gauss points used when integrating the cohesive zone
1579  // printf("mCSNumGaussPoints: %d\n", mCSNumGaussPoints );
1580 
1581  int planeStrainFlag = -1;
1583  if ( planeStrainFlag == 1 ) {
1584  mUsePlaneStrain = true;
1585  }
1586 
1587  return IRRT_OK;
1588 }
1589 
1591 {
1592  if ( mCZMaterialNum > 0 ) {
1594  }
1595 
1596  if ( mUsePlaneStrain ) {
1598  }
1599 
1601 }
1602 
1604 {
1605  if ( mCZMaterialNum > 0 ) {
1606 
1608 
1609  if ( mpCZMat == NULL ) {
1610  OOFEM_ERROR("Failed to fetch pointer for mpCZMat.");
1611  }
1612  }
1613 }
1614 
1616 {
1618  {
1619  XfemManager *xMan = this->element->giveDomain()->giveXfemManager();
1620  XfemStructureManager *xsMan = dynamic_cast<XfemStructureManager*>( xMan );
1621 
1622  if(xsMan) {
1623  if(xsMan->giveUseNonStdCz()) {
1624  return true;
1625  }
1626  else {
1627  return false;
1628  }
1629  }
1630  else {
1631  return false;
1632  }
1633  }
1634  else {
1635  return false;
1636  }
1637 }
1638 
1640 {
1641  // Computes the deformation gradient in the Voigt format at the Gauss point gp of
1642  // the receiver at time step tStep.
1643  // Order of components: 11, 22, 33, 23, 13, 12, 32, 31, 21 in the 3D.
1644 
1645  NLStructuralElement *nlStructEl = static_cast<NLStructuralElement*>( element );
1646 
1647  // Obtain the current displacement vector of the element and subtract initial displacements (if present)
1648  FloatArray u;
1649  nlStructEl->computeVectorOf(VM_Total, tStep, u); // solution vector
1650  if ( nlStructEl->initialDisplacements ) {
1651  u.subtract(* nlStructEl->initialDisplacements);
1652  }
1653 
1654  // Displacement gradient H = du/dX
1655  FloatMatrix B;
1656  nlStructEl->computeBHmatrixAt(gp, B);
1657  answer.beProductOf(B, u);
1658 
1659  // Deformation gradient F = H + I
1660  MaterialMode matMode = gp->giveMaterialMode();
1661  if ( matMode == _3dMat || matMode == _PlaneStrain ) {
1662  answer.at(1) += 1.0;
1663  answer.at(2) += 1.0;
1664  answer.at(3) += 1.0;
1665  } else if ( matMode == _PlaneStress ) {
1666  answer.at(1) += 1.0;
1667  answer.at(2) += 1.0;
1668  } else if ( matMode == _1dMat ) {
1669  answer.at(1) += 1.0;
1670  } else {
1671  OOFEM_ERROR("MaterialMode is not supported yet (%s)", __MaterialModeToString(matMode) );
1672  }
1673 }
1674 
1675 void XfemStructuralElementInterface :: giveIntersectionsTouchingCrack(std :: vector< int > &oTouchingEnrItemIndices, const std :: vector< int > &iCandidateIndices, int iEnrItemIndex, XfemManager &iXMan)
1676 {
1677  EnrichmentItem *ei = iXMan.giveEnrichmentItem(iEnrItemIndex);
1678 
1679 
1680  for ( int candidateIndex : iCandidateIndices ) {
1681  if ( candidateIndex != iEnrItemIndex ) {
1682  // Fetch candidate enrichment item
1683  EnrichmentItem *eiCandidate = iXMan.giveEnrichmentItem(candidateIndex);
1684 
1685  // This treatment is only necessary if the enrichment front
1686  // is an EnrFrontIntersection. Therefore, start by trying a
1687  // dynamic cast.
1688 
1689  // Check start tip
1690  EnrFrontIntersection *efStart = dynamic_cast< EnrFrontIntersection * >( eiCandidate->giveEnrichmentFrontStart() );
1691  if ( efStart != NULL ) {
1692  const TipInfo &tipInfo = efStart->giveTipInfo();
1693 
1694  if ( ei->tipIsTouchingEI(tipInfo) ) {
1695  //printf("Crack %d is touched by a tip on crack %d.\n", iEnrItemIndex, candidateIndex);
1696  oTouchingEnrItemIndices.push_back(candidateIndex);
1697  }
1698  }
1699 
1700  // Check end tip
1701  EnrFrontIntersection *efEnd = dynamic_cast< EnrFrontIntersection * >( eiCandidate->giveEnrichmentFrontEnd() );
1702  if ( efEnd != NULL ) {
1703  const TipInfo &tipInfo = efEnd->giveTipInfo();
1704 
1705  if ( ei->tipIsTouchingEI(tipInfo) ) {
1706  //printf("Crack %d is touched by a tip on crack %d.\n", iEnrItemIndex, candidateIndex);
1707  oTouchingEnrItemIndices.push_back(candidateIndex);
1708  }
1709  }
1710  }
1711  }
1712 }
1713 
1714 void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(std :: vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep)
1715 {
1716  const int numCells = mSubTri.size();
1717  vtkPieces [ 0 ].setNumberOfCells(numCells);
1718 
1719  int numTotalNodes = numCells * 3;
1720  vtkPieces [ 0 ].setNumberOfNodes(numTotalNodes);
1721 
1722  // Node coordinates
1723  std :: vector< FloatArray >nodeCoords;
1724  int nodesPassed = 1;
1725  for ( auto &tri: mSubTri ) {
1726  for ( int i = 1; i <= 3; i++ ) {
1727  FloatArray x = tri.giveVertex(i);
1728  nodeCoords.push_back(x);
1729  vtkPieces [ 0 ].setNodeCoords(nodesPassed, x);
1730  nodesPassed++;
1731  }
1732  }
1733 
1734  // Connectivity, offset and cell type
1735  nodesPassed = 1;
1736  int offset = 3;
1737  for ( size_t i = 1; i <= mSubTri.size(); i++ ) {
1738  IntArray nodes = {
1739  nodesPassed, nodesPassed + 1, nodesPassed + 2
1740  };
1741  nodesPassed += 3;
1742  vtkPieces [ 0 ].setConnectivity(i, nodes);
1743 
1744  vtkPieces [ 0 ].setOffset(i, offset);
1745  offset += 3;
1746 
1747  vtkPieces [ 0 ].setCellType(i, 5); // Linear triangle
1748  }
1749 
1750 
1751 
1752  // Export nodal variables from primary fields
1753  vtkPieces [ 0 ].setNumberOfPrimaryVarsToExport(primaryVarsToExport.giveSize(), numTotalNodes);
1754 
1755  for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) {
1756  UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum);
1757 
1758 
1759  nodesPassed = 1;
1760 
1761  for ( auto &tri: mSubTri ) {
1762  FloatArray triCenter = tri.giveVertex(1);
1763  triCenter.add( tri.giveVertex(2) );
1764  triCenter.add( tri.giveVertex(3) );
1765  triCenter.times(1.0 / 3.0);
1766 
1767  double meanEdgeLength = 0.0;
1768  meanEdgeLength += ( 1.0 / 3.0 ) * tri.giveVertex(1).distance( tri.giveVertex(2) );
1769  meanEdgeLength += ( 1.0 / 3.0 ) * tri.giveVertex(2).distance( tri.giveVertex(3) );
1770  meanEdgeLength += ( 1.0 / 3.0 ) * tri.giveVertex(3).distance( tri.giveVertex(1) );
1771 
1772  const double relPertLength = XfemTolerances :: giveRelLengthTolTight();
1773 
1774  for ( int i = 1; i <= 3; i++ ) {
1775  if ( type == DisplacementVector ) { // compute displacement
1776  FloatArray u = {
1777  0.0, 0.0, 0.0
1778  };
1779 
1780 
1781  // Fetch global coordinates (in undeformed configuration)
1782  const FloatArray &x = tri.giveVertex(i);
1783 
1784  FloatArray locCoordNode;
1785  element->computeLocalCoordinates(locCoordNode, x);
1786 
1787 
1788  FloatArray pertVec;
1789  FloatArray locCoord;
1790  double pertLength = relPertLength;
1791 
1792  int numTries = 1;
1793  for ( int j = 0; j < numTries; j++ ) {
1794  // Perturb towards triangle center, to ensure that
1795  // we end up on the correct side of the crack
1796  pertVec.beDifferenceOf(triCenter, x);
1797  pertVec.times(pertLength);
1798  FloatArray xPert = x;
1799  xPert.add(pertVec);
1800 
1801 
1802  // Compute local coordinates
1803  element->computeLocalCoordinates(locCoord, xPert);
1804  }
1805 
1806  // Compute displacement in point
1807  FloatMatrix NMatrix;
1808  FloatArray solVec;
1809 
1810  // Use only regular basis functions for edge nodes to get linear interpolation
1811  // (to make the visualization look nice)
1812  FloatArray N;
1814  interp->evalN( N, locCoordNode, FEIElementGeometryWrapper(element) );
1815 // interp->evalN( N, locCoord, FEIElementGeometryWrapper(element) );
1816  const int nDofMan = element->giveNumberOfDofManagers();
1817 
1819  int numEI = xMan->giveNumberOfEnrichmentItems();
1820 
1821  bool joinNodes = false;
1822 
1823  for ( int eiIndex = 1; eiIndex <= numEI; eiIndex++ ) {
1824  EnrichmentItem *ei = xMan->giveEnrichmentItem(eiIndex);
1825 
1826  double levelSetTang = 0.0, levelSetNormal = 0.0, levelSetInNode = 0.0;
1827 
1828  bool evaluationSucceeded = true;
1829  for ( int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++ ) {
1830  DofManager *dMan = element->giveDofManager(elNodeInd);
1831  const FloatArray &nodeCoord = * ( dMan->giveCoordinates() );
1832 
1833  if ( !ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), nodeCoord) ) {
1834  evaluationSucceeded = false;
1835  }
1836  levelSetTang += N.at(elNodeInd) * levelSetInNode;
1837 
1838  if ( !ei->evalLevelSetNormalInNode(levelSetInNode, dMan->giveGlobalNumber(), nodeCoord) ) {
1839  evaluationSucceeded = false;
1840  }
1841  levelSetNormal += N.at(elNodeInd) * levelSetInNode;
1842  }
1843 
1844  double tangSignDist = levelSetTang, arcPos = 0.0;
1845 
1846  GeometryBasedEI *geoEI = dynamic_cast< GeometryBasedEI * >( ei );
1847  if ( geoEI != NULL ) {
1848  // TODO: Consider removing this special treatment. /ES
1849  geoEI->giveGeometry()->computeTangentialSignDist(tangSignDist, x, arcPos);
1850  }
1851 
1852 
1853  if(!evaluationSucceeded) {
1854 // printf("!evaluationSucceeded.\n");
1855  }
1856 
1857 // if ( ( tangSignDist > ( 1.0e-3 ) * meanEdgeLength && fabs(levelSetNormal) < ( 1.0e-2 ) * meanEdgeLength ) && evaluationSucceeded ) {
1858 // joinNodes = false;
1859 // }
1860 
1861 // if ( ( tangSignDist < ( 1.0e-3 ) * meanEdgeLength || fabs(levelSetNormal) > ( 1.0e-2 ) * meanEdgeLength ) || !evaluationSucceeded ) {
1862  if ( ( tangSignDist < ( 1.0e-3 ) * meanEdgeLength || fabs(levelSetNormal) > ( 1.0e-2 ) * meanEdgeLength ) && false ) {
1863  joinNodes = false;
1864  }
1865  }
1866 
1867  if ( joinNodes ) {
1868  // if point on edge
1869  XfemElementInterface_createEnrNmatrixAt(NMatrix, locCoord, * element, true);
1870  element->computeVectorOf(VM_Total, tStep, solVec);
1871  } else {
1872  XfemElementInterface_createEnrNmatrixAt(NMatrix, locCoord, * element, false);
1873  element->computeVectorOf(VM_Total, tStep, solVec);
1874  }
1875 
1876 
1877  FloatArray uTemp;
1878  uTemp.beProductOf(NMatrix, solVec);
1879 
1880  if ( uTemp.giveSize() == 3 ) {
1881  u = uTemp;
1882  } else {
1883  u = {
1884  uTemp [ 0 ], uTemp [ 1 ], 0.0
1885  };
1886  }
1887 
1888 
1889  FloatArray valuearray = u;
1890  vtkPieces [ 0 ].setPrimaryVarInNode(fieldNum, nodesPassed, valuearray);
1891  } else {
1892  // TODO: Implement
1893  printf("fieldNum: %d\n", fieldNum);
1894  }
1895 
1896  nodesPassed++;
1897  }
1898  }
1899  }
1900 
1901 
1902  // Export nodal variables from internal fields
1903  vtkPieces [ 0 ].setNumberOfInternalVarsToExport(0, numTotalNodes);
1904 
1905 
1906  vtkPieces [ 0 ].setNumberOfCellVarsToExport(cellVarsToExport.giveSize(), numCells);
1907  for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) {
1908  InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i);
1909 
1910  for ( size_t triInd = 1; triInd <= mSubTri.size(); triInd++ ) {
1911 
1912  FloatArray average;
1914  computeIPAverageInTriangle(average, iRule, element, type, tStep, mSubTri[triInd-1]);
1915 
1916  if(average.giveSize() == 0) {
1917  VTKXMLExportModule :: computeIPAverage(average, iRule, element, type, tStep);
1918  }
1919 
1920 
1921  FloatArray averageVoigt;
1922 
1923  if( average.giveSize() == 6 ) {
1924 
1925  averageVoigt.resize(9);
1926 
1927  averageVoigt.at(1) = average.at(1);
1928  averageVoigt.at(5) = average.at(2);
1929  averageVoigt.at(9) = average.at(3);
1930  averageVoigt.at(6) = averageVoigt.at(8) = average.at(4);
1931  averageVoigt.at(3) = averageVoigt.at(7) = average.at(5);
1932  averageVoigt.at(2) = averageVoigt.at(4) = average.at(6);
1933  }
1934  else {
1935  if(average.giveSize() == 1) {
1936  averageVoigt.resize(1);
1937  averageVoigt.at(1) = average.at(1);
1938  }
1939  }
1940 
1941  vtkPieces [ 0 ].setCellVar(i, triInd, averageVoigt);
1942  }
1943  }
1944 
1945 
1946 
1947  // Export of XFEM related quantities
1948  if ( element->giveDomain()->hasXfemManager() ) {
1950 
1951  int nEnrIt = xMan->giveNumberOfEnrichmentItems();
1952  vtkPieces [ 0 ].setNumberOfInternalXFEMVarsToExport(xMan->vtkExportFields.giveSize(), nEnrIt, numTotalNodes);
1953 
1954  const int nDofMan = element->giveNumberOfDofManagers();
1955 
1956 
1957  for ( int field = 1; field <= xMan->vtkExportFields.giveSize(); field++ ) {
1958  XFEMStateType xfemstype = ( XFEMStateType ) xMan->vtkExportFields [ field - 1 ];
1959 
1960  for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) {
1961  EnrichmentItem *ei = xMan->giveEnrichmentItem(enrItIndex);
1962  for ( int nodeInd = 1; nodeInd <= numTotalNodes; nodeInd++ ) {
1963  const FloatArray &x = nodeCoords [ nodeInd - 1 ];
1964  FloatArray locCoord;
1965  element->computeLocalCoordinates(locCoord, x);
1966 
1967  FloatArray N;
1969  interp->evalN( N, locCoord, FEIElementGeometryWrapper(element) );
1970 
1971 
1972  if ( xfemstype == XFEMST_LevelSetPhi ) {
1973  double levelSet = 0.0, levelSetInNode = 0.0;
1974 
1975  for ( int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++ ) {
1976  DofManager *dMan = element->giveDofManager(elNodeInd);
1977  const FloatArray &nodeCoord = * ( dMan->giveCoordinates() );
1978  ei->evalLevelSetNormalInNode(levelSetInNode, dMan->giveGlobalNumber(), nodeCoord);
1979 
1980  levelSet += N.at(elNodeInd) * levelSetInNode;
1981  }
1982 
1983 
1984  FloatArray valueArray = {
1985  levelSet
1986  };
1987  vtkPieces [ 0 ].setInternalXFEMVarInNode(field, enrItIndex, nodeInd, valueArray);
1988  } else if ( xfemstype == XFEMST_LevelSetGamma ) {
1989  double levelSet = 0.0, levelSetInNode = 0.0;
1990 
1991  for ( int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++ ) {
1992  DofManager *dMan = element->giveDofManager(elNodeInd);
1993  const FloatArray &nodeCoord = * ( dMan->giveCoordinates() );
1994  ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), nodeCoord);
1995 
1996  levelSet += N.at(elNodeInd) * levelSetInNode;
1997  }
1998 
1999 
2000  FloatArray valueArray = {
2001  levelSet
2002  };
2003  vtkPieces [ 0 ].setInternalXFEMVarInNode(field, enrItIndex, nodeInd, valueArray);
2004  } else if ( xfemstype == XFEMST_NodeEnrMarker ) {
2005  double nodeEnrMarker = 0.0, nodeEnrMarkerInNode = 0.0;
2006 
2007  for ( int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++ ) {
2008  DofManager *dMan = element->giveDofManager(elNodeInd);
2009  ei->evalNodeEnrMarkerInNode( nodeEnrMarkerInNode, dMan->giveGlobalNumber() );
2010 
2011  nodeEnrMarker += N.at(elNodeInd) * nodeEnrMarkerInNode;
2012  }
2013 
2014 
2015 
2016  FloatArray valueArray = {
2017  nodeEnrMarker
2018  };
2019  vtkPieces [ 0 ].setInternalXFEMVarInNode(field, enrItIndex, nodeInd, valueArray);
2020  }
2021  }
2022  }
2023  }
2024  }
2025 }
2026 
2028 {
2029  // Computes the volume average (over an element) for the quantity defined by isType
2030  double gptot = 0.0;
2031  answer.clear();
2032  FloatArray temp;
2033  if ( iRule ) {
2034  for ( IntegrationPoint *ip: *iRule ) {
2035 
2036  FloatArray globCoord = ip->giveGlobalCoordinates();
2037 // globCoord.resizeWithValues(2);
2038 
2039  if( iTri.pointIsInTriangle(globCoord) ) {
2040  elem->giveIPValue(temp, ip, isType, tStep);
2041  gptot += ip->giveWeight();
2042  answer.add(ip->giveWeight(), temp);
2043  }
2044  }
2045 
2046  answer.times(1. / gptot);
2047  }
2048 
2049 }
2050 
2051 } /* namespace oofem */
CrossSection * giveCrossSection()
Definition: element.C:495
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...
virtual void giveStiffnessMatrix_PlaneStrain(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)=0
static double giveRelLengthTolTight()
InternalStateType
Type representing the physical meaning of element or constitutive model internal variable.
void setField(int item, InputFieldType id)
virtual bool isActivated(TimeStep *tStep)
Definition: element.C:793
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition: gausspoint.h:191
void subtract(const FloatArray &src)
Subtracts array src to receiver.
Definition: floatarray.C:258
std::vector< std::unique_ptr< IntegrationRule > > & giveIntegrationRulesArray()
Definition: element.h:837
const std::vector< int > & giveMaterialModifyingEnrItemIndices() const
Definition: xfemmanager.h:251
virtual void computeCohesiveTangentAt(FloatMatrix &answer, TimeStep *tStep)
Abstract class representing entity, which is included in the FE model using one (or more) global func...
virtual void XfemElementInterface_computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep)
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Returns the integration point corresponding value in full form.
Definition: element.C:1257
virtual MaterialStatus * giveStatus(GaussPoint *gp) const
Returns material status of receiver in given integration point.
Definition: material.C:244
bool evalNodeEnrMarkerInNode(double &oNodeEnrMarker, int iNodeInd) const
virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0
Evaluates the array of interpolation functions (shape functions) at given point.
virtual void giveRealStress_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep)=0
int giveNumGpPerTri() const
Definition: xfemmanager.h:178
void giveSubtriangulationCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep)
VTK Interface.
void beVectorProductOf(const FloatArray &v1, const FloatArray &v2)
Computes vector product (or cross product) of vectors given as parameters, , and stores the result in...
Definition: floatarray.C:415
EnrichmentFront * giveEnrichmentFrontStart()
Class and object Domain.
Definition: domain.h:115
virtual void give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep)
void giveSubPolygon(std::vector< FloatArray > &oPoints, const double &iXiStart, const double &iXiEnd) const
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Returns local vector of unknowns.
Definition: element.C:86
virtual void copyStateVariables(const MaterialStatus &iStatus)=0
static void refineTriangle(std::vector< Triangle > &oRefinedTri, const Triangle &iTri)
Split a triangle in four.
Definition: geometry.C:634
virtual int computeNumberOfDofs()
Computes or simply returns total number of element&#39;s local DOFs.
Definition: element.h:424
virtual IntegrationRule * giveIntegrationRule(int i)
Definition: element.h:835
int giveGlobalNumber() const
Definition: dofmanager.h:501
virtual void XfemElementInterface_computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity=NULL)
int giveNumTriRefs() const
Number of Gauss points per sub-triangle in cut elements.
Definition: xfemmanager.h:179
Abstract base class for "structural" finite elements with geometrical nonlinearities.
virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep)
Default implementation relies on giveRealStressVector for second Piola-Kirchoff stress.
virtual void createMaterialStatus(GaussPoint &iGP)=0
Provides Xfem interface for an element.
bool isEmpty() const
Checks if receiver is empty (i.e., zero sized).
Definition: intarray.h:208
std::unique_ptr< FloatArray > initialDisplacements
Initial displacement vector, describes the initial nodal displacements when element has been casted...
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
int giveGlobalNumber() const
Definition: element.h:1059
void setIntegrationRules(std::vector< std::unique_ptr< IntegrationRule > > irlist)
Sets integration rules.
Definition: element.C:562
TipInfo gathers useful information about a crack tip, like its position and tangent direction...
Definition: tipinfo.h:24
void clear()
Clears receiver (zero size).
Definition: floatarray.h:206
void giveElementEnrichmentItemIndices(std::vector< int > &oElemEnrInd, int iElementIndex) const
Definition: xfemmanager.C:583
virtual void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const =0
virtual FloatArray * giveCoordinates()
Definition: dofmanager.h:382
EngngModel * giveEngngModel()
Returns engineering model to which receiver is associated.
Definition: domain.C:433
std::vector< std::unique_ptr< IntegrationRule > > mIntRule_tmp
double giveTargetTime()
Returns target time.
Definition: timestep.h:146
Abstract base class for all finite elements.
Definition: element.h:145
Base class for dof managers.
Definition: dofmanager.h:113
virtual MaterialMode giveMaterialMode()
Returns material mode for receiver integration points.
Definition: element.h:691
MaterialMode
Type representing material mode of integration point.
Definition: materialmode.h:89
XfemStructureManager: XFEM manager with extra functionality specific for the sm module.
void giveIntersectionsTouchingCrack(std::vector< int > &oTouchingEnrItemIndices, const std::vector< int > &iCandidateIndices, int iEnrItemIndex, XfemManager &iXMan)
Identify enrichment items with an intersection enrichment front that touches a given enrichment item...
std::vector< std::unique_ptr< IntegrationRule > > mpCZIntegrationRules_tmp
virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer)
Computes interpolation matrix for element unknowns.
void AppendCohesiveZoneGaussPoint(GaussPoint *ipGP)
Definition: crack.C:59
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
MatResponseMode
Describes the character of characteristic material matrix.
virtual void giveCZInputRecord(DynamicInputRecord &input)
#define _IFT_XfemElementInterface_PlaneStrain
XfemManager * giveXfemManager()
Definition: domain.C:375
virtual int giveNumberOfDofManagers() const
Definition: element.h:656
static void WriteTrianglesToVTK(const std::string &iName, const std::vector< Triangle > &iTriangles)
virtual IRResultType initializeCZFrom(InputRecord *ir)
virtual FEInterpolation * giveInterpolation() const
Definition: element.h:629
Abstract base class representing integration rule.
static void WritePointsToVTK(const std::string &iName, const std::vector< FloatArray > &iPoints)
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Sets receiver to be a - b.
Definition: floatarray.C:341
virtual void computeCohesiveTangent(FloatMatrix &answer, TimeStep *tStep)
Base abstract class representing cross section in finite element mesh.
Definition: crosssection.h:107
bool giveVtkDebug() const
Definition: xfemmanager.h:243
Class representing a general abstraction for finite element interpolation class.
Definition: feinterpol.h:132
PrescribedGradientHomogenization * giveBC()
int giveNumberOfEnrichmentItems() const
Definition: xfemmanager.h:185
const char * __MaterialModeToString(MaterialMode _value)
Definition: cltypes.C:314
#define max
Abstract base class for all "structural" finite elements.
void computeIPAverageInTriangle(FloatArray &answer, IntegrationRule *iRule, Element *elem, InternalStateType isType, TimeStep *tStep, const Triangle &iTri)
Help functions for VTK export.
virtual double computeVolumeAround(GaussPoint *gp)
Returns volume related to given integration point.
Definition: element.h:518
Crack.
Definition: crack.h:54
double computeEffectiveSveSize(StructuralFE2MaterialStatus *iFe2Ms)
virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const FloatMatrix &F, TimeStep *tStep)
Material * giveMaterial(int n)
Service for accessing particular domain material model.
Definition: domain.C:281
#define M_PI
Definition: mathfem.h:52
bool pointIsInTriangle(const FloatArray &iP) const
Checks if the projection of the the point iP onto the triangle plane is inside the triangle...
Definition: geometry.C:491
#define OOFEM_ERROR(...)
Definition: error.h:61
double computeSquaredNorm() const
Computes the square of the norm.
Definition: floatarray.C:846
const FloatArray & giveNormal() const
virtual double giveWeight()
Returns integration weight of receiver.
Definition: gausspoint.h:181
virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
Computes full 3d material stiffness matrix at given integration point, time, respecting load history ...
UnknownType
Type representing particular unknown (its physical meaning).
Definition: unknowntype.h:55
virtual void giveRealStress_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep)=0
StructuralCrossSection * giveStructuralCrossSection()
Helper function which returns the structural cross-section for the element.
void times(double f)
Multiplies receiver by factor f.
Definition: floatmatrix.C:1594
bool evalLevelSetNormalInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
void XfemElementInterface_createEnrNmatrixAt(FloatMatrix &oAnswer, const FloatArray &iLocCoord, Element &iEl, bool iSetDiscontContribToZero)
Creates enriched N-matrix.
Wrapper around element definition to provide FEICellGeometry interface.
Definition: feinterpol.h:95
#define _IFT_XfemElementInterface_NumIntPointsCZ
virtual void giveStiffnessMatrix_PlaneStress(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)=0
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Receiver becomes the result of the product of aMatrix and anArray.
Definition: floatarray.C:676
This class implements a structural interface material status information.
#define N(p, q)
Definition: mdm.C:367
void plusProductSymmUpper(const FloatMatrix &a, const FloatMatrix &b, double dV)
Adds to the receiver the product .
Definition: floatmatrix.C:698
void beTProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Receiver becomes the result of the product of aMatrix^T and anArray.
Definition: floatarray.C:708
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
double distance_square(const FloatArray &iP1, const FloatArray &iP2, double &oXi, double &oXiUnbounded) const
Definition: floatarray.C:499
Imposes a prescribed gradient weakly on the boundary with an independent traction discretization...
std::vector< std::vector< int > > mCZTouchingEnrItemIndices
Indices of enrichment items that give cohesive zone contributions to a given GP, even though the GP i...
const FloatArray & giveGlobalCoordinates()
Definition: gausspoint.h:160
std::vector< std::unique_ptr< IntegrationRule > > mpCZIntegrationRules
virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep)
Default implementation relies on giveRealStressVector for second Piola-Kirchoff stress.
void ComputeBOrBHMatrix(FloatMatrix &oAnswer, GaussPoint &iGP, Element &iEl, bool iComputeBH, const FloatArray &iNaturalGpCoord)
Help function for computation of B and BH.
Abstract base class representing a material status information.
Definition: matstatus.h:84
std::vector< std::unique_ptr< IntegrationRule > > mpCZExtraIntegrationRules
bool hasXfemManager()
Definition: domain.C:386
bool evalLevelSetTangInNode(double &oLevelSet, int iNodeInd, const FloatArray &iGlobalCoord) const
Class representing vector of real numbers.
Definition: floatarray.h:82
std::vector< int > mCZEnrItemIndices
Index of enrichment items associated with cohesive zones.
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
This class manages the xfem part.
Definition: xfemmanager.h:109
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
virtual double give(CrossSectionProperty a, GaussPoint *gp)
Returns the value of cross section property at given point.
Definition: crosssection.C:151
static void computeIPAverage(FloatArray &answer, IntegrationRule *iRule, Element *elem, InternalStateType isType, TimeStep *tStep)
Computes a cell average of an InternalStateType varible based on the weights in the integrationpoints...
#define _IFT_XfemElementInterface_CohesiveZoneMaterial
IntArray vtkExportFields
List with the fields that should be exported to VTK.
Definition: xfemmanager.h:167
IntegrationPointStatus * giveMaterialStatus()
Returns reference to associated material status (NULL if not defined).
Definition: gausspoint.h:205
MaterialStatus * giveClosestGP_MatStat(double &oClosestDist, std::vector< std::unique_ptr< IntegrationRule > > &iRules, const FloatArray &iCoord)
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
Class representing the general Input Record.
Definition: inputrecord.h:101
bool isElementEnriched(const Element *elem)
Definition: xfemmanager.C:104
void add(const FloatMatrix &a)
Adds matrix to the receiver.
Definition: floatmatrix.C:1023
BasicGeometry * giveGeometry()
XFEMStateType
Definition: xfemmanager.h:92
bool mUsePlaneStrain
Flag that tells if plane stress or plane strain is assumed.
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:367
void setColumn(const FloatArray &src, int c)
Sets the values of the matrix in specified column.
Definition: floatmatrix.C:648
Class representing the a dynamic Input Record.
void times(double s)
Multiplies receiver with scalar.
Definition: floatarray.C:818
void beTranspositionOf(const FloatMatrix &src)
Assigns to the receiver the transposition of parameter.
Definition: floatmatrix.C:323
EnrichmentItem * giveEnrichmentItem(int n)
Definition: xfemmanager.h:184
virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords)
Computes the element local coordinates from given global coordinates.
Definition: element.C:1222
bool tipIsTouchingEI(const TipInfo &iTipInfo)
Abstract base class for all "structural" constitutive models.
virtual void XfemElementInterface_partitionElement(std::vector< Triangle > &oTriangles, const std::vector< FloatArray > &iPoints)
Partitions the element into patches by a triangulation.
virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
Computes full 3d material stiffness matrix at given integration point, time, respecting load history ...
int giveElementPlaceInArray(int iGlobalElNum) const
Returns the array index of the element with global number iGlobalElNum, so that it can be fetched by ...
Definition: domain.C:183
virtual bool XfemElementInterface_updateIntegrationRule()
Updates integration rule based on the triangulation.
void beProductTOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:397
void zero()
Zeroes all coefficient of receiver.
Definition: floatmatrix.C:1326
Domain * giveDomain() const
Definition: femcmpnn.h:100
virtual void computeGlobalCohesiveTractionVector(FloatArray &oT, const FloatArray &iJump, const FloatArray &iCrackNormal, const FloatMatrix &iNMatrix, GaussPoint &iGP, TimeStep *tStep)
Multiscale constitutive model for subscale structural problems.
virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer)
Computes a matrix which, multiplied by the column matrix of nodal displacements, gives the displaceme...
const TipInfo & giveTipInfo() const
void push_back(const double &iVal)
Add one element.
Definition: floatarray.h:118
void beUnitMatrix()
Sets receiver to unity matrix.
Definition: floatmatrix.C:1332
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
virtual bool isMaterialModified(GaussPoint &iGP, Element &iEl, CrossSection *&opCS) const
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:337
virtual TimeStep * giveCurrentStep(bool force=false)
Returns current time step.
Definition: engngm.h:683
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
Abstract base class for all structural cross section models.
void computeNCohesive(FloatMatrix &oN, GaussPoint &iGP, int iEnrItemIndex, const std::vector< int > &iTouchingEnrItemIndices)
Compute N-matrix for cohesive zone.
Abstract base class for all "structural" interface models.
the oofem namespace is to define a context or scope in which all oofem names are defined.
DofManager * giveDofManager(int i) const
Definition: element.C:514
virtual void computeCohesiveForces(FloatArray &answer, TimeStep *tStep)
Domain * giveDomain()
Definition: xfemmanager.h:202
double normalize()
Normalizes receiver.
Definition: floatarray.C:828
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: floatmatrix.h:156
void symmetrized()
Initializes the lower half of the receiver according to the upper half.
Definition: floatmatrix.C:1576
virtual bool hasAnalyticalTangentStiffness() const =0
Tells if the model has implemented analytical tangent stiffness.
void computeDisplacementJump(GaussPoint &iGP, FloatArray &oJump, const FloatArray &iSolVec, const FloatMatrix &iNMatrix)
const FloatArray & giveNormal() const
Returns const reference to normal vector.
Class representing integration point in finite element program.
Definition: gausspoint.h:93
Class representing solution step.
Definition: timestep.h:80
void letNormalBe(FloatArray iN)
Assigns normal vector.
virtual void XfemElementInterface_computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *, TimeStep *tStep)
EnrichmentFront * giveEnrichmentFrontEnd()
void add(const FloatArray &src)
Adds array src to receiver.
Definition: floatarray.C:156
EnrichmentItem with geometry described by BasicGeometry.
PatchIntegrationRule provides integration over a triangle patch.
void setPeriodicityNormal(const FloatArray &iPeriodicityNormal)
virtual void giveMassMtrxIntegrationgMask(IntArray &answer)
Returns mask indicating, which unknowns (their type and ordering is the same as element unknown vecto...
std::vector< std::unique_ptr< IntegrationRule > > mpCZExtraIntegrationRules_tmp
Class representing Gaussian-quadrature integration rule.
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631
virtual Material * giveMaterial(IntegrationPoint *ip)=0
Returns the material associated with the GP.
virtual void XfemElementInterface_computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep)
virtual MaterialStatus * CreateStatus(GaussPoint *gp) const
Creates new copy of associated status and inserts it into given integration point.
Definition: material.h:316

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:32 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011