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() );
12 normalTraction = max(normalTraction, 0.0); // only consider tensile tractions
13 scalarField shearTraction =
14 cohesiveZone.internalField() *
15 mag( (I - Foam::sqr(n.internalField())) & traction.internalField() );
17 // the traction fraction is monitored to decide which faces to break:
18 // ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face
20 const surfaceScalarField sigmaMax = rheology.cohLaw().sigmaMax();
21 const surfaceScalarField tauMax = rheology.cohLaw().tauMax();
23 const scalarField& sigmaMaxI = sigmaMax.internalField();
24 const scalarField& tauMaxI = tauMax.internalField();
26 //scalarField effTractionFraction = effTraction/sigmaMax;
27 scalarField effTractionFraction(normalTraction.size(), 0.0);
32 (normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI) + (shearTraction/tauMaxI)*(shearTraction/tauMaxI);
36 // solidCohesiveFixedModeMix only uses sigmaMax
38 (normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI) + (shearTraction/sigmaMaxI)*(shearTraction/sigmaMaxI);
40 maxEffTractionFraction = gMax(effTractionFraction);
42 SLList<label> facesToBreakList;
43 SLList<scalar> facesToBreakEffTractionFractionList;
45 forAll(effTractionFraction, faceI)
47 if (effTractionFraction[faceI] > 1.0)
49 facesToBreakList.insert(faceI);
50 facesToBreakEffTractionFractionList.insert(effTractionFraction[faceI]);
54 labelList facesToBreak(facesToBreakList);
55 List<scalar> facesToBreakEffTractionFraction(facesToBreakEffTractionFractionList);
57 nFacesToBreak = facesToBreak.size();
59 // Break only one face per topo change
60 if (nFacesToBreak > 1)
65 // philipc - select face with maximum effective traction fraction
66 label faceToBreakIndex = -1;
67 scalar faceToBreakEffTractionFraction = 0;
68 forAll(facesToBreakEffTractionFraction, faceI)
70 if (facesToBreakEffTractionFraction[faceI] > faceToBreakEffTractionFraction)
72 faceToBreakEffTractionFraction = facesToBreakEffTractionFraction[faceI];
73 faceToBreakIndex = facesToBreak[faceI];
77 scalar gMaxEffTractionFraction =
78 returnReduce(faceToBreakEffTractionFraction, maxOp<scalar>());
80 if (Pstream::parRun())
82 bool procHasFaceToBreak = false;
83 if (nFacesToBreak > 0)
85 if ( mag(gMaxEffTractionFraction - faceToBreakEffTractionFraction) < SMALL )
87 // philipc - Maximum traction fraction is on this processor
88 procHasFaceToBreak = true;
92 // Check if maximum is present on more then one processors
93 label procID = Pstream::nProcs();
94 if (procHasFaceToBreak)
96 procID = Pstream::myProcNo();
100 returnReduce<label>(procID, minOp<label>());
102 if (procID != minProcID)
109 // Check coupled (processor) patches
111 SLList<label> coupledFacesToBreakList;
112 SLList<scalar> coupledFacesToBreakEffTractionFractionList;
113 forAll(mesh.boundary(), patchI)
115 if (mesh.boundary()[patchI].coupled())
117 // scalarField pEffTraction =
118 // cohesiveZone.boundaryField()[patchI] *
119 // mag(traction.boundaryField()[patchI]);
120 // scalarField pEffTractionFraction = pEffTraction/sigmaMax.boundaryField()[patchI];
122 scalarField pNormalTraction =
123 cohesiveZone.boundaryField()[patchI] *
124 ( n.boundaryField()[patchI] & traction.boundaryField()[patchI] );
125 pNormalTraction = max(pNormalTraction, 0.0); // only consider tensile tractions
126 scalarField pShearTraction =
127 cohesiveZone.boundaryField()[patchI] *
128 mag( (I - Foam::sqr(n.boundaryField()[patchI])) & traction.boundaryField()[patchI] );
130 // the traction fraction is monitored to decide which faces to break:
131 // ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face
132 const scalarField& pSigmaMax = sigmaMax.boundaryField()[patchI];
133 const scalarField& pTauMax = tauMax.boundaryField()[patchI];
135 scalarField pEffTractionFraction(pNormalTraction.size(), 0.0);
136 if(cohesivePatchUPtr)
138 pEffTractionFraction =
139 (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) + (pShearTraction/pTauMax)*(pShearTraction/pTauMax);
143 // solidCohesiveFixedModeMix only uses sigmaMax
144 pEffTractionFraction =
145 (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) + (pShearTraction/pSigmaMax)*(pShearTraction/pSigmaMax);
148 label start = mesh.boundaryMesh()[patchI].start();
150 forAll(pEffTractionFraction, faceI)
152 if (pEffTractionFraction[faceI] > maxEffTractionFraction)
154 maxEffTractionFraction = pEffTractionFraction[faceI];
157 if (pEffTractionFraction[faceI] > 1.0)
159 coupledFacesToBreakList.insert(start + faceI);
160 coupledFacesToBreakEffTractionFractionList.insert
162 pEffTractionFraction[faceI]
169 labelList coupledFacesToBreak(coupledFacesToBreakList);
170 List<scalar> coupledFacesToBreakEffTractionFraction
172 coupledFacesToBreakEffTractionFractionList
175 nCoupledFacesToBreak = coupledFacesToBreak.size();
177 // Break only one face per topo change
178 if (nCoupledFacesToBreak > 1)
180 nCoupledFacesToBreak = 1;
183 // Select coupled face with maximum effective traction fraction
184 label coupledFaceToBreakIndex = -1;
185 scalar coupledFaceToBreakEffTractionFraction = 0;
186 forAll(coupledFacesToBreakEffTractionFraction, faceI)
190 coupledFacesToBreakEffTractionFraction[faceI]
191 > coupledFaceToBreakEffTractionFraction
194 coupledFaceToBreakEffTractionFraction =
195 coupledFacesToBreakEffTractionFraction[faceI];
196 coupledFaceToBreakIndex = coupledFacesToBreak[faceI];
200 scalar gMaxCoupledEffTractionFraction =
201 returnReduce(coupledFaceToBreakEffTractionFraction, maxOp<scalar>());
203 if (Pstream::parRun())
206 bool procHasCoupledFaceToBreak = false;
207 if (nCoupledFacesToBreak > 0)
211 mag(gMaxCoupledEffTractionFraction - coupledFaceToBreakEffTractionFraction)
215 // Maximum traction fraction is on this processor
216 procHasCoupledFaceToBreak = true;
220 // Check if maximum is present on more then one processors
221 label procID = Pstream::nProcs();
222 if (procHasCoupledFaceToBreak)
224 procID = Pstream::myProcNo();
228 returnReduce<label>(procID, minOp<label>());
230 if (procID != minProcID)
232 nCoupledFacesToBreak = 0;
236 if (gMaxCoupledEffTractionFraction > gMaxEffTractionFraction)
238 // Break coupled face
243 // Break internal face
244 nCoupledFacesToBreak = 0;
247 // Make sure that coupled faces are broken in pairs
248 labelList ngbProc(Pstream::nProcs(), -1);
249 labelList index(Pstream::nProcs(), -1);
250 if (nCoupledFacesToBreak)
253 mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex);
255 label start = mesh.boundaryMesh()[patchID].start();
256 label localIndex = coupledFaceToBreakIndex - start;
258 const processorPolyPatch& procPatch =
259 refCast<const processorPolyPatch>(mesh.boundaryMesh()[patchID]);
260 label ngbProcNo = procPatch.neighbProcNo();
262 ngbProc[Pstream::myProcNo()] = ngbProcNo;
263 index[Pstream::myProcNo()] = localIndex;
266 if (returnReduce(nCoupledFacesToBreak, maxOp<label>()))
268 reduce(ngbProc, maxOp<labelList>());
269 reduce(index, maxOp<labelList>());
271 for (label procI = 0; procI < Pstream::nProcs(); procI++)
273 if (procI != Pstream::myProcNo())
275 if (ngbProc[procI] == Pstream::myProcNo())
277 forAll(mesh.boundaryMesh(), patchI)
281 mesh.boundaryMesh()[patchI].type()
282 == processorPolyPatch::typeName
285 const processorPolyPatch& procPatch =
286 refCast<const processorPolyPatch>
288 mesh.boundaryMesh()[patchI]
290 label ngbProcNo = procPatch.neighbProcNo();
292 if (ngbProcNo == procI)
295 mesh.boundaryMesh()[patchI].start();
296 coupledFaceToBreakIndex = start + index[procI];
297 nCoupledFacesToBreak = 1;
307 vector faceToBreakTraction = vector::zero;
308 vector faceToBreakNormal = vector::zero;
309 scalar faceToBreakSigmaMax = 0.0;
310 scalar faceToBreakTauMax = 0.0;
311 // Set faces to break
312 if (nFacesToBreak > 0)
314 faceToBreakTraction = traction.internalField()[faceToBreakIndex];
315 faceToBreakNormal = n.internalField()[faceToBreakIndex];
317 // Scale broken face traction
318 faceToBreakSigmaMax = sigmaMaxI[faceToBreakIndex];
319 faceToBreakTauMax = tauMaxI[faceToBreakIndex];
320 scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
321 normalTrac = max(normalTrac, 0.0);
322 scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
323 scalar scaleFactor = 1;
324 if(cohesivePatchUPtr)
328 (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
329 + (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
334 // solidCohesiveFixedModeMix only uses sigmaMax
337 (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
338 + (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
342 faceToBreakTraction *= scaleFactor;
346 else if (nCoupledFacesToBreak > 0)
349 mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex);
350 label start = mesh.boundaryMesh()[patchID].start();
351 label localIndex = coupledFaceToBreakIndex - start;
353 faceToBreakTraction = traction.boundaryField()[patchID][localIndex];
354 faceToBreakNormal = n.boundaryField()[patchID][localIndex];
356 // Scale broken face traction
357 faceToBreakSigmaMax = sigmaMax.boundaryField()[patchID][localIndex];
358 faceToBreakTauMax = tauMax.boundaryField()[patchID][localIndex];
359 scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
360 normalTrac = max(normalTrac, 0.0);
361 scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
362 scalar scaleFactor = 1;
363 if(cohesivePatchUPtr)
367 (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
368 + (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
373 // solidCohesiveFixedModeMix only uses sigmaMax
376 (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
377 + (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
381 faceToBreakTraction *= scaleFactor;
386 reduce(topoChange, orOp<bool>());
388 labelList faceToBreak(nFacesToBreak, faceToBreakIndex);
389 boolList faceToBreakFlip(nFacesToBreak, false);
390 labelList coupledFaceToBreak
392 nCoupledFacesToBreak,
393 coupledFaceToBreakIndex
396 reduce(nFacesToBreak, maxOp<label>());
397 reduce(nCoupledFacesToBreak, maxOp<label>());
399 if (nFacesToBreak || nCoupledFacesToBreak)
401 Pout << "Internal face to break: " << faceToBreak << endl;
402 Pout << "Coupled face to break: " << coupledFaceToBreak << endl;
404 mesh.setBreak(faceToBreak, faceToBreakFlip, coupledFaceToBreak);
407 const labelList& faceMap = mesh.topoChangeMap().faceMap();
408 label start = mesh.boundaryMesh()[cohesivePatchID].start();
410 // mu = rheology.mu();
411 // lambda = rheology.lambda();
412 // muf = fvc::interpolate(mu);
413 // lambdaf = fvc::interpolate(lambda);
416 Cf = fvc::interpolate(C);
417 Kf = fvc::interpolate(K);
419 // we need to modify propertiess after cracking otherwise momentum equation is wrong
420 // but solidInterface seems to hold some information about old mesh
421 // so we will delete it and make another
422 // we could probably add a public clearout function
423 // create new solidInterface
424 //Pout << "Creating new solidInterface" << endl;
425 //delete solidInterfacePtr;
426 //solidInterfacePtr = new solidInterface(mesh, rheology);
427 // delete demand driven data as the mesh has changed
428 if(rheology.solidInterfaceActive())
430 rheology.solInterface().clearOut();
431 solidInterfacePtr->modifyProperties(Cf, Kf);
434 // Local crack displacement
436 U.boundaryField()[cohesivePatchID].patchInternalField();
438 U.oldTime().boundaryField()[cohesivePatchID].patchInternalField();
440 // Global crack displacement
441 vectorField globalUpI = mesh.globalCrackField(UpI);
442 vectorField globalOldUpI = mesh.globalCrackField(oldUpI);
444 // C and K field on new crack faces must be updated
445 symmTensor4thOrderField CPI = C.boundaryField()[cohesivePatchID].patchInternalField();
446 diagTensorField KPI = K.boundaryField()[cohesivePatchID].patchInternalField();
447 symmTensor4thOrderField globalCPI = mesh.globalCrackField(CPI);
448 diagTensorField globalKPI = mesh.globalCrackField(KPI);
450 // cohesivePatchU.size()
451 int cohesivePatchSize(cohesivePatchUPtr ? cohesivePatchUPtr->size() : cohesivePatchUFixedModePtr->size());
453 // Initialise U for new cohesive face
454 const labelList& gcfa = mesh.globalCrackFaceAddressing();
455 label globalIndex = mesh.localCrackStart();
456 // for (label i=0; i<cohesivePatchU.size(); i++)
457 for (label i=0; i<cohesivePatchSize; i++)
459 label oldFaceIndex = faceMap[start+i];
462 if (oldFaceIndex == faceToBreakIndex)
464 U.boundaryField()[cohesivePatchID][i] =
467 globalUpI[globalIndex]
468 + globalUpI[gcfa[globalIndex]]
470 U.oldTime().boundaryField()[cohesivePatchID][i] =
473 globalOldUpI[globalIndex]
474 + globalOldUpI[gcfa[globalIndex]]
477 // initialise C and K on new faces
478 // set new face value to value of internal cell
479 Cf.boundaryField()[cohesivePatchID][i] = globalCPI[globalIndex];
480 Kf.boundaryField()[cohesivePatchID][i] = globalKPI[globalIndex];
490 // we must calculate grad using interface
491 // U at the interface has not been calculated yet as interface.correct()
492 // has not been called yet
493 // not really a problem as gradU is correct in second outer iteration
494 // as long as this does not cause convergence problems for the first iterations.
495 // we should be able to calculate the interface displacements without
496 // having to call interface.correct()
497 // todo: add calculateInterfaceU() function
498 // interface grad uses Gauss, we need least squares
499 //gradU = solidInterfacePtr->grad(U);
500 gradU = fvc::grad(U); // leastSquaresSolidInterface grad scheme
501 //snGradU = fvc::snGrad(U);
503 # include "calculateTraction.H"
504 //if (nFacesToBreak || nCoupledFacesToBreak) mesh.write(); traction.write();
506 // Initialise initiation traction for new cohesive patch face
507 // for (label i=0; i<cohesivePatchU.size(); i++)
508 for (label i=0; i<cohesivePatchSize; i++)
510 label oldFaceIndex = faceMap[start+i];
515 (oldFaceIndex == faceToBreakIndex)
516 || (oldFaceIndex == coupledFaceToBreakIndex)
520 mesh.Sf().boundaryField()[cohesivePatchID][i]
521 /mesh.magSf().boundaryField()[cohesivePatchID][i];
524 if ((n0&faceToBreakNormal) > SMALL)
526 traction.boundaryField()[cohesivePatchID][i] =
529 traction.oldTime().boundaryField()[cohesivePatchID][i] =
532 if(cohesivePatchUPtr)
534 cohesivePatchUPtr->traction()[i] = faceToBreakTraction;
538 cohesivePatchUFixedModePtr->traction()[i] = faceToBreakTraction;
539 cohesivePatchUFixedModePtr->initiationTraction()[i] = faceToBreakTraction;
544 traction.boundaryField()[cohesivePatchID][i] =
545 -faceToBreakTraction;
547 traction.oldTime().boundaryField()[cohesivePatchID][i] =
548 -faceToBreakTraction;
550 //cohesivePatchU.traction()[i] = -faceToBreakTraction;
551 if(cohesivePatchUPtr)
553 cohesivePatchUPtr->traction()[i] = -faceToBreakTraction;
557 cohesivePatchUFixedModePtr->traction()[i] = -faceToBreakTraction;
558 cohesivePatchUFixedModePtr->initiationTraction()[i] = -faceToBreakTraction;
564 // hmmnn we only need a reference for very small groups of cells
566 //# include "updateReference.H"