2 nCoupledFacesToBreak = 0;
4 // Check internal faces
6 // scalarField effTraction =
7 // cohesiveZone.internalField() *
8 // mag(traction.internalField());
9 scalarField normalTraction =
10 cohesiveZone.internalField()*
11 ( n.internalField() & traction.internalField() );
13 // only consider tensile tractions
14 normalTraction = max(normalTraction, scalar(0));
15 scalarField shearTraction =
16 cohesiveZone.internalField()*
17 mag( (I - Foam::sqr(n.internalField())) & traction.internalField() );
19 // the traction fraction is monitored to decide which faces to break:
20 // ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face
22 const surfaceScalarField sigmaMax = rheology.cohLaw().sigmaMax();
23 const surfaceScalarField tauMax = rheology.cohLaw().tauMax();
25 const scalarField& sigmaMaxI = sigmaMax.internalField();
26 const scalarField& tauMaxI = tauMax.internalField();
28 //scalarField effTractionFraction = effTraction/sigmaMax;
29 scalarField effTractionFraction(normalTraction.size(), 0.0);
34 (normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI)
35 + (shearTraction/tauMaxI)*(shearTraction/tauMaxI);
39 // solidCohesiveFixedModeMix only uses sigmaMax
41 (normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI)
42 + (shearTraction/sigmaMaxI)*(shearTraction/sigmaMaxI);
45 maxEffTractionFraction = gMax(effTractionFraction);
47 SLList<label> facesToBreakList;
48 SLList<scalar> facesToBreakEffTractionFractionList;
50 forAll(effTractionFraction, faceI)
52 if (effTractionFraction[faceI] > 1.0)
54 facesToBreakList.insert(faceI);
55 facesToBreakEffTractionFractionList.insert
57 effTractionFraction[faceI]
62 labelList facesToBreak(facesToBreakList);
63 List<scalar> facesToBreakEffTractionFraction
65 facesToBreakEffTractionFractionList
68 nFacesToBreak = facesToBreak.size();
70 // Break only one face per topo change
71 if (nFacesToBreak > 1)
76 // philipc - select face with maximum effective traction fraction
77 label faceToBreakIndex = -1;
78 scalar faceToBreakEffTractionFraction = 0;
79 forAll(facesToBreakEffTractionFraction, faceI)
83 facesToBreakEffTractionFraction[faceI]
84 > faceToBreakEffTractionFraction
87 faceToBreakEffTractionFraction =
88 facesToBreakEffTractionFraction[faceI];
89 faceToBreakIndex = facesToBreak[faceI];
93 scalar gMaxEffTractionFraction =
94 returnReduce(faceToBreakEffTractionFraction, maxOp<scalar>());
96 if (Pstream::parRun())
98 bool procHasFaceToBreak = false;
99 if (nFacesToBreak > 0)
103 mag(gMaxEffTractionFraction - faceToBreakEffTractionFraction)
107 // philipc - Maximum traction fraction is on this processor
108 procHasFaceToBreak = true;
112 // Check if maximum is present on more then one processors
113 label procID = Pstream::nProcs();
114 if (procHasFaceToBreak)
116 procID = Pstream::myProcNo();
120 returnReduce<label>(procID, minOp<label>());
122 if (procID != minProcID)
129 // Check coupled (processor) patches
131 SLList<label> coupledFacesToBreakList;
132 SLList<scalar> coupledFacesToBreakEffTractionFractionList;
133 forAll(mesh.boundary(), patchI)
135 if (mesh.boundary()[patchI].coupled())
137 // scalarField pEffTraction =
138 // cohesiveZone.boundaryField()[patchI]*
139 // mag(traction.boundaryField()[patchI]);
140 // scalarField pEffTractionFraction = pEffTraction/sigmaMax.boundaryField()[patchI];
142 scalarField pNormalTraction =
143 cohesiveZone.boundaryField()[patchI]*
144 ( n.boundaryField()[patchI] & traction.boundaryField()[patchI] );
146 // only consider tensile tractions
147 pNormalTraction = max(pNormalTraction, scalar(0));
149 scalarField pShearTraction =
150 cohesiveZone.boundaryField()[patchI]*
151 mag( (I - Foam::sqr(n.boundaryField()[patchI])) & traction.boundaryField()[patchI] );
153 // the traction fraction is monitored to decide which faces to break:
154 // ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face
155 const scalarField& pSigmaMax = sigmaMax.boundaryField()[patchI];
156 const scalarField& pTauMax = tauMax.boundaryField()[patchI];
158 scalarField pEffTractionFraction(pNormalTraction.size(), 0.0);
159 if(cohesivePatchUPtr)
161 pEffTractionFraction =
162 (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
163 + (pShearTraction/pTauMax)*(pShearTraction/pTauMax);
167 // solidCohesiveFixedModeMix only uses sigmaMax
168 pEffTractionFraction =
169 (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
170 + (pShearTraction/pSigmaMax)*(pShearTraction/pSigmaMax);
173 label start = mesh.boundaryMesh()[patchI].start();
175 forAll(pEffTractionFraction, faceI)
177 if (pEffTractionFraction[faceI] > maxEffTractionFraction)
179 maxEffTractionFraction = pEffTractionFraction[faceI];
182 if (pEffTractionFraction[faceI] > 1.0)
184 coupledFacesToBreakList.insert(start + faceI);
185 coupledFacesToBreakEffTractionFractionList.insert
187 pEffTractionFraction[faceI]
194 labelList coupledFacesToBreak(coupledFacesToBreakList);
195 List<scalar> coupledFacesToBreakEffTractionFraction
197 coupledFacesToBreakEffTractionFractionList
200 nCoupledFacesToBreak = coupledFacesToBreak.size();
202 // Break only one face per topo change
203 if (nCoupledFacesToBreak > 1)
205 nCoupledFacesToBreak = 1;
208 // Select coupled face with maximum effective traction fraction
209 label coupledFaceToBreakIndex = -1;
210 scalar coupledFaceToBreakEffTractionFraction = 0;
211 forAll(coupledFacesToBreakEffTractionFraction, faceI)
215 coupledFacesToBreakEffTractionFraction[faceI]
216 > coupledFaceToBreakEffTractionFraction
219 coupledFaceToBreakEffTractionFraction =
220 coupledFacesToBreakEffTractionFraction[faceI];
221 coupledFaceToBreakIndex = coupledFacesToBreak[faceI];
225 scalar gMaxCoupledEffTractionFraction =
226 returnReduce(coupledFaceToBreakEffTractionFraction, maxOp<scalar>());
228 if (Pstream::parRun())
231 bool procHasCoupledFaceToBreak = false;
232 if (nCoupledFacesToBreak > 0)
236 mag(gMaxCoupledEffTractionFraction - coupledFaceToBreakEffTractionFraction)
240 // Maximum traction fraction is on this processor
241 procHasCoupledFaceToBreak = true;
245 // Check if maximum is present on more then one processors
246 label procID = Pstream::nProcs();
247 if (procHasCoupledFaceToBreak)
249 procID = Pstream::myProcNo();
253 returnReduce<label>(procID, minOp<label>());
255 if (procID != minProcID)
257 nCoupledFacesToBreak = 0;
261 if (gMaxCoupledEffTractionFraction > gMaxEffTractionFraction)
263 // Break coupled face
268 // Break internal face
269 nCoupledFacesToBreak = 0;
272 // Make sure that coupled faces are broken in pairs
273 labelList ngbProc(Pstream::nProcs(), -1);
274 labelList index(Pstream::nProcs(), -1);
275 if (nCoupledFacesToBreak)
278 mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex);
280 label start = mesh.boundaryMesh()[patchID].start();
281 label localIndex = coupledFaceToBreakIndex - start;
283 const processorPolyPatch& procPatch =
284 refCast<const processorPolyPatch>(mesh.boundaryMesh()[patchID]);
285 label ngbProcNo = procPatch.neighbProcNo();
287 ngbProc[Pstream::myProcNo()] = ngbProcNo;
288 index[Pstream::myProcNo()] = localIndex;
291 if (returnReduce(nCoupledFacesToBreak, maxOp<label>()))
293 reduce(ngbProc, maxOp<labelList>());
294 reduce(index, maxOp<labelList>());
296 for (label procI = 0; procI < Pstream::nProcs(); procI++)
298 if (procI != Pstream::myProcNo())
300 if (ngbProc[procI] == Pstream::myProcNo())
302 forAll(mesh.boundaryMesh(), patchI)
306 mesh.boundaryMesh()[patchI].type()
307 == processorPolyPatch::typeName
310 const processorPolyPatch& procPatch =
311 refCast<const processorPolyPatch>
313 mesh.boundaryMesh()[patchI]
315 label ngbProcNo = procPatch.neighbProcNo();
317 if (ngbProcNo == procI)
320 mesh.boundaryMesh()[patchI].start();
321 coupledFaceToBreakIndex = start + index[procI];
322 nCoupledFacesToBreak = 1;
332 vector faceToBreakTraction = vector::zero;
333 vector faceToBreakNormal = vector::zero;
334 scalar faceToBreakSigmaMax = 0.0;
335 scalar faceToBreakTauMax = 0.0;
337 // Set faces to break
338 if (nFacesToBreak > 0)
340 faceToBreakTraction = traction.internalField()[faceToBreakIndex];
341 faceToBreakNormal = n.internalField()[faceToBreakIndex];
343 // Scale broken face traction
344 faceToBreakSigmaMax = sigmaMaxI[faceToBreakIndex];
345 faceToBreakTauMax = tauMaxI[faceToBreakIndex];
346 scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
347 normalTrac = max(normalTrac, 0.0);
348 scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
349 scalar scaleFactor = 1;
350 if(cohesivePatchUPtr)
357 (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
358 + (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
364 // solidCohesiveFixedModeMix only uses sigmaMax
370 (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
371 + (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
376 faceToBreakTraction *= scaleFactor;
380 else if (nCoupledFacesToBreak > 0)
383 mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex);
384 label start = mesh.boundaryMesh()[patchID].start();
385 label localIndex = coupledFaceToBreakIndex - start;
387 faceToBreakTraction = traction.boundaryField()[patchID][localIndex];
388 faceToBreakNormal = n.boundaryField()[patchID][localIndex];
390 // Scale broken face traction
391 faceToBreakSigmaMax = sigmaMax.boundaryField()[patchID][localIndex];
392 faceToBreakTauMax = tauMax.boundaryField()[patchID][localIndex];
393 scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
394 normalTrac = max(normalTrac, 0.0);
395 scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
396 scalar scaleFactor = 1;
397 if(cohesivePatchUPtr)
404 (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
405 + (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
411 // solidCohesiveFixedModeMix only uses sigmaMax
417 (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
418 + (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
423 faceToBreakTraction *= scaleFactor;
428 reduce(topoChange, orOp<bool>());
430 labelList faceToBreak(nFacesToBreak, faceToBreakIndex);
431 boolList faceToBreakFlip(nFacesToBreak, false);
432 labelList coupledFaceToBreak
434 nCoupledFacesToBreak,
435 coupledFaceToBreakIndex
438 reduce(nFacesToBreak, maxOp<label>());
439 reduce(nCoupledFacesToBreak, maxOp<label>());
441 if (nFacesToBreak || nCoupledFacesToBreak)
443 Pout << "Internal face to break: " << faceToBreak << endl;
444 Pout << "Coupled face to break: " << coupledFaceToBreak << endl;
446 mesh.setBreak(faceToBreak, faceToBreakFlip, coupledFaceToBreak);
449 const labelList& faceMap = mesh.topoChangeMap().faceMap();
450 label start = mesh.boundaryMesh()[cohesivePatchID].start();
453 lambda = rheology.lambda();
454 muf = fvc::interpolate(mu);
455 lambdaf = fvc::interpolate(lambda);
457 // we need to modify propertiess after cracking otherwise momentum equation is wrong
458 // but solidInterface seems to hold some information about old mesh
459 // so we will delete it and make another
460 // we could probably add a public clearout function
461 // create new solidInterface
462 //Pout << "Creating new solidInterface" << endl;
463 //delete solidInterfacePtr;
464 //solidInterfacePtr = new solidInterface(mesh, rheology);
465 // delete demand driven data as the mesh has changed
466 if(rheology.solidInterfaceActive())
468 rheology.solInterface().clearOut();
469 solidInterfacePtr->modifyProperties(muf, lambdaf);
472 // Local crack displacement
474 U.boundaryField()[cohesivePatchID].patchInternalField();
476 U.oldTime().boundaryField()[cohesivePatchID].patchInternalField();
478 // Global crack displacement
479 vectorField globalUpI = mesh.globalCrackField(UpI);
480 vectorField globalOldUpI = mesh.globalCrackField(oldUpI);
482 // mu and lambda field on new crack faces must be updated
483 scalarField muPI = mu.boundaryField()[cohesivePatchID].patchInternalField();
484 scalarField lambdaPI = lambda.boundaryField()[cohesivePatchID].patchInternalField();
485 scalarField globalMuPI = mesh.globalCrackField(muPI);
486 scalarField globalLambdaPI = mesh.globalCrackField(lambdaPI);
488 // cohesivePatchU.size()
489 int cohesivePatchSize(cohesivePatchUPtr ? cohesivePatchUPtr->size() : cohesivePatchUFixedModePtr->size());
491 // Initialise U for new cohesive face
492 const labelList& gcfa = mesh.globalCrackFaceAddressing();
493 label globalIndex = mesh.localCrackStart();
494 // for (label i=0; i<cohesivePatchU.size(); i++)
495 for (label i=0; i<cohesivePatchSize; i++)
497 label oldFaceIndex = faceMap[start+i];
500 if (oldFaceIndex == faceToBreakIndex)
502 U.boundaryField()[cohesivePatchID][i] =
505 globalUpI[globalIndex]
506 + globalUpI[gcfa[globalIndex]]
508 U.oldTime().boundaryField()[cohesivePatchID][i] =
511 globalOldUpI[globalIndex]
512 + globalOldUpI[gcfa[globalIndex]]
515 // initialise mu and lambda on new faces
516 // set new face value to value of internal cell
517 muf.boundaryField()[cohesivePatchID][i] = globalMuPI[globalIndex];
518 lambdaf.boundaryField()[cohesivePatchID][i] = globalLambdaPI[globalIndex];
528 // we must calculate grad using interface
529 // U at the interface has not been calculated yet as interface.correct()
530 // has not been called yet
531 // not really a problem as gradU is correct in second outer iteration
532 // as long as this does not cause convergence problems for the first iterations.
533 // we should be able to calculate the interface displacements without
534 // having to call interface.correct()
535 // todo: add calculateInterfaceU() function
536 // interface grad uses Gauss, we need least squares
537 //gradU = solidInterfacePtr->grad(U);
538 gradU = fvc::grad(U); // leastSquaresSolidInterface grad scheme
539 //snGradU = fvc::snGrad(U);
541 # include "calculateTraction.H"
542 //if (nFacesToBreak || nCoupledFacesToBreak) mesh.write(); traction.write();
544 // Initialise initiation traction for new cohesive patch face
545 // for (label i=0; i<cohesivePatchU.size(); i++)
546 for (label i=0; i<cohesivePatchSize; i++)
548 label oldFaceIndex = faceMap[start+i];
553 (oldFaceIndex == faceToBreakIndex)
554 || (oldFaceIndex == coupledFaceToBreakIndex)
558 mesh.Sf().boundaryField()[cohesivePatchID][i]
559 /mesh.magSf().boundaryField()[cohesivePatchID][i];
562 if ((n0 & faceToBreakNormal) > SMALL)
564 traction.boundaryField()[cohesivePatchID][i] =
567 traction.oldTime().boundaryField()[cohesivePatchID][i] =
570 if(cohesivePatchUPtr)
572 cohesivePatchUPtr->traction()[i] = faceToBreakTraction;
576 cohesivePatchUFixedModePtr->traction()[i] = faceToBreakTraction;
577 cohesivePatchUFixedModePtr->initiationTraction()[i] = faceToBreakTraction;
582 traction.boundaryField()[cohesivePatchID][i] =
583 -faceToBreakTraction;
584 traction.oldTime().boundaryField()[cohesivePatchID][i] =
585 -faceToBreakTraction;
587 //cohesivePatchU.traction()[i] = -faceToBreakTraction;
588 if(cohesivePatchUPtr)
590 cohesivePatchUPtr->traction()[i] = -faceToBreakTraction;
594 cohesivePatchUFixedModePtr->traction()[i] =
595 -faceToBreakTraction;
596 cohesivePatchUFixedModePtr->initiationTraction()[i] =
597 -faceToBreakTraction;
603 // hmmnn we only need a reference for very small groups of cells
605 //# include "updateReference.H"