2013-10-11 13:31:14 +00:00
|
|
|
nFacesToBreak = 0;
|
|
|
|
nCoupledFacesToBreak = 0;
|
|
|
|
{
|
|
|
|
// Check internal faces
|
|
|
|
|
2014-06-01 18:12:52 +00:00
|
|
|
// scalarField effTraction =
|
2013-10-11 13:31:14 +00:00
|
|
|
// cohesiveZone.internalField() *
|
|
|
|
// mag(traction.internalField());
|
2015-05-01 12:21:04 +00:00
|
|
|
scalarField normalTraction =
|
|
|
|
cohesiveZone.internalField()*
|
|
|
|
( n.internalField() & traction.internalField() );
|
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
// only consider tensile tractions
|
2015-05-01 12:21:04 +00:00
|
|
|
normalTraction = max(normalTraction, scalar(0));
|
|
|
|
scalarField shearTraction =
|
2015-05-17 14:25:35 +00:00
|
|
|
cohesiveZone.internalField()*
|
2015-05-01 12:21:04 +00:00
|
|
|
mag( (I - Foam::sqr(n.internalField())) & traction.internalField() );
|
2013-10-11 13:31:14 +00:00
|
|
|
|
|
|
|
// the traction fraction is monitored to decide which faces to break:
|
|
|
|
// ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face
|
2015-05-17 14:25:35 +00:00
|
|
|
|
2013-10-11 13:31:14 +00:00
|
|
|
const surfaceScalarField sigmaMax = rheology.cohLaw().sigmaMax();
|
|
|
|
const surfaceScalarField tauMax = rheology.cohLaw().tauMax();
|
|
|
|
|
|
|
|
const scalarField& sigmaMaxI = sigmaMax.internalField();
|
|
|
|
const scalarField& tauMaxI = tauMax.internalField();
|
|
|
|
|
|
|
|
//scalarField effTractionFraction = effTraction/sigmaMax;
|
|
|
|
// scalarField effTractionFraction =
|
|
|
|
// (normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI) + (shearTraction/tauMaxI)*(shearTraction/tauMaxI);
|
|
|
|
scalarField effTractionFraction(normalTraction.size(), 0.0);
|
2014-06-01 18:12:52 +00:00
|
|
|
|
2013-10-11 13:31:14 +00:00
|
|
|
if(cohesivePatchDUPtr)
|
2015-05-01 12:21:04 +00:00
|
|
|
{
|
|
|
|
effTractionFraction =
|
|
|
|
(normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI)
|
|
|
|
+ (shearTraction/tauMaxI)*(shearTraction/tauMaxI);
|
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
else
|
2015-05-01 12:21:04 +00:00
|
|
|
{
|
|
|
|
// solidCohesiveFixedModeMix only uses sigmaMax
|
|
|
|
effTractionFraction =
|
|
|
|
(normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI)
|
|
|
|
+ (shearTraction/sigmaMaxI)*(shearTraction/sigmaMaxI);
|
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
|
|
|
|
maxEffTractionFraction = gMax(effTractionFraction);
|
|
|
|
|
|
|
|
SLList<label> facesToBreakList;
|
|
|
|
SLList<scalar> facesToBreakEffTractionFractionList;
|
|
|
|
|
|
|
|
forAll(effTractionFraction, faceI)
|
|
|
|
{
|
2015-05-01 12:21:04 +00:00
|
|
|
if (effTractionFraction[faceI] > 1.0)
|
2013-10-11 13:31:14 +00:00
|
|
|
{
|
|
|
|
facesToBreakList.insert(faceI);
|
2015-05-01 12:21:04 +00:00
|
|
|
facesToBreakEffTractionFractionList.insert
|
|
|
|
(
|
|
|
|
effTractionFraction[faceI]
|
|
|
|
);
|
2013-10-11 13:31:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
labelList facesToBreak(facesToBreakList);
|
2019-02-01 12:36:12 +00:00
|
|
|
scalarList facesToBreakEffTractionFraction
|
2015-05-01 12:21:04 +00:00
|
|
|
(
|
|
|
|
facesToBreakEffTractionFractionList
|
|
|
|
);
|
2013-10-11 13:31:14 +00:00
|
|
|
|
|
|
|
nFacesToBreak = facesToBreak.size();
|
|
|
|
|
|
|
|
// Break only one face per topo change
|
|
|
|
if (nFacesToBreak > 1)
|
|
|
|
{
|
|
|
|
nFacesToBreak = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// philipc - select face with maximum effective traction fraction
|
|
|
|
label faceToBreakIndex = -1;
|
|
|
|
scalar faceToBreakEffTractionFraction = 0;
|
|
|
|
forAll(facesToBreakEffTractionFraction, faceI)
|
|
|
|
{
|
2015-05-01 12:21:04 +00:00
|
|
|
if
|
|
|
|
(
|
|
|
|
facesToBreakEffTractionFraction[faceI]
|
|
|
|
> faceToBreakEffTractionFraction
|
|
|
|
)
|
2013-10-11 13:31:14 +00:00
|
|
|
{
|
2015-05-01 12:21:04 +00:00
|
|
|
faceToBreakEffTractionFraction =
|
|
|
|
facesToBreakEffTractionFraction[faceI];
|
2013-10-11 13:31:14 +00:00
|
|
|
faceToBreakIndex = facesToBreak[faceI];
|
|
|
|
}
|
|
|
|
}
|
2015-05-17 14:25:35 +00:00
|
|
|
|
2014-06-01 18:12:52 +00:00
|
|
|
scalar gMaxEffTractionFraction =
|
2013-10-11 13:31:14 +00:00
|
|
|
returnReduce(faceToBreakEffTractionFraction, maxOp<scalar>());
|
|
|
|
|
|
|
|
if (Pstream::parRun())
|
|
|
|
{
|
|
|
|
bool procHasFaceToBreak = false;
|
|
|
|
if (nFacesToBreak > 0)
|
|
|
|
{
|
2015-05-01 12:21:04 +00:00
|
|
|
if
|
|
|
|
(
|
|
|
|
mag(gMaxEffTractionFraction - faceToBreakEffTractionFraction)
|
|
|
|
< SMALL
|
|
|
|
)
|
2013-10-11 13:31:14 +00:00
|
|
|
{
|
|
|
|
// philipc - Maximum traction fraction is on this processor
|
|
|
|
procHasFaceToBreak = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if maximum is present on more then one processors
|
|
|
|
label procID = Pstream::nProcs();
|
|
|
|
if (procHasFaceToBreak)
|
|
|
|
{
|
|
|
|
procID = Pstream::myProcNo();
|
|
|
|
}
|
|
|
|
|
|
|
|
label minProcID =
|
|
|
|
returnReduce<label>(procID, minOp<label>());
|
|
|
|
|
|
|
|
if (procID != minProcID)
|
|
|
|
{
|
|
|
|
nFacesToBreak = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check coupled (processor) patches
|
|
|
|
|
|
|
|
SLList<label> coupledFacesToBreakList;
|
|
|
|
SLList<scalar> coupledFacesToBreakEffTractionFractionList;
|
|
|
|
forAll(mesh.boundary(), patchI)
|
|
|
|
{
|
|
|
|
if (mesh.boundary()[patchI].coupled())
|
|
|
|
{
|
2014-06-01 18:12:52 +00:00
|
|
|
// scalarField pEffTraction =
|
2015-05-17 14:25:35 +00:00
|
|
|
// cohesiveZone.boundaryField()[patchI]*
|
|
|
|
// mag(traction.boundaryField()[patchI]);
|
|
|
|
// scalarField pEffTractionFraction = pEffTraction/sigmaMax.boundaryField()[patchI];
|
|
|
|
|
|
|
|
scalarField pNormalTraction =
|
|
|
|
cohesiveZone.boundaryField()[patchI]*
|
|
|
|
( n.boundaryField()[patchI] & traction.boundaryField()[patchI] );
|
|
|
|
|
|
|
|
// only consider tensile tractions
|
|
|
|
pNormalTraction = max(pNormalTraction, scalar(0));
|
|
|
|
|
|
|
|
scalarField pShearTraction =
|
|
|
|
cohesiveZone.boundaryField()[patchI]*
|
|
|
|
mag( (I - Foam::sqr(n.boundaryField()[patchI])) & traction.boundaryField()[patchI] );
|
|
|
|
|
|
|
|
// the traction fraction is monitored to decide which faces to break:
|
|
|
|
// ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face
|
|
|
|
const scalarField& pSigmaMax = sigmaMax.boundaryField()[patchI];
|
|
|
|
const scalarField& pTauMax = tauMax.boundaryField()[patchI];
|
|
|
|
|
|
|
|
// scalarField pEffTractionFraction =
|
|
|
|
// (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) + (pShearTraction/pTauMax)*(pShearTraction/pTauMax);
|
|
|
|
scalarField pEffTractionFraction(pNormalTraction.size(), 0.0);
|
|
|
|
if(cohesivePatchDUPtr)
|
|
|
|
{
|
|
|
|
pEffTractionFraction =
|
|
|
|
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
|
|
|
|
+ (pShearTraction/pTauMax)*(pShearTraction/pTauMax);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// solidCohesiveFixedModeMix only uses sigmaMax
|
|
|
|
pEffTractionFraction =
|
|
|
|
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
|
|
|
|
+ (pShearTraction/pSigmaMax)*(pShearTraction/pSigmaMax);
|
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
|
|
|
|
label start = mesh.boundaryMesh()[patchI].start();
|
|
|
|
|
|
|
|
forAll(pEffTractionFraction, faceI)
|
|
|
|
{
|
2015-05-01 12:21:04 +00:00
|
|
|
if (pEffTractionFraction[faceI] > maxEffTractionFraction)
|
|
|
|
{
|
|
|
|
maxEffTractionFraction = pEffTractionFraction[faceI];
|
2013-10-11 13:31:14 +00:00
|
|
|
}
|
2014-06-01 18:12:52 +00:00
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
if (pEffTractionFraction[faceI] > 1.0)
|
2013-10-11 13:31:14 +00:00
|
|
|
{
|
2015-05-17 14:25:35 +00:00
|
|
|
//Pout << "coupled face to break " << faceI << endl;
|
2013-10-11 13:31:14 +00:00
|
|
|
coupledFacesToBreakList.insert(start + faceI);
|
|
|
|
coupledFacesToBreakEffTractionFractionList.insert
|
|
|
|
(
|
|
|
|
pEffTractionFraction[faceI]
|
|
|
|
);
|
|
|
|
}
|
2014-06-01 18:12:52 +00:00
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
labelList coupledFacesToBreak(coupledFacesToBreakList);
|
2019-02-01 12:36:12 +00:00
|
|
|
scalarList coupledFacesToBreakEffTractionFraction
|
2013-10-11 13:31:14 +00:00
|
|
|
(
|
|
|
|
coupledFacesToBreakEffTractionFractionList
|
|
|
|
);
|
|
|
|
|
|
|
|
nCoupledFacesToBreak = coupledFacesToBreak.size();
|
|
|
|
// Pout << "nCoupledFacesToBreak: " << nCoupledFacesToBreak << endl;
|
|
|
|
|
|
|
|
// Break only one face per topo change
|
|
|
|
if (nCoupledFacesToBreak > 1)
|
|
|
|
{
|
|
|
|
nCoupledFacesToBreak = 1;
|
|
|
|
}
|
2014-06-01 18:12:52 +00:00
|
|
|
|
2013-10-11 13:31:14 +00:00
|
|
|
// Select coupled face with maximum effective traction fraction
|
|
|
|
label coupledFaceToBreakIndex = -1;
|
|
|
|
scalar coupledFaceToBreakEffTractionFraction = 0;
|
|
|
|
forAll(coupledFacesToBreakEffTractionFraction, faceI)
|
|
|
|
{
|
2014-06-01 18:12:52 +00:00
|
|
|
if
|
2013-10-11 13:31:14 +00:00
|
|
|
(
|
2014-06-01 18:12:52 +00:00
|
|
|
coupledFacesToBreakEffTractionFraction[faceI]
|
2013-10-11 13:31:14 +00:00
|
|
|
> coupledFaceToBreakEffTractionFraction
|
|
|
|
)
|
|
|
|
{
|
2014-06-01 18:12:52 +00:00
|
|
|
coupledFaceToBreakEffTractionFraction =
|
2013-10-11 13:31:14 +00:00
|
|
|
coupledFacesToBreakEffTractionFraction[faceI];
|
|
|
|
coupledFaceToBreakIndex = coupledFacesToBreak[faceI];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-01 18:12:52 +00:00
|
|
|
scalar gMaxCoupledEffTractionFraction =
|
2013-10-11 13:31:14 +00:00
|
|
|
returnReduce(coupledFaceToBreakEffTractionFraction, maxOp<scalar>());
|
|
|
|
|
|
|
|
if (Pstream::parRun())
|
|
|
|
{
|
|
|
|
|
|
|
|
bool procHasCoupledFaceToBreak = false;
|
|
|
|
if (nCoupledFacesToBreak > 0)
|
|
|
|
{
|
|
|
|
if
|
|
|
|
(
|
2014-06-01 18:12:52 +00:00
|
|
|
mag(gMaxCoupledEffTractionFraction - coupledFaceToBreakEffTractionFraction)
|
|
|
|
< SMALL
|
2013-10-11 13:31:14 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
// Maximum traction fraction is on this processor
|
|
|
|
procHasCoupledFaceToBreak = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if maximum is present on more then one processors
|
|
|
|
label procID = Pstream::nProcs();
|
|
|
|
if (procHasCoupledFaceToBreak)
|
|
|
|
{
|
|
|
|
procID = Pstream::myProcNo();
|
|
|
|
}
|
|
|
|
|
|
|
|
label minProcID =
|
|
|
|
returnReduce<label>(procID, minOp<label>());
|
2014-06-01 18:12:52 +00:00
|
|
|
|
2013-10-11 13:31:14 +00:00
|
|
|
if (procID != minProcID)
|
|
|
|
{
|
|
|
|
nCoupledFacesToBreak = 0;
|
2014-06-01 18:12:52 +00:00
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (gMaxCoupledEffTractionFraction > gMaxEffTractionFraction)
|
|
|
|
{
|
|
|
|
// Break coupled face
|
|
|
|
nFacesToBreak = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Break internal face
|
|
|
|
nCoupledFacesToBreak = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure that coupled faces are broken in pairs
|
|
|
|
labelList ngbProc(Pstream::nProcs(), -1);
|
|
|
|
labelList index(Pstream::nProcs(), -1);
|
|
|
|
if (nCoupledFacesToBreak)
|
|
|
|
{
|
2014-06-01 18:12:52 +00:00
|
|
|
label patchID =
|
2013-10-11 13:31:14 +00:00
|
|
|
mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex);
|
2015-05-17 14:25:35 +00:00
|
|
|
|
2013-10-11 13:31:14 +00:00
|
|
|
label start = mesh.boundaryMesh()[patchID].start();
|
|
|
|
label localIndex = coupledFaceToBreakIndex - start;
|
|
|
|
|
|
|
|
const processorPolyPatch& procPatch =
|
|
|
|
refCast<const processorPolyPatch>(mesh.boundaryMesh()[patchID]);
|
|
|
|
label ngbProcNo = procPatch.neighbProcNo();
|
|
|
|
|
|
|
|
ngbProc[Pstream::myProcNo()] = ngbProcNo;
|
|
|
|
index[Pstream::myProcNo()] = localIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (returnReduce(nCoupledFacesToBreak, maxOp<label>()))
|
|
|
|
{
|
|
|
|
reduce(ngbProc, maxOp<labelList>());
|
|
|
|
reduce(index, maxOp<labelList>());
|
|
|
|
|
|
|
|
for (label procI = 0; procI < Pstream::nProcs(); procI++)
|
|
|
|
{
|
|
|
|
if (procI != Pstream::myProcNo())
|
|
|
|
{
|
|
|
|
if (ngbProc[procI] == Pstream::myProcNo())
|
|
|
|
{
|
|
|
|
forAll(mesh.boundaryMesh(), patchI)
|
|
|
|
{
|
|
|
|
if
|
|
|
|
(
|
|
|
|
mesh.boundaryMesh()[patchI].type()
|
|
|
|
== processorPolyPatch::typeName
|
|
|
|
)
|
|
|
|
{
|
|
|
|
const processorPolyPatch& procPatch =
|
|
|
|
refCast<const processorPolyPatch>
|
|
|
|
(
|
|
|
|
mesh.boundaryMesh()[patchI]
|
|
|
|
);
|
|
|
|
label ngbProcNo = procPatch.neighbProcNo();
|
2014-06-01 18:12:52 +00:00
|
|
|
|
2013-10-11 13:31:14 +00:00
|
|
|
if (ngbProcNo == procI)
|
|
|
|
{
|
2014-06-01 18:12:52 +00:00
|
|
|
label start =
|
2013-10-11 13:31:14 +00:00
|
|
|
mesh.boundaryMesh()[patchI].start();
|
|
|
|
coupledFaceToBreakIndex = start + index[procI];
|
|
|
|
nCoupledFacesToBreak = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vector faceToBreakTraction = vector::zero;
|
|
|
|
vector faceToBreakNormal = vector::zero;
|
|
|
|
scalar faceToBreakSigmaMax = 0.0;
|
|
|
|
scalar faceToBreakTauMax = 0.0;
|
|
|
|
|
|
|
|
// Set faces to break
|
|
|
|
if (nFacesToBreak > 0)
|
|
|
|
{
|
|
|
|
faceToBreakTraction = traction.internalField()[faceToBreakIndex];
|
|
|
|
faceToBreakNormal = n.internalField()[faceToBreakIndex];
|
|
|
|
|
|
|
|
// Scale broken face traction
|
2015-05-17 14:25:35 +00:00
|
|
|
// The scale factor is derived by solving the following eqn for alpha:
|
|
|
|
// (alpha*tN/tNC)^2 + (alpha*tS/tSC)^2 = 1
|
|
|
|
faceToBreakSigmaMax = sigmaMaxI[faceToBreakIndex];
|
|
|
|
faceToBreakTauMax = tauMaxI[faceToBreakIndex];
|
|
|
|
scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
|
|
|
|
normalTrac = max(normalTrac, 0.0);
|
|
|
|
scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
|
|
|
|
scalar scaleFactor = 1;
|
|
|
|
if(cohesivePatchDUPtr)
|
|
|
|
{
|
|
|
|
scaleFactor =
|
|
|
|
Foam::sqrt
|
|
|
|
(
|
|
|
|
1 /
|
|
|
|
(
|
|
|
|
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
|
|
|
|
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
|
|
|
|
)
|
|
|
|
);
|
2015-05-17 15:11:30 +00:00
|
|
|
}
|
2015-05-17 14:25:35 +00:00
|
|
|
else
|
2015-05-17 15:11:30 +00:00
|
|
|
{
|
2015-05-17 14:25:35 +00:00
|
|
|
// solidCohesiveFixedModeMix only uses sigmaMax
|
|
|
|
scaleFactor =
|
|
|
|
Foam::sqrt
|
|
|
|
(
|
|
|
|
1 /
|
|
|
|
(
|
|
|
|
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
|
|
|
|
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
|
|
|
|
)
|
|
|
|
);
|
2015-05-17 15:11:30 +00:00
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
|
|
|
|
faceToBreakTraction *= scaleFactor;
|
|
|
|
|
|
|
|
topoChange = true;
|
|
|
|
}
|
|
|
|
else if (nCoupledFacesToBreak > 0)
|
|
|
|
{
|
2014-06-01 18:12:52 +00:00
|
|
|
label patchID =
|
2013-10-11 13:31:14 +00:00
|
|
|
mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex);
|
|
|
|
label start = mesh.boundaryMesh()[patchID].start();
|
|
|
|
label localIndex = coupledFaceToBreakIndex - start;
|
|
|
|
|
|
|
|
faceToBreakTraction = traction.boundaryField()[patchID][localIndex];
|
|
|
|
faceToBreakNormal = n.boundaryField()[patchID][localIndex];
|
2014-06-01 18:12:52 +00:00
|
|
|
|
2013-10-11 13:31:14 +00:00
|
|
|
// Scale broken face traction
|
2015-05-17 14:25:35 +00:00
|
|
|
faceToBreakSigmaMax = sigmaMax.boundaryField()[patchID][localIndex];
|
|
|
|
faceToBreakTauMax = tauMax.boundaryField()[patchID][localIndex];
|
|
|
|
scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
|
|
|
|
normalTrac = max(normalTrac, 0.0);
|
|
|
|
scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
|
|
|
|
scalar scaleFactor = 1;
|
|
|
|
if(cohesivePatchDUPtr)
|
|
|
|
{
|
|
|
|
scaleFactor =
|
|
|
|
Foam::sqrt
|
2015-05-01 12:21:04 +00:00
|
|
|
(
|
2015-05-17 14:25:35 +00:00
|
|
|
1 /
|
|
|
|
(
|
|
|
|
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
|
|
|
|
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// solidCohesiveFixedModeMix only uses sigmaMax
|
|
|
|
scaleFactor =
|
|
|
|
Foam::sqrt
|
2015-05-01 12:21:04 +00:00
|
|
|
(
|
2015-05-17 14:25:35 +00:00
|
|
|
1 /
|
|
|
|
(
|
|
|
|
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
|
|
|
|
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
faceToBreakTraction *= scaleFactor;
|
2015-05-15 13:57:39 +00:00
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
topoChange = true;
|
2013-10-11 13:31:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
reduce(topoChange, orOp<bool>());
|
|
|
|
|
|
|
|
labelList faceToBreak(nFacesToBreak, faceToBreakIndex);
|
|
|
|
boolList faceToBreakFlip(nFacesToBreak, false);
|
|
|
|
labelList coupledFaceToBreak
|
|
|
|
(
|
|
|
|
nCoupledFacesToBreak,
|
|
|
|
coupledFaceToBreakIndex
|
|
|
|
);
|
|
|
|
|
|
|
|
reduce(nFacesToBreak, maxOp<label>());
|
|
|
|
reduce(nCoupledFacesToBreak, maxOp<label>());
|
|
|
|
|
|
|
|
if (nFacesToBreak || nCoupledFacesToBreak)
|
|
|
|
{
|
|
|
|
Pout << "Internal face to break: " << faceToBreak << endl;
|
|
|
|
Pout << "Coupled face to break: " << coupledFaceToBreak << endl;
|
|
|
|
|
|
|
|
mesh.setBreak(faceToBreak, faceToBreakFlip, coupledFaceToBreak);
|
2015-05-17 14:25:35 +00:00
|
|
|
mesh.update();
|
2013-10-11 13:31:14 +00:00
|
|
|
|
|
|
|
const labelList& faceMap = mesh.topoChangeMap().faceMap();
|
|
|
|
label start = mesh.boundaryMesh()[cohesivePatchID].start();
|
|
|
|
|
|
|
|
mu = rheology.mu();
|
|
|
|
lambda = rheology.lambda();
|
|
|
|
muf = fvc::interpolate(mu);
|
|
|
|
lambdaf = fvc::interpolate(lambda);
|
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
// we need to modify propertiess after cracking otherwise momentum equation is wrong
|
|
|
|
// but solidInterface seems to hold some information about old mesh
|
|
|
|
// so we will delete it and make another
|
|
|
|
// we could probably add a public clearout function
|
|
|
|
// create new solidInterface
|
|
|
|
if(rheology.solidInterfaceActive())
|
|
|
|
{
|
|
|
|
rheology.solInterface().clearOut();
|
|
|
|
solidInterfacePtr->modifyProperties(muf, lambdaf);
|
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
|
|
|
|
// All values on the new crack faces get set to zero
|
2015-05-17 14:25:35 +00:00
|
|
|
// so we must manually correct them
|
2014-06-01 18:12:52 +00:00
|
|
|
const vectorField DUpI =
|
2013-10-11 13:31:14 +00:00
|
|
|
DU.boundaryField()[cohesivePatchID].patchInternalField();
|
2014-06-01 18:12:52 +00:00
|
|
|
const vectorField oldDUpI =
|
2013-10-11 13:31:14 +00:00
|
|
|
DU.oldTime().boundaryField()[cohesivePatchID].patchInternalField();
|
2014-06-01 18:12:52 +00:00
|
|
|
const vectorField UpI =
|
2013-10-11 13:31:14 +00:00
|
|
|
U.boundaryField()[cohesivePatchID].patchInternalField();
|
2014-06-01 18:12:52 +00:00
|
|
|
const vectorField oldUpI =
|
2013-10-11 13:31:14 +00:00
|
|
|
U.oldTime().boundaryField()[cohesivePatchID].patchInternalField();
|
2014-06-01 18:12:52 +00:00
|
|
|
const symmTensorField sigmapI =
|
2013-10-11 13:31:14 +00:00
|
|
|
sigma.boundaryField()[cohesivePatchID].patchInternalField();
|
|
|
|
const scalarField muPI = mu.boundaryField()[cohesivePatchID].patchInternalField();
|
|
|
|
const scalarField lambdaPI = lambda.boundaryField()[cohesivePatchID].patchInternalField();
|
2014-06-01 18:12:52 +00:00
|
|
|
|
2013-10-11 13:31:14 +00:00
|
|
|
// Global crack fields
|
|
|
|
const vectorField globalDUpI = mesh.globalCrackField(DUpI);
|
|
|
|
const vectorField globalOldDUpI = mesh.globalCrackField(oldDUpI);
|
|
|
|
const vectorField globalUpI = mesh.globalCrackField(UpI);
|
|
|
|
const vectorField globalOldUpI = mesh.globalCrackField(oldUpI);
|
|
|
|
const symmTensorField globalsigmapI = mesh.globalCrackField(sigmapI);
|
|
|
|
const scalarField globalMuPI = mesh.globalCrackField(muPI);
|
|
|
|
const scalarField globalLambdaPI = mesh.globalCrackField(lambdaPI);
|
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
// cohesivePatchU.size()
|
|
|
|
int cohesivePatchSize(cohesivePatchDUPtr ? cohesivePatchDUPtr->size() : cohesivePatchDUFixedModePtr->size());
|
2013-10-11 13:31:14 +00:00
|
|
|
|
|
|
|
// Initialise fields for new cohesive face
|
|
|
|
const labelList& gcfa = mesh.globalCrackFaceAddressing();
|
|
|
|
label globalIndex = mesh.localCrackStart();
|
|
|
|
//for (label i=0; i<cohesivePatchDU.size(); i++)
|
|
|
|
for (label i=0; i<cohesivePatchSize; i++)
|
|
|
|
{
|
|
|
|
label oldFaceIndex = faceMap[start+i];
|
|
|
|
|
|
|
|
// If new face
|
|
|
|
if (oldFaceIndex == faceToBreakIndex)
|
|
|
|
{
|
2015-05-17 14:25:35 +00:00
|
|
|
// set to average of old cell centres
|
|
|
|
// hmnnn it would be better to interpolate
|
|
|
|
// using weights... OK for now: future work
|
2013-10-11 13:31:14 +00:00
|
|
|
DU.boundaryField()[cohesivePatchID][i] =
|
|
|
|
0.5
|
|
|
|
*(
|
2014-06-01 18:12:52 +00:00
|
|
|
globalDUpI[globalIndex]
|
2013-10-11 13:31:14 +00:00
|
|
|
+ globalDUpI[gcfa[globalIndex]]
|
|
|
|
);
|
|
|
|
DU.oldTime().boundaryField()[cohesivePatchID][i] =
|
|
|
|
0.5
|
|
|
|
*(
|
2014-06-01 18:12:52 +00:00
|
|
|
globalOldDUpI[globalIndex]
|
2013-10-11 13:31:14 +00:00
|
|
|
+ globalOldDUpI[gcfa[globalIndex]]
|
|
|
|
);
|
|
|
|
U.boundaryField()[cohesivePatchID][i] =
|
|
|
|
0.5
|
|
|
|
*(
|
2014-06-01 18:12:52 +00:00
|
|
|
globalUpI[globalIndex]
|
2013-10-11 13:31:14 +00:00
|
|
|
+ globalUpI[gcfa[globalIndex]]
|
|
|
|
);
|
|
|
|
U.oldTime().boundaryField()[cohesivePatchID][i] =
|
|
|
|
0.5
|
|
|
|
*(
|
2014-06-01 18:12:52 +00:00
|
|
|
globalOldUpI[globalIndex]
|
2013-10-11 13:31:14 +00:00
|
|
|
+ globalOldUpI[gcfa[globalIndex]]
|
|
|
|
);
|
|
|
|
sigma.boundaryField()[cohesivePatchID][i] =
|
|
|
|
0.5
|
|
|
|
*(
|
2014-06-01 18:12:52 +00:00
|
|
|
globalsigmapI[globalIndex]
|
2013-10-11 13:31:14 +00:00
|
|
|
+ globalsigmapI[gcfa[globalIndex]]
|
|
|
|
);
|
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
// initialise mu and lambda on new faces
|
|
|
|
// set new face value to value of internal cell
|
|
|
|
muf.boundaryField()[cohesivePatchID][i] = globalMuPI[globalIndex];
|
|
|
|
lambdaf.boundaryField()[cohesivePatchID][i] = globalLambdaPI[globalIndex];
|
2013-10-11 13:31:14 +00:00
|
|
|
|
|
|
|
globalIndex++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
globalIndex++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// we must calculate grad using interface
|
2015-05-17 14:25:35 +00:00
|
|
|
// DU at the interface has not been calculated yet as interface.correct()
|
|
|
|
// has not been called yet
|
|
|
|
// not really a problem as gradDU is correct in second outer iteration
|
|
|
|
// as long as this does not cause convergence problems for the first iterations.
|
|
|
|
// we should be able to calculate the interface displacements without
|
|
|
|
// having to call interface.correct()
|
|
|
|
// todo: add calculateInterfaceDU() function
|
|
|
|
// interface grad uses Gauss, we need least squares
|
2013-10-11 13:31:14 +00:00
|
|
|
gradDU = fvc::grad(DU); // leastSquaresSolidInterface grad scheme
|
2015-05-17 14:25:35 +00:00
|
|
|
//gradDU = solidInterfacePtr->grad(DU);
|
2013-10-11 13:31:14 +00:00
|
|
|
//snGradDU = fvc::snGrad(DU);
|
|
|
|
|
|
|
|
# include "calculateTraction.H"
|
2015-05-17 14:25:35 +00:00
|
|
|
//if (nFacesToBreak || nCoupledFacesToBreak) mesh.write(); traction.write();
|
2013-10-11 13:31:14 +00:00
|
|
|
|
2014-06-01 18:12:52 +00:00
|
|
|
// Initialise initiation traction for new cohesive patch face
|
2015-05-17 14:25:35 +00:00
|
|
|
// we also need to update the traction_ field in the crack boundary condition
|
|
|
|
// this is because it cannot set itself during mapping.
|
2013-10-11 13:31:14 +00:00
|
|
|
//for (label i=0; i<cohesivePatchDU.size(); i++)
|
|
|
|
for (label i=0; i<cohesivePatchSize; i++)
|
|
|
|
{
|
|
|
|
label oldFaceIndex = faceMap[start+i];
|
|
|
|
|
|
|
|
// If new face
|
|
|
|
if
|
|
|
|
(
|
|
|
|
(oldFaceIndex == faceToBreakIndex)
|
|
|
|
|| (oldFaceIndex == coupledFaceToBreakIndex)
|
|
|
|
)
|
|
|
|
{
|
2014-06-01 18:12:52 +00:00
|
|
|
vector n0 =
|
2013-10-11 13:31:14 +00:00
|
|
|
mesh.Sf().boundaryField()[cohesivePatchID][i]
|
|
|
|
/mesh.magSf().boundaryField()[cohesivePatchID][i];
|
|
|
|
//vector n1 = -n0;
|
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
if ((n0 & faceToBreakNormal) > SMALL)
|
2013-10-11 13:31:14 +00:00
|
|
|
{
|
2015-05-17 14:25:35 +00:00
|
|
|
traction.boundaryField()[cohesivePatchID][i] =
|
|
|
|
faceToBreakTraction;
|
2013-10-11 13:31:14 +00:00
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
traction.oldTime().boundaryField()[cohesivePatchID][i] =
|
|
|
|
faceToBreakTraction;
|
2015-05-17 15:11:30 +00:00
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
// this seems to slow convergence in some simple test cases...
|
|
|
|
// but surely it should be better update it
|
|
|
|
//cohesivePatchDU.traction()[i] = faceToBreakTraction;
|
|
|
|
if(cohesivePatchDUPtr)
|
|
|
|
{
|
|
|
|
cohesivePatchDUPtr->traction()[i] = faceToBreakTraction;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cohesivePatchDUFixedModePtr->traction()[i] = faceToBreakTraction;
|
|
|
|
cohesivePatchDUFixedModePtr->initiationTraction()[i] = faceToBreakTraction;
|
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-05-17 14:25:35 +00:00
|
|
|
traction.boundaryField()[cohesivePatchID][i] =
|
|
|
|
-faceToBreakTraction;
|
|
|
|
traction.oldTime().boundaryField()[cohesivePatchID][i] =
|
|
|
|
-faceToBreakTraction;
|
2015-05-17 15:11:30 +00:00
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
//cohesivePatchDU.traction()[i] = -faceToBreakTraction;
|
|
|
|
if(cohesivePatchDUPtr)
|
|
|
|
{
|
|
|
|
cohesivePatchDUPtr->traction()[i] = -faceToBreakTraction;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cohesivePatchDUFixedModePtr->traction()[i] =
|
|
|
|
-faceToBreakTraction;
|
|
|
|
cohesivePatchDUFixedModePtr->initiationTraction()[i] =
|
|
|
|
-faceToBreakTraction;
|
|
|
|
}
|
2013-10-11 13:31:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-06-01 18:12:52 +00:00
|
|
|
|
2015-05-17 14:25:35 +00:00
|
|
|
// hmmnn we only need a reference for very small groups of cells
|
|
|
|
// turn off for now
|
|
|
|
//# include "updateReference.H"
|
2013-10-11 13:31:14 +00:00
|
|
|
}
|
|
|
|
}
|