Fixing indentation in applications/solvers/solidMechanics

This commit is contained in:
Henrik Rusche 2015-05-17 16:25:35 +02:00
parent b46695ce1e
commit c1cd77a15f
138 changed files with 5164 additions and 5127 deletions

View file

@ -6,26 +6,24 @@ aitkenDelta = (U - U.prevIter()) / aitkenInitialRes;
// update relaxation factor // update relaxation factor
if(iCorr == 0) if(iCorr == 0)
{ {
aitkenTheta = 0.1; aitkenTheta = 0.1;
} }
else else
{ {
vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField(); vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField();
//scalar sumMagB = gSum(mag(b)); //scalar sumMagB = gSum(mag(b));
scalar sumMagB = gSum(magSqr(b)); scalar sumMagB = gSum(magSqr(b));
if(sumMagB < SMALL) if(sumMagB < SMALL)
{ {
//Warning << "Aitken under-relaxation: denominator less then SMALL" //Warning << "Aitken under-relaxation: denominator less then SMALL"
// << endl; // << endl;
sumMagB += SMALL; sumMagB += SMALL;
} }
aitkenTheta = -aitkenTheta* aitkenTheta = -aitkenTheta*
gSum(aitkenDelta.prevIter().internalField() & b) gSum(aitkenDelta.prevIter().internalField() & b)/sumMagB;
/ }
sumMagB;
}
// correction to the latest U // correction to the latest U
U += aitkenTheta*aitkenDelta*aitkenInitialRes; U += aitkenTheta*aitkenDelta*aitkenInitialRes;

View file

@ -1,49 +1,44 @@
if(divSigmaExpMethod == "standard") if(divSigmaExpMethod == "standard")
{ {
divSigmaExp = fvc::div divSigmaExp = fvc::div
( (
mu*gradU.T() + lambda*(I*tr(gradU)) - (mu + lambda)*gradU, mu*gradU.T() + lambda*(I*tr(gradU)) - (mu + lambda)*gradU,
"div(sigma)" "div(sigma)"
);
}
else if(divSigmaExpMethod == "surface")
{
divSigmaExp = fvc::div
(
muf*(mesh.Sf() & fvc::interpolate(gradU.T()))
+ lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradU)))
- (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradU))
); );
} }
else if(divSigmaExpMethod == "decompose") else if(divSigmaExpMethod == "surface")
{ {
snGradU = fvc::snGrad(U); divSigmaExp = fvc::div
(
muf*(mesh.Sf() & fvc::interpolate(gradU.T()))
+ lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradU)))
- (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradU))
);
}
else if(divSigmaExpMethod == "decompose")
{
snGradU = fvc::snGrad(U);
surfaceTensorField shearGradU = surfaceTensorField shearGradU = ((I - n*n) & fvc::interpolate(gradU));
((I - n*n)&fvc::interpolate(gradU));
divSigmaExp = fvc::div divSigmaExp = fvc::div
( (
mesh.magSf() mesh.magSf()*
*( (
- (muf + lambdaf)*(snGradU&(I - n*n)) - (muf + lambdaf)*(snGradU & (I - n*n))
+ lambdaf*tr(shearGradU&(I - n*n))*n + lambdaf*tr(shearGradU & (I - n*n))*n
+ muf*(shearGradU&n) + muf*(shearGradU&n)
) )
); );
} }
else if(divSigmaExpMethod == "expLaplacian") else if(divSigmaExpMethod == "expLaplacian")
{ {
divSigmaExp = divSigmaExp =
- fvc::laplacian(mu + lambda, U, "laplacian(DU,U)") - fvc::laplacian(mu + lambda, U, "laplacian(DU,U)")
+ fvc::div + fvc::div(mu*gradU.T() + lambda*(I*tr(gradU)), "div(sigma)");
( }
mu*gradU.T() else
+ lambda*(I*tr(gradU)), {
"div(sigma)" FatalErrorIn(args.executable())
); << "divSigmaExp method " << divSigmaExpMethod << " not found!" << endl;
} }
else
{
FatalError << "divSigmaExp method " << divSigmaExpMethod << " not found!" << endl;
}

View file

@ -1,19 +1,19 @@
{ {
// force residual is the net force on the model // force residual is the net force on the model
// this should got to zero in a converged steady state model // this should got to zero in a converged steady state model
// should be altered for parallel runs // should be altered for parallel runs
vector netForce = vector::zero; vector netForce = vector::zero;
forAll(mesh.boundary(), patchi) forAll(mesh.boundary(), patchi)
{ {
netForce += netForce += sum
sum(
mesh.Sf().boundaryField()[patchi]
&
( (
2*mu.boundaryField()[patchi]*symm(gradU.boundaryField()[patchi]) mesh.Sf().boundaryField()[patchi]
+ lambda*tr(gradU.boundaryField()[patchi])*I &
) (
2*mu.boundaryField()[patchi]*symm(gradU.boundaryField()[patchi])
+ lambda*tr(gradU.boundaryField()[patchi])*I
)
); );
} }
forceResidual = mag(netForce); forceResidual = mag(netForce);
} }

View file

@ -1,22 +1,22 @@
{ {
surfaceVectorField n = mesh.Sf()/mesh.magSf(); surfaceVectorField n = mesh.Sf()/mesh.magSf();
// traction = (n&fvc::interpolate(sigma)); // traction = (n & fvc::interpolate(sigma));
// surfaceTensorField sGradU = // surfaceTensorField sGradU =
// ((I - n*n)&fvc::interpolate(gradU)); // ((I - n*n) & fvc::interpolate(gradU));
// traction = // traction =
// (2*mu + lambda)*snGradU // (2*mu + lambda)*snGradU
// - (mu + lambda)*(snGradU&(I - n*n)) // - (mu + lambda)*(snGradU&(I - n*n))
// + mu*(sGradU&n) // + mu*(sGradU & n)
// + lambda*tr(sGradU&(I - n*n))*n; // + lambda*tr(sGradU&(I - n*n))*n;
// traction = // traction =
// (2*mu + lambda)*fvc::snGrad(U) // (2*mu + lambda)*fvc::snGrad(U)
// - (mu + lambda)*(n&sGradU) // - (mu + lambda)*(n & sGradU)
// + mu*(sGradU&n) // + mu*(sGradU & n)
// + lambda*tr(sGradU)*n; // + lambda*tr(sGradU)*n;
// philipc // philipc
// I am having trouble with back-calculation of interface tractions from solid interface // I am having trouble with back-calculation of interface tractions from solid interface
@ -27,15 +27,15 @@
traction = (n&fvc::interpolate(sigma)); traction = (n&fvc::interpolate(sigma));
// forAll(traction.boundaryField(), patchi) // forAll(traction.boundaryField(), patchi)
// { // {
// if (mesh.boundary()[patchi].type() == "cohesive") // if (mesh.boundary()[patchi].type() == "cohesive")
// { // {
// forAll(traction.boundaryField()[patchi], facei) // forAll(traction.boundaryField()[patchi], facei)
// { // {
// Pout << "face " << facei << " with traction magnitude " // Pout << "face " << facei << " with traction magnitude "
// << mag(traction.boundaryField()[patchi][facei])/1e6 << " MPa and traction " // << mag(traction.boundaryField()[patchi][facei])/1e6 << " MPa and traction "
// << traction.boundaryField()[patchi][facei]/1e6 << " MPa" << endl; // << traction.boundaryField()[patchi][facei]/1e6 << " MPa" << endl;
// } // }
// } // }
// } // }
} }

View file

@ -1,54 +1,53 @@
label cohesivePatchID = -1; label cohesivePatchID = -1;
solidCohesiveFvPatchVectorField* cohesivePatchUPtr = NULL; solidCohesiveFvPatchVectorField* cohesivePatchUPtr = NULL;
solidCohesiveFixedModeMixFvPatchVectorField* cohesivePatchUFixedModePtr = NULL; solidCohesiveFixedModeMixFvPatchVectorField* cohesivePatchUFixedModePtr = NULL;
forAll (U.boundaryField(), patchI) forAll (U.boundaryField(), patchI)
{ {
if (isA<solidCohesiveFvPatchVectorField>(U.boundaryField()[patchI])) if (isA<solidCohesiveFvPatchVectorField>(U.boundaryField()[patchI]))
{ {
cohesivePatchID = patchI; cohesivePatchID = patchI;
cohesivePatchUPtr = cohesivePatchUPtr =
&refCast<solidCohesiveFvPatchVectorField> &refCast<solidCohesiveFvPatchVectorField>
( (
U.boundaryField()[cohesivePatchID] U.boundaryField()[cohesivePatchID]
); );
break; break;
}
else if (isA<solidCohesiveFixedModeMixFvPatchVectorField>(U.boundaryField()[patchI]))
{
cohesivePatchID = patchI;
cohesivePatchUFixedModePtr =
&refCast<solidCohesiveFixedModeMixFvPatchVectorField>
(
U.boundaryField()[cohesivePatchID]
);
break;
} }
else if (isA<solidCohesiveFixedModeMixFvPatchVectorField>(U.boundaryField()[patchI]))
{
cohesivePatchID = patchI;
cohesivePatchUFixedModePtr =
&refCast<solidCohesiveFixedModeMixFvPatchVectorField>
(
U.boundaryField()[cohesivePatchID]
);
break;
}
} }
if(cohesivePatchID == -1) if(cohesivePatchID == -1)
{ {
FatalErrorIn(args.executable()) FatalErrorIn(args.executable())
<< "Can't find cohesiveLawFvPatch" << nl << "Can't find cohesiveLawFvPatch" << nl
<< "One of the boundary patches in " << U.name() << ".boundaryField() " << "One of the boundary patches in " << U.name() << ".boundaryField() "
<< "should be of type " << solidCohesiveFvPatchVectorField::typeName << "should be of type " << solidCohesiveFvPatchVectorField::typeName
<< "or " << solidCohesiveFixedModeMixFvPatchVectorField::typeName << "or " << solidCohesiveFixedModeMixFvPatchVectorField::typeName
<< abort(FatalError); << abort(FatalError);
} }
// solidCohesiveFvPatchVectorField& cohesivePatchU = // solidCohesiveFvPatchVectorField& cohesivePatchU =
// refCast<solidCohesiveFvPatchVectorField> // refCast<solidCohesiveFvPatchVectorField>
// ( // (
// U.boundaryField()[cohesivePatchID] // U.boundaryField()[cohesivePatchID]
// ); // );
// philipc: I have moved cohesive stuff to constitutiveModel // philipc: I have moved cohesive stuff to constitutiveModel
// cohesiveZone is an index field
// cohesiveZone is an index field // which allows the user to limit the crack to certain areas at runtime
// which allows the user to limit the crack to certain areas at runtime // 1 for faces within cohesiveZone
// 1 for faces within cohesiveZone // 0 for faces outside cohesiveZone
// 0 for faces outside cohesiveZone
surfaceScalarField cohesiveZone surfaceScalarField cohesiveZone
( (
IOobject IOobject
@ -65,85 +64,87 @@
// limit crack to specified boxes // limit crack to specified boxes
{ {
const dictionary& stressControl = const dictionary& stressControl =
mesh.solutionDict().subDict("solidMechanics"); mesh.solutionDict().subDict("solidMechanics");
List<boundBox> userBoxes(stressControl.lookup("crackLimitingBoxes")); List<boundBox> userBoxes(stressControl.lookup("crackLimitingBoxes"));
const surfaceVectorField& Cf = mesh.Cf(); const surfaceVectorField& Cf = mesh.Cf();
forAll(cohesiveZone.internalField(), faceI) forAll(cohesiveZone.internalField(), faceI)
{
bool faceInsideBox = false;
forAll(userBoxes, boxi)
{ {
if(userBoxes[boxi].contains(Cf.internalField()[faceI])) faceInsideBox = true; bool faceInsideBox = false;
}
if(faceInsideBox) forAll(userBoxes, boxi)
{
cohesiveZone.internalField()[faceI] = 1.0;
}
}
forAll(cohesiveZone.boundaryField(), patchI)
{
// cracks may go along proc boundaries
if(mesh.boundaryMesh()[patchI].type() == processorPolyPatch::typeName)
{
forAll(cohesiveZone.boundaryField()[patchI], faceI)
{
bool faceInsideBox = false;
forAll(userBoxes, boxi)
{ {
if(userBoxes[boxi].contains(Cf.boundaryField()[patchI][faceI])) faceInsideBox = true; if(userBoxes[boxi].contains(Cf.internalField()[faceI])) faceInsideBox = true;
} }
if(faceInsideBox) if(faceInsideBox)
{ {
cohesiveZone.boundaryField()[patchI][faceI] = 1.0; cohesiveZone.internalField()[faceI] = 1.0;
} }
} }
}
}
Info << "\nThere are " << gSum(cohesiveZone.internalField()) << " potential internal crack faces" << nl << endl; forAll(cohesiveZone.boundaryField(), patchI)
Info << "\nThere are " << gSum(cohesiveZone.boundaryField())/2 << " potential coupled boundary crack faces" << nl << endl; {
// cracks may go along proc boundaries
if(mesh.boundaryMesh()[patchI].type() == processorPolyPatch::typeName)
{
forAll(cohesiveZone.boundaryField()[patchI], faceI)
{
bool faceInsideBox = false;
// write field for visualisation forAll(userBoxes, boxi)
volScalarField cohesiveZoneVol {
( if(userBoxes[boxi].contains(Cf.boundaryField()[patchI][faceI])) faceInsideBox = true;
IOobject }
(
"cohesiveZoneVol", if(faceInsideBox)
runTime.timeName(), {
mesh, cohesiveZone.boundaryField()[patchI][faceI] = 1.0;
IOobject::NO_READ, }
IOobject::AUTO_WRITE }
), }
mesh,
dimensionedScalar("zero", dimless, 0.0)
);
forAll(cohesiveZone.internalField(), facei)
{
if(cohesiveZone.internalField()[facei])
{
cohesiveZoneVol.internalField()[mesh.owner()[facei]] = 1.0;
cohesiveZoneVol.internalField()[mesh.neighbour()[facei]] = 1.0;
} }
}
forAll(cohesiveZone.boundaryField(), patchi) Info << "\nThere are " << gSum(cohesiveZone.internalField()) << " potential internal crack faces" << nl << endl;
{ Info << "\nThere are " << gSum(cohesiveZone.boundaryField())/2 << " potential coupled boundary crack faces" << nl << endl;
forAll(cohesiveZone.boundaryField()[patchi], facei)
// write field for visualisation
volScalarField cohesiveZoneVol
(
IOobject
(
"cohesiveZoneVol",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0)
);
forAll(cohesiveZone.internalField(), facei)
{ {
if(cohesiveZone.boundaryField()[patchi][facei] > 0.0) if(cohesiveZone.internalField()[facei])
{
cohesiveZoneVol.internalField()[mesh.owner()[facei]] = 1.0;
cohesiveZoneVol.internalField()[mesh.neighbour()[facei]] = 1.0;
}
}
forAll(cohesiveZone.boundaryField(), patchi)
{ {
cohesiveZoneVol.boundaryField()[patchi][facei] = 1.0; forAll(cohesiveZone.boundaryField()[patchi], facei)
{
if(cohesiveZone.boundaryField()[patchi][facei] > 0.0)
{
cohesiveZoneVol.boundaryField()[patchi][facei] = 1.0;
}
}
} }
} Info << "Writing cohesiveZone field" << endl;
} cohesiveZoneVol.write();
Info << "Writing cohesiveZone field" << endl;
cohesiveZoneVol.write();
} }

View file

@ -35,8 +35,8 @@
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimless, vector::zero) dimensionedVector("zero", dimless, vector::zero)
); );
volVectorField V volVectorField V
@ -122,7 +122,7 @@
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimLength, vector::zero) dimensionedVector("zero", dimLength, vector::zero)
); );
// aitken relaxation factor // aitken relaxation factor
scalar aitkenInitialRes = 1.0; scalar aitkenInitialRes = 1.0;
@ -140,5 +140,5 @@ scalar aitkenTheta = 0.1;
// IOobject::AUTO_WRITE // IOobject::AUTO_WRITE
// ), // ),
// mesh, // mesh,
// dimensionedVector("zero", dimless, vector::zero) // dimensionedVector("zero", dimless, vector::zero)
// ); // );

View file

@ -1,14 +1,14 @@
OFstream * filePtr(NULL); OFstream* filePtr(NULL);
word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch")); word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch"));
label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName); label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName);
if(historyPatchID == -1) if(historyPatchID == -1)
{ {
Warning << "history patch " << historyPatchName Warning << "history patch " << historyPatchName
<< " not found. Force-displacement will not be written" << " not found. Force-displacement will not be written"
<< endl; << endl;
} }
else if(Pstream::master()) else if(Pstream::master())
{ {
Info << "Force-displacement for patch " << historyPatchName Info << "Force-displacement for patch " << historyPatchName
<< " will be written to forceDisp.dat" << " will be written to forceDisp.dat"
<< endl; << endl;
@ -17,4 +17,4 @@ if(historyPatchID == -1)
filePtr = new OFstream(hisDirName/historyPatchName+"forceDisp.dat"); filePtr = new OFstream(hisDirName/historyPatchName+"forceDisp.dat");
OFstream& forceDispFile = *filePtr; OFstream& forceDispFile = *filePtr;
forceDispFile << "#Disp(mm)\tForce(N)" << endl; forceDispFile << "#Disp(mm)\tForce(N)" << endl;
} }

View file

@ -54,64 +54,64 @@ Author
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
# include "setRootCase.H" # include "setRootCase.H"
# include "createTime.H" # include "createTime.H"
# include "createCrackerMesh.H" # include "createCrackerMesh.H"
# include "createFields.H" # include "createFields.H"
# include "createCrack.H" # include "createCrack.H"
//# include "createReference.H" //# include "createReference.H"
# include "createHistory.H" # include "createHistory.H"
# include "readDivSigmaExpMethod.H" # include "readDivSigmaExpMethod.H"
# include "createSolidInterfaceNoModify.H" # include "createSolidInterfaceNoModify.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl; Info<< "\nStarting time loop\n" << endl;
lduMatrix::debug = 0; lduMatrix::debug = 0;
scalar maxEffTractionFraction = 0; scalar maxEffTractionFraction = 0;
// time rates for predictor // time rates for predictor
volTensorField gradV = fvc::ddt(gradU); volTensorField gradV = fvc::ddt(gradU);
surfaceVectorField snGradV = surfaceVectorField snGradV =
(snGradU - snGradU.oldTime())/runTime.deltaT(); (snGradU - snGradU.oldTime())/runTime.deltaT();
//# include "initialiseSolution.H" //# include "initialiseSolution.H"
while (runTime.run()) while (runTime.run())
{ {
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
# include "setDeltaT.H" # include "setDeltaT.H"
runTime++; runTime++;
Info<< "\nTime: " << runTime.timeName() << " s\n" << endl; Info << "Time = " << runTime.timeName() << nl << endl;
volScalarField rho = rheology.rho(); volScalarField rho = rheology.rho();
volScalarField mu = rheology.mu(); volScalarField mu = rheology.mu();
volScalarField lambda = rheology.lambda(); volScalarField lambda = rheology.lambda();
surfaceScalarField muf = fvc::interpolate(mu); surfaceScalarField muf = fvc::interpolate(mu);
surfaceScalarField lambdaf = fvc::interpolate(lambda); surfaceScalarField lambdaf = fvc::interpolate(lambda);
if (solidInterfaceCorr) if (solidInterfaceCorr)
{ {
solidInterfacePtr->modifyProperties(muf, lambdaf); solidInterfacePtr->modifyProperties(muf, lambdaf);
} }
//# include "waveCourantNo.H" //# include "waveCourantNo.H"
int iCorr = 0; int iCorr = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar initialResidual = 0; scalar initialResidual = 0;
scalar relativeResidual = 1; scalar relativeResidual = 1;
//scalar forceResidual = 1; //scalar forceResidual = 1;
label nFacesToBreak = 0; label nFacesToBreak = 0;
label nCoupledFacesToBreak = 0; label nCoupledFacesToBreak = 0;
bool topoChange = false; bool topoChange = false;
// Predictor step using time rates // Predictor step using time rates
if (predictor) if (predictor)
{ {
Info<< "Predicting U, gradU and snGradU using velocity" Info<< "Predicting U, gradU and snGradU using velocity"
<< endl; << endl;
@ -120,149 +120,148 @@ int main(int argc, char *argv[])
snGradU += snGradV*runTime.deltaT(); snGradU += snGradV*runTime.deltaT();
} }
do do
{ {
surfaceVectorField n = mesh.Sf()/mesh.magSf(); surfaceVectorField n = mesh.Sf()/mesh.magSf();
do do
{ {
U.storePrevIter(); U.storePrevIter();
# include "calculateDivSigmaExp.H" # include "calculateDivSigmaExp.H"
fvVectorMatrix UEqn fvVectorMatrix UEqn
( (
rho*fvm::d2dt2(U) rho*fvm::d2dt2(U)
== ==
fvm::laplacian(2*muf + lambdaf, U, "laplacian(DU,U)") fvm::laplacian(2*muf + lambdaf, U, "laplacian(DU,U)")
+ divSigmaExp + divSigmaExp
); );
//# include "setReference.H" //# include "setReference.H"
if (solidInterfaceCorr) if(solidInterfaceCorr)
{ {
solidInterfacePtr->correct(UEqn); solidInterfacePtr->correct(UEqn);
} }
if (relaxEqn) if (relaxEqn)
{ {
UEqn.relax(); UEqn.relax();
} }
solverPerf = UEqn.solve(); solverPerf = UEqn.solve();
if (aitkenRelax) if (aitkenRelax)
{ {
# include "aitkenRelaxation.H" # include "aitkenRelaxation.H"
} }
else else
{ {
U.relax(); U.relax();
} }
if (iCorr == 0) if (iCorr == 0)
{ {
initialResidual = solverPerf.initialResidual(); initialResidual = solverPerf.initialResidual();
aitkenInitialRes = gMax(mag(U.internalField())); aitkenInitialRes = gMax(mag(U.internalField()));
} }
//gradU = solidInterfacePtr->grad(U); //gradU = solidInterfacePtr->grad(U);
// use leastSquaresSolidInterface grad scheme // use leastSquaresSolidInterface grad scheme
gradU = fvc::grad(U); gradU = fvc::grad(U);
# include "calculateRelativeResidual.H" # include "calculateRelativeResidual.H"
//# include "calculateForceResidual.H" //# include "calculateForceResidual.H"
if (iCorr % infoFrequency == 0) if (iCorr % infoFrequency == 0)
{ {
Info << "\tTime " << runTime.value() Info<< "\tTime " << runTime.value()
<< ", Corr " << iCorr << ", Corr " << iCorr
<< ", Solving for " << U.name() << ", Solving for " << U.name()
<< " using " << solverPerf.solverName() << " using " << solverPerf.solverName()
<< ", res = " << solverPerf.initialResidual() << ", res = " << solverPerf.initialResidual()
<< ", rel res = " << relativeResidual; << ", rel res = " << relativeResidual;
if (aitkenRelax) if (aitkenRelax)
{ {
Info << ", aitken = " << aitkenTheta; Info << ", aitken = " << aitkenTheta;
} }
Info << ", inner iters " << solverPerf.nIterations() << endl; Info << ", inner iters " << solverPerf.nIterations() << endl;
} }
} }
while while
( (
//iCorr++ == 0 //iCorr++ == 0
iCorr++ < 2 iCorr++ < 2
|| ||
( (
solverPerf.initialResidual() > convergenceTolerance solverPerf.initialResidual() > convergenceTolerance
//relativeResidual > convergenceTolerance //relativeResidual > convergenceTolerance
&& && iCorr < nCorr
iCorr < nCorr )
) );
);
Info << "Solving for " << U.name() << " using " Info<< "Solving for " << U.name() << " using "
<< solverPerf.solverName() << solverPerf.solverName()
<< ", Initial residual = " << initialResidual << ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual() << ", Final residual = " << solverPerf.initialResidual()
<< ", No outer iterations " << iCorr << ", No outer iterations " << iCorr
<< ", Relative residual " << relativeResidual << endl; << ", Relative residual " << relativeResidual << endl;
# include "calculateTraction.H" # include "calculateTraction.H"
# include "updateCrack.H" # include "updateCrack.H"
Info<< "Max effective traction fraction: " Info<< "Max effective traction fraction: "
<< maxEffTractionFraction << endl; << maxEffTractionFraction << endl;
// reset counter if faces want to crack // reset counter if faces want to crack
if ((nFacesToBreak > 0) || (nCoupledFacesToBreak > 0)) iCorr = 0; if ((nFacesToBreak > 0) || (nCoupledFacesToBreak > 0)) iCorr = 0;
} }
while( (nFacesToBreak > 0) || (nCoupledFacesToBreak > 0)); while( (nFacesToBreak > 0) || (nCoupledFacesToBreak > 0));
if (cohesivePatchUPtr) if (cohesivePatchUPtr)
{ {
if (returnReduce(cohesivePatchUPtr->size(), sumOp<label>())) if (returnReduce(cohesivePatchUPtr->size(), sumOp<label>()))
{ {
cohesivePatchUPtr->cracking(); cohesivePatchUPtr->cracking();
} }
} }
else else
{ {
if if
( (
returnReduce returnReduce
( (
cohesivePatchUFixedModePtr->size(), cohesivePatchUFixedModePtr->size(),
sumOp<label>() sumOp<label>()
) )
) )
{ {
Pout << "Number of faces in crack: " Pout << "Number of faces in crack: "
<< cohesivePatchUFixedModePtr->size() << endl; << cohesivePatchUFixedModePtr->size() << endl;
cohesivePatchUFixedModePtr->relativeSeparationDistance(); cohesivePatchUFixedModePtr->relativeSeparationDistance();
} }
} }
// update time rates for predictor // update time rates for predictor
if (predictor) if (predictor)
{ {
V = fvc::ddt(U); V = fvc::ddt(U);
gradV = fvc::ddt(gradU); gradV = fvc::ddt(gradU);
snGradV = (snGradU - snGradU.oldTime())/runTime.deltaT(); snGradV = (snGradU - snGradU.oldTime())/runTime.deltaT();
} }
# include "calculateEpsilonSigma.H" # include "calculateEpsilonSigma.H"
# include "writeFields.H" # include "writeFields.H"
# include "writeHistory.H" # include "writeHistory.H"
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s\n\n" << " ClockTime = " << runTime.elapsedClockTime() << " s\n\n"
<< endl; << endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;
return(0); return(0);
} }

View file

@ -2,8 +2,8 @@
word divSigmaExpMethod(mesh.solutionDict().subDict("solidMechanics").lookup("divSigmaExp")); word divSigmaExpMethod(mesh.solutionDict().subDict("solidMechanics").lookup("divSigmaExp"));
Info << "Selecting divSigmaExp calculation method " << divSigmaExpMethod << endl; Info << "Selecting divSigmaExp calculation method " << divSigmaExpMethod << endl;
if(divSigmaExpMethod != "standard" && divSigmaExpMethod != "surface" && divSigmaExpMethod != "decompose" && divSigmaExpMethod != "laplacian") if(divSigmaExpMethod != "standard" && divSigmaExpMethod != "surface" && divSigmaExpMethod != "decompose" && divSigmaExpMethod != "laplacian")
{ {
FatalError << "divSigmaExp method " << divSigmaExpMethod << " not found!" << nl FatalError << "divSigmaExp method " << divSigmaExpMethod << " not found!" << nl
<< "valid methods are:\nstandard\nsurface\ndecompose\nlaplacian" << "valid methods are:\nstandard\nsurface\ndecompose\nlaplacian"
<< exit(FatalError); << exit(FatalError);
} }

View file

@ -1,36 +1,36 @@
if (dynamicTimeStep && runTime.value() > dynamicTimeStepActivation) if (dynamicTimeStep && runTime.value() > dynamicTimeStepActivation)
{ {
if if
( (
//(maxEffTraction < 0.999*CzLaw.sigmaMax().value()) //(maxEffTraction < 0.999*CzLaw.sigmaMax().value())
(returnReduce(maxEffTractionFraction, maxOp<scalar>()) < 0.99) (returnReduce(maxEffTractionFraction, maxOp<scalar>()) < 0.99)
//&& (cohesivePatchU.size() == 0) //&& (cohesivePatchU.size() == 0)
&& (mag(runTime.deltaT().value() - deltaTmax) < SMALL) && (mag(runTime.deltaT().value() - deltaTmax) < SMALL)
) )
{ {
runTime.setDeltaT(deltaTmax); runTime.setDeltaT(deltaTmax);
} }
else else
{ {
scalar newDeltaT = deltaTmin; scalar newDeltaT = deltaTmin;
if (newDeltaT/runTime.deltaT().value() < 0.5) if (newDeltaT/runTime.deltaT().value() < 0.5)
{ {
newDeltaT = 0.5*runTime.deltaT().value(); newDeltaT = 0.5*runTime.deltaT().value();
Info << "Reducing time step" << nl; Info << "Reducing time step" << nl;
} }
runTime.setDeltaT(newDeltaT); runTime.setDeltaT(newDeltaT);
} }
Pout << "Current time step size: " Pout << "Current time step size: "
<< runTime.deltaT().value() << " s" << endl; << runTime.deltaT().value() << " s" << endl;
scalar maxDT = runTime.deltaT().value(); scalar maxDT = runTime.deltaT().value();
if(mag(returnReduce(maxDT, maxOp<scalar>()) - runTime.deltaT().value()) > SMALL) if(mag(returnReduce(maxDT, maxOp<scalar>()) - runTime.deltaT().value()) > SMALL)
{ {
FatalError << "Processors have different time-steps!" FatalError << "Processors have different time-steps!"
<< exit(FatalError); << exit(FatalError);
} }
} }

View file

@ -13,7 +13,7 @@ nCoupledFacesToBreak = 0;
// only consider tensile tractions // only consider tensile tractions
normalTraction = max(normalTraction, scalar(0)); normalTraction = max(normalTraction, scalar(0));
scalarField shearTraction = scalarField shearTraction =
cohesiveZone.internalField() * cohesiveZone.internalField()*
mag( (I - Foam::sqr(n.internalField())) & traction.internalField() ); mag( (I - Foam::sqr(n.internalField())) & traction.internalField() );
// the traction fraction is monitored to decide which faces to break: // the traction fraction is monitored to decide which faces to break:
@ -41,6 +41,7 @@ nCoupledFacesToBreak = 0;
(normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI) (normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI)
+ (shearTraction/sigmaMaxI)*(shearTraction/sigmaMaxI); + (shearTraction/sigmaMaxI)*(shearTraction/sigmaMaxI);
} }
maxEffTractionFraction = gMax(effTractionFraction); maxEffTractionFraction = gMax(effTractionFraction);
SLList<label> facesToBreakList; SLList<label> facesToBreakList;
@ -77,9 +78,14 @@ nCoupledFacesToBreak = 0;
scalar faceToBreakEffTractionFraction = 0; scalar faceToBreakEffTractionFraction = 0;
forAll(facesToBreakEffTractionFraction, faceI) forAll(facesToBreakEffTractionFraction, faceI)
{ {
if (facesToBreakEffTractionFraction[faceI] > faceToBreakEffTractionFraction) if
(
facesToBreakEffTractionFraction[faceI]
> faceToBreakEffTractionFraction
)
{ {
faceToBreakEffTractionFraction = facesToBreakEffTractionFraction[faceI]; faceToBreakEffTractionFraction =
facesToBreakEffTractionFraction[faceI];
faceToBreakIndex = facesToBreak[faceI]; faceToBreakIndex = facesToBreak[faceI];
} }
} }
@ -92,7 +98,11 @@ nCoupledFacesToBreak = 0;
bool procHasFaceToBreak = false; bool procHasFaceToBreak = false;
if (nFacesToBreak > 0) if (nFacesToBreak > 0)
{ {
if ( mag(gMaxEffTractionFraction - faceToBreakEffTractionFraction) < SMALL ) if
(
mag(gMaxEffTractionFraction - faceToBreakEffTractionFraction)
< SMALL
)
{ {
// philipc - Maximum traction fraction is on this processor // philipc - Maximum traction fraction is on this processor
procHasFaceToBreak = true; procHasFaceToBreak = true;
@ -100,7 +110,7 @@ nCoupledFacesToBreak = 0;
} }
// Check if maximum is present on more then one processors // Check if maximum is present on more then one processors
label procID = Pstream::nProcs(); label procID = Pstream::nProcs();
if (procHasFaceToBreak) if (procHasFaceToBreak)
{ {
procID = Pstream::myProcNo(); procID = Pstream::myProcNo();
@ -125,46 +135,51 @@ nCoupledFacesToBreak = 0;
if (mesh.boundary()[patchI].coupled()) if (mesh.boundary()[patchI].coupled())
{ {
// scalarField pEffTraction = // scalarField pEffTraction =
// cohesiveZone.boundaryField()[patchI] * // cohesiveZone.boundaryField()[patchI]*
// mag(traction.boundaryField()[patchI]); // mag(traction.boundaryField()[patchI]);
// scalarField pEffTractionFraction = pEffTraction/sigmaMax.boundaryField()[patchI]; // scalarField pEffTractionFraction = pEffTraction/sigmaMax.boundaryField()[patchI];
scalarField pNormalTraction = scalarField pNormalTraction =
cohesiveZone.boundaryField()[patchI] * cohesiveZone.boundaryField()[patchI]*
( n.boundaryField()[patchI] & traction.boundaryField()[patchI] ); ( n.boundaryField()[patchI] & traction.boundaryField()[patchI] );
pNormalTraction = max(pNormalTraction, scalar(0)); // only consider tensile tractions
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: // only consider tensile tractions
// ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face pNormalTraction = max(pNormalTraction, scalar(0));
const scalarField& pSigmaMax = sigmaMax.boundaryField()[patchI];
const scalarField& pTauMax = tauMax.boundaryField()[patchI];
scalarField pEffTractionFraction(pNormalTraction.size(), 0.0); scalarField pShearTraction =
if(cohesivePatchUPtr) cohesiveZone.boundaryField()[patchI]*
{ mag( (I - Foam::sqr(n.boundaryField()[patchI])) & traction.boundaryField()[patchI] );
pEffTractionFraction =
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) + (pShearTraction/pTauMax)*(pShearTraction/pTauMax); // the traction fraction is monitored to decide which faces to break:
} // ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face
else const scalarField& pSigmaMax = sigmaMax.boundaryField()[patchI];
{ const scalarField& pTauMax = tauMax.boundaryField()[patchI];
// solidCohesiveFixedModeMix only uses sigmaMax
pEffTractionFraction = scalarField pEffTractionFraction(pNormalTraction.size(), 0.0);
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) + (pShearTraction/pSigmaMax)*(pShearTraction/pSigmaMax); if(cohesivePatchUPtr)
} {
pEffTractionFraction =
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
+ (pShearTraction/pTauMax)*(pShearTraction/pTauMax);
}
else
{
// solidCohesiveFixedModeMix only uses sigmaMax
pEffTractionFraction =
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
+ (pShearTraction/pSigmaMax)*(pShearTraction/pSigmaMax);
}
label start = mesh.boundaryMesh()[patchI].start(); label start = mesh.boundaryMesh()[patchI].start();
forAll(pEffTractionFraction, faceI) forAll(pEffTractionFraction, faceI)
{ {
if (pEffTractionFraction[faceI] > maxEffTractionFraction) if (pEffTractionFraction[faceI] > maxEffTractionFraction)
{ {
maxEffTractionFraction = pEffTractionFraction[faceI]; maxEffTractionFraction = pEffTractionFraction[faceI];
} }
if (pEffTractionFraction[faceI] > 1.0) if (pEffTractionFraction[faceI] > 1.0)
{ {
coupledFacesToBreakList.insert(start + faceI); coupledFacesToBreakList.insert(start + faceI);
coupledFacesToBreakEffTractionFractionList.insert coupledFacesToBreakEffTractionFractionList.insert
@ -259,8 +274,8 @@ nCoupledFacesToBreak = 0;
labelList index(Pstream::nProcs(), -1); labelList index(Pstream::nProcs(), -1);
if (nCoupledFacesToBreak) if (nCoupledFacesToBreak)
{ {
label patchID = label patchID =
mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex); mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex);
label start = mesh.boundaryMesh()[patchID].start(); label start = mesh.boundaryMesh()[patchID].start();
label localIndex = coupledFaceToBreakIndex - start; label localIndex = coupledFaceToBreakIndex - start;
@ -318,6 +333,7 @@ nCoupledFacesToBreak = 0;
vector faceToBreakNormal = vector::zero; vector faceToBreakNormal = vector::zero;
scalar faceToBreakSigmaMax = 0.0; scalar faceToBreakSigmaMax = 0.0;
scalar faceToBreakTauMax = 0.0; scalar faceToBreakTauMax = 0.0;
// Set faces to break // Set faces to break
if (nFacesToBreak > 0) if (nFacesToBreak > 0)
{ {
@ -325,31 +341,39 @@ nCoupledFacesToBreak = 0;
faceToBreakNormal = n.internalField()[faceToBreakIndex]; faceToBreakNormal = n.internalField()[faceToBreakIndex];
// Scale broken face traction // Scale broken face traction
faceToBreakSigmaMax = sigmaMaxI[faceToBreakIndex]; faceToBreakSigmaMax = sigmaMaxI[faceToBreakIndex];
faceToBreakTauMax = tauMaxI[faceToBreakIndex]; faceToBreakTauMax = tauMaxI[faceToBreakIndex];
scalar normalTrac = faceToBreakNormal & faceToBreakTraction; scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
normalTrac = max(normalTrac, 0.0); normalTrac = max(normalTrac, 0.0);
scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction ); scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
scalar scaleFactor = 1; scalar scaleFactor = 1;
if(cohesivePatchUPtr) if(cohesivePatchUPtr)
{
scaleFactor =
::sqrt(1 / (
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
) );
}
else
{ {
// solidCohesiveFixedModeMix only uses sigmaMax scaleFactor =
scaleFactor = Foam::sqrt
::sqrt(1 / ( (
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax) 1 /
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax) (
) ); (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
)
);
}
else
{
// solidCohesiveFixedModeMix only uses sigmaMax
scaleFactor =
Foam::sqrt
(
1 /
(
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
)
);
} }
faceToBreakTraction *= scaleFactor; faceToBreakTraction *= scaleFactor;
topoChange = true; topoChange = true;
} }
@ -364,29 +388,37 @@ nCoupledFacesToBreak = 0;
faceToBreakNormal = n.boundaryField()[patchID][localIndex]; faceToBreakNormal = n.boundaryField()[patchID][localIndex];
// Scale broken face traction // Scale broken face traction
faceToBreakSigmaMax = sigmaMax.boundaryField()[patchID][localIndex]; faceToBreakSigmaMax = sigmaMax.boundaryField()[patchID][localIndex];
faceToBreakTauMax = tauMax.boundaryField()[patchID][localIndex]; faceToBreakTauMax = tauMax.boundaryField()[patchID][localIndex];
scalar normalTrac = faceToBreakNormal & faceToBreakTraction; scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
normalTrac = max(normalTrac, 0.0); normalTrac = max(normalTrac, 0.0);
scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction ); scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
scalar scaleFactor = 1; scalar scaleFactor = 1;
if(cohesivePatchUPtr) if(cohesivePatchUPtr)
{ {
scaleFactor = scaleFactor =
::sqrt(1 / ( Foam::sqrt
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax) (
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax) 1 /
) ); (
} (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
else + (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
{ )
// solidCohesiveFixedModeMix only uses sigmaMax );
scaleFactor = }
::sqrt(1 / ( else
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax) {
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax) // solidCohesiveFixedModeMix only uses sigmaMax
) ); scaleFactor =
} Foam::sqrt
(
1 /
(
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
)
);
}
faceToBreakTraction *= scaleFactor; faceToBreakTraction *= scaleFactor;
@ -422,20 +454,20 @@ nCoupledFacesToBreak = 0;
muf = fvc::interpolate(mu); muf = fvc::interpolate(mu);
lambdaf = fvc::interpolate(lambda); lambdaf = fvc::interpolate(lambda);
// we need to modify propertiess after cracking otherwise momentum equation is wrong // we need to modify propertiess after cracking otherwise momentum equation is wrong
// but solidInterface seems to hold some information about old mesh // but solidInterface seems to hold some information about old mesh
// so we will delete it and make another // so we will delete it and make another
// we could probably add a public clearout function // we could probably add a public clearout function
// create new solidInterface // create new solidInterface
//Pout << "Creating new solidInterface" << endl; //Pout << "Creating new solidInterface" << endl;
//delete solidInterfacePtr; //delete solidInterfacePtr;
//solidInterfacePtr = new solidInterface(mesh, rheology); //solidInterfacePtr = new solidInterface(mesh, rheology);
// delete demand driven data as the mesh has changed // delete demand driven data as the mesh has changed
if(rheology.solidInterfaceActive()) if(rheology.solidInterfaceActive())
{ {
rheology.solInterface().clearOut(); rheology.solInterface().clearOut();
solidInterfacePtr->modifyProperties(muf, lambdaf); solidInterfacePtr->modifyProperties(muf, lambdaf);
} }
// Local crack displacement // Local crack displacement
vectorField UpI = vectorField UpI =
@ -447,21 +479,21 @@ nCoupledFacesToBreak = 0;
vectorField globalUpI = mesh.globalCrackField(UpI); vectorField globalUpI = mesh.globalCrackField(UpI);
vectorField globalOldUpI = mesh.globalCrackField(oldUpI); vectorField globalOldUpI = mesh.globalCrackField(oldUpI);
// mu and lambda field on new crack faces must be updated // mu and lambda field on new crack faces must be updated
scalarField muPI = mu.boundaryField()[cohesivePatchID].patchInternalField(); scalarField muPI = mu.boundaryField()[cohesivePatchID].patchInternalField();
scalarField lambdaPI = lambda.boundaryField()[cohesivePatchID].patchInternalField(); scalarField lambdaPI = lambda.boundaryField()[cohesivePatchID].patchInternalField();
scalarField globalMuPI = mesh.globalCrackField(muPI); scalarField globalMuPI = mesh.globalCrackField(muPI);
scalarField globalLambdaPI = mesh.globalCrackField(lambdaPI); scalarField globalLambdaPI = mesh.globalCrackField(lambdaPI);
// cohesivePatchU.size() // cohesivePatchU.size()
int cohesivePatchSize(cohesivePatchUPtr ? cohesivePatchUPtr->size() : cohesivePatchUFixedModePtr->size()); int cohesivePatchSize(cohesivePatchUPtr ? cohesivePatchUPtr->size() : cohesivePatchUFixedModePtr->size());
// Initialise U for new cohesive face // Initialise U for new cohesive face
const labelList& gcfa = mesh.globalCrackFaceAddressing(); const labelList& gcfa = mesh.globalCrackFaceAddressing();
label globalIndex = mesh.localCrackStart(); label globalIndex = mesh.localCrackStart();
// for (label i=0; i<cohesivePatchU.size(); i++) // for (label i=0; i<cohesivePatchU.size(); i++)
for (label i=0; i<cohesivePatchSize; i++) for (label i=0; i<cohesivePatchSize; i++)
{ {
label oldFaceIndex = faceMap[start+i]; label oldFaceIndex = faceMap[start+i];
// If new face // If new face
@ -480,10 +512,10 @@ nCoupledFacesToBreak = 0;
+ globalOldUpI[gcfa[globalIndex]] + globalOldUpI[gcfa[globalIndex]]
); );
// initialise mu and lambda on new faces // initialise mu and lambda on new faces
// set new face value to value of internal cell // set new face value to value of internal cell
muf.boundaryField()[cohesivePatchID][i] = globalMuPI[globalIndex]; muf.boundaryField()[cohesivePatchID][i] = globalMuPI[globalIndex];
lambdaf.boundaryField()[cohesivePatchID][i] = globalLambdaPI[globalIndex]; lambdaf.boundaryField()[cohesivePatchID][i] = globalLambdaPI[globalIndex];
globalIndex++; globalIndex++;
} }
@ -494,24 +526,24 @@ nCoupledFacesToBreak = 0;
} }
// we must calculate grad using interface // we must calculate grad using interface
// U at the interface has not been calculated yet as interface.correct() // U at the interface has not been calculated yet as interface.correct()
// has not been called yet // has not been called yet
// not really a problem as gradU is correct in second outer iteration // not really a problem as gradU is correct in second outer iteration
// as long as this does not cause convergence problems for the first iterations. // as long as this does not cause convergence problems for the first iterations.
// we should be able to calculate the interface displacements without // we should be able to calculate the interface displacements without
// having to call interface.correct() // having to call interface.correct()
// todo: add calculateInterfaceU() function // todo: add calculateInterfaceU() function
// interface grad uses Gauss, we need least squares // interface grad uses Gauss, we need least squares
//gradU = solidInterfacePtr->grad(U); //gradU = solidInterfacePtr->grad(U);
gradU = fvc::grad(U); // leastSquaresSolidInterface grad scheme gradU = fvc::grad(U); // leastSquaresSolidInterface grad scheme
//snGradU = fvc::snGrad(U); //snGradU = fvc::snGrad(U);
# include "calculateTraction.H" # include "calculateTraction.H"
//if (nFacesToBreak || nCoupledFacesToBreak) mesh.write(); traction.write(); //if (nFacesToBreak || nCoupledFacesToBreak) mesh.write(); traction.write();
// Initialise initiation traction for new cohesive patch face // Initialise initiation traction for new cohesive patch face
// for (label i=0; i<cohesivePatchU.size(); i++) // for (label i=0; i<cohesivePatchU.size(); i++)
for (label i=0; i<cohesivePatchSize; i++) for (label i=0; i<cohesivePatchSize; i++)
{ {
label oldFaceIndex = faceMap[start+i]; label oldFaceIndex = faceMap[start+i];
@ -527,48 +559,49 @@ nCoupledFacesToBreak = 0;
/mesh.magSf().boundaryField()[cohesivePatchID][i]; /mesh.magSf().boundaryField()[cohesivePatchID][i];
//vector n1 = -n0; //vector n1 = -n0;
if ((n0&faceToBreakNormal) > SMALL) if ((n0 & faceToBreakNormal) > SMALL)
{ {
traction.boundaryField()[cohesivePatchID][i] = traction.boundaryField()[cohesivePatchID][i] =
faceToBreakTraction; faceToBreakTraction;
traction.oldTime().boundaryField()[cohesivePatchID][i] = traction.oldTime().boundaryField()[cohesivePatchID][i] =
faceToBreakTraction; faceToBreakTraction;
if(cohesivePatchUPtr) if(cohesivePatchUPtr)
{ {
cohesivePatchUPtr->traction()[i] = faceToBreakTraction; cohesivePatchUPtr->traction()[i] = faceToBreakTraction;
} }
else else
{ {
cohesivePatchUFixedModePtr->traction()[i] = faceToBreakTraction; cohesivePatchUFixedModePtr->traction()[i] = faceToBreakTraction;
cohesivePatchUFixedModePtr->initiationTraction()[i] = faceToBreakTraction; cohesivePatchUFixedModePtr->initiationTraction()[i] = faceToBreakTraction;
} }
} }
else else
{ {
traction.boundaryField()[cohesivePatchID][i] = traction.boundaryField()[cohesivePatchID][i] =
-faceToBreakTraction; -faceToBreakTraction;
traction.oldTime().boundaryField()[cohesivePatchID][i] =
-faceToBreakTraction;
traction.oldTime().boundaryField()[cohesivePatchID][i] = //cohesivePatchU.traction()[i] = -faceToBreakTraction;
-faceToBreakTraction; if(cohesivePatchUPtr)
{
//cohesivePatchU.traction()[i] = -faceToBreakTraction; cohesivePatchUPtr->traction()[i] = -faceToBreakTraction;
if(cohesivePatchUPtr) }
{ else
cohesivePatchUPtr->traction()[i] = -faceToBreakTraction; {
} cohesivePatchUFixedModePtr->traction()[i] =
else -faceToBreakTraction;
{ cohesivePatchUFixedModePtr->initiationTraction()[i] =
cohesivePatchUFixedModePtr->traction()[i] = -faceToBreakTraction; -faceToBreakTraction;
cohesivePatchUFixedModePtr->initiationTraction()[i] = -faceToBreakTraction; }
}
} }
} }
} }
// hmmnn we only need a reference for very small groups of cells // hmmnn we only need a reference for very small groups of cells
// turn off for now // turn off for now
//# include "updateReference.H" //# include "updateReference.H"
} }
} }

View file

@ -4,20 +4,21 @@
forAll(U.boundaryField(), patchI) forAll(U.boundaryField(), patchI)
{ {
// philipc - this used to set a reference on // philipc - this used to set a reference on
// processors which did not have a patch that fixesValue // processors which did not have a patch that fixesValue
// so processor in the centre of the domain all had // so processor in the centre of the domain all had
// a referece set causing stress peaks and resulting // a referece set causing stress peaks and resulting
// in an incorrect solution // in an incorrect solution
// so a quick fix is to not set a reference on regions // so a quick fix is to not set a reference on regions
// with a processor boundary // with a processor boundary
//if (U.boundaryField()[patchI].fixesValue()) //if (U.boundaryField()[patchI].fixesValue())
if ( if
U.boundaryField()[patchI].fixesValue() (
|| U.boundaryField()[patchI].fixesValue()
mesh.boundaryMesh()[patchI].type() ||
== processorPolyPatch::typeName mesh.boundaryMesh()[patchI].type()
) == processorPolyPatch::typeName
)
{ {
const unallocLabelList& curFaceCells = const unallocLabelList& curFaceCells =
mesh.boundary()[patchI].faceCells(); mesh.boundary()[patchI].faceCells();

View file

@ -85,62 +85,65 @@ if (runTime.outputTime() || topoChange)
//- cohesive damage and cracking, and GII and GII //- cohesive damage and cracking, and GII and GII
volScalarField damageAndCracks volScalarField damageAndCracks
( (
IOobject IOobject
( (
"damageAndCracks", "damageAndCracks",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedScalar("zero", dimless, 0.0), dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName calculatedFvPatchVectorField::typeName
); );
volScalarField GI
(
IOobject
(
"GI",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName
);
volScalarField GII
(
IOobject
(
"GII",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName
);
forAll(U.boundaryField(), patchi)
{
// if(U.boundaryField()[patchi].type() == cohesiveLawMultiMatFvPatchVectorField::typeName)
if(U.boundaryField()[patchi].type() == solidCohesiveFvPatchVectorField::typeName)
{
// cohesiveLawMultiMatFvPatchVectorField& Upatch =
// refCast<cohesiveLawMultiMatFvPatchVectorField>(U.boundaryField()[patchi]);
solidCohesiveFvPatchVectorField& Upatch =
refCast<solidCohesiveFvPatchVectorField>(U.boundaryField()[patchi]);
GI.boundaryField()[patchi] = Upatch.GI(); volScalarField GI
GII.boundaryField()[patchi] = Upatch.GII(); (
damageAndCracks.boundaryField()[patchi] = Upatch.crackingAndDamage(); IOobject
} (
} "GI",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName
);
volScalarField GII
(
IOobject
(
"GII",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName
);
forAll(U.boundaryField(), patchi)
{
// if(U.boundaryField()[patchi].type() == cohesiveLawMultiMatFvPatchVectorField::typeName)
if(U.boundaryField()[patchi].type() == solidCohesiveFvPatchVectorField::typeName)
{
// cohesiveLawMultiMatFvPatchVectorField& Upatch =
// refCast<cohesiveLawMultiMatFvPatchVectorField>(U.boundaryField()[patchi]);
solidCohesiveFvPatchVectorField& Upatch =
refCast<solidCohesiveFvPatchVectorField>(U.boundaryField()[patchi]);
GI.boundaryField()[patchi] = Upatch.GI();
GII.boundaryField()[patchi] = Upatch.GII();
damageAndCracks.boundaryField()[patchi] = Upatch.crackingAndDamage();
}
}
volScalarField GTotal("GTotal", GI + GII); volScalarField GTotal("GTotal", GI + GII);
GTotal.write(); GTotal.write();

View file

@ -1,35 +1,35 @@
//- write force displacement to file //- write force displacement to file
if(historyPatchID != -1) if(historyPatchID != -1)
{ {
Info << "Writing disp and force of patch "<<historyPatchName<<" to file" Info << "Writing disp and force of patch "<<historyPatchName<<" to file"
<< endl; << endl;
//- for small strain or moving mesh //- for small strain or moving mesh
vector force = gSum(mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID]); vector force = gSum(mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID]);
//- for large strain total lagrangian //- for large strain total lagrangian
// tensorField F = I + gradU.boundaryField()[historyPatchID]; // tensorField F = I + gradU.boundaryField()[historyPatchID];
// vectorField totalForce = mesh.Sf().boundaryField()[historyPatchID] & (sigma.boundaryField()[historyPatchID] & F); // vectorField totalForce = mesh.Sf().boundaryField()[historyPatchID] & (sigma.boundaryField()[historyPatchID] & F);
//vector force = sum( totalForce ); //vector force = sum( totalForce );
//scalar force = force[vector::Y]; //scalar force = force[vector::Y];
//- patchIntegrate utility integrates it this way but this is worng because the sigma tensor should //- patchIntegrate utility integrates it this way but this is worng because the sigma tensor should
//- be dotted with the surface normal to give the actual traction/force //- be dotted with the surface normal to give the actual traction/force
//- you cannot just take the component of the sigma tensor //- you cannot just take the component of the sigma tensor
//scalar forcePatchIntegrateMethod = gSum( //scalar forcePatchIntegrateMethod = gSum(
// mesh.magSf().boundaryField()[historyPatchID] // mesh.magSf().boundaryField()[historyPatchID]*
// *sigma.boundaryField()[historyPatchID].component(symmTensor::XY) // sigma.boundaryField()[historyPatchID].component(symmTensor::XY)
// ); //);
vector avDisp = gAverage(U.boundaryField()[historyPatchID]); vector avDisp = gAverage(U.boundaryField()[historyPatchID]);
//- write to file //- write to file
if(Pstream::master()) if(Pstream::master())
{ {
OFstream& forceDispFile = *filePtr; OFstream& forceDispFile = *filePtr;
forceDispFile << avDisp.x() << " " << avDisp.y() << " " << avDisp.z() << " " forceDispFile << avDisp.x() << " " << avDisp.y() << " " << avDisp.z() << " "
<< force.x() << " " << force.y() << " " << force.z() << endl; << force.x() << " " << force.y() << " " << force.z() << endl;
} }
} }

View file

@ -6,26 +6,24 @@ aitkenDelta = (DU - DU.prevIter()) / aitkenInitialRes;
// update relaxation factor // update relaxation factor
if(iCorr == 0) if(iCorr == 0)
{ {
aitkenTheta = 0.01; aitkenTheta = 0.01;
} }
else else
{ {
vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField(); vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField();
//scalar sumMagB = gSum(mag(b)); //scalar sumMagB = gSum(mag(b));
scalar sumMagB = gSum(magSqr(b)); scalar sumMagB = gSum(magSqr(b));
if(sumMagB < SMALL) if(sumMagB < SMALL)
{ {
//Warning << "Aitken under-relaxation: denominator less then SMALL" //Warning << "Aitken under-relaxation: denominator less then SMALL"
// << endl; // << endl;
sumMagB += SMALL; sumMagB += SMALL;
} }
aitkenTheta = -aitkenTheta* aitkenTheta = -aitkenTheta*
gSum(aitkenDelta.prevIter().internalField() & b) gSum(aitkenDelta.prevIter().internalField() & b)/sumMagB;
/ }
sumMagB;
}
// correction to the latest DU // correction to the latest DU
DU += aitkenTheta*aitkenDelta*aitkenInitialRes; DU += aitkenTheta*aitkenDelta*aitkenInitialRes;

View file

@ -1,49 +1,45 @@
if(divDSigmaExpMethod == "standard") if(divDSigmaExpMethod == "standard")
{ {
divDSigmaExp = fvc::div divDSigmaExp = fvc::div
( (
mu*gradDU.T() + lambda*(I*tr(gradDU)) - (mu + lambda)*gradDU, mu*gradDU.T() + lambda*(I*tr(gradDU)) - (mu + lambda)*gradDU,
"div(sigma)" "div(sigma)"
);
}
else if(divDSigmaExpMethod == "surface")
{
divDSigmaExp = fvc::div
(
muf*(mesh.Sf() & fvc::interpolate(gradDU.T()))
+ lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU)))
- (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU))
); );
} }
else if(divDSigmaExpMethod == "decompose") else if(divDSigmaExpMethod == "surface")
{ {
snGradDU = fvc::snGrad(DU); divDSigmaExp = fvc::div
(
muf*(mesh.Sf() & fvc::interpolate(gradDU.T()))
+ lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU)))
- (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU))
);
}
else if(divDSigmaExpMethod == "decompose")
{
snGradDU = fvc::snGrad(DU);
surfaceTensorField shearGradDU = surfaceTensorField shearGradDU = ((I - n*n) & fvc::interpolate(gradDU));
((I - n*n)&fvc::interpolate(gradDU));
divDSigmaExp = fvc::div divDSigmaExp = fvc::div
( (
mesh.magSf() mesh.magSf()*
*( (
- (muf + lambdaf)*(snGradDU&(I - n*n)) - (muf + lambdaf)*(snGradDU & (I - n*n))
+ lambdaf*tr(shearGradDU&(I - n*n))*n + lambdaf*tr(shearGradDU & (I - n*n))*n
+ muf*(shearGradDU&n) + muf*(shearGradDU & n)
) )
); );
} }
else if(divDSigmaExpMethod == "expLaplacian") else if(divDSigmaExpMethod == "expLaplacian")
{ {
divDSigmaExp = divDSigmaExp =
- fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)") - fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)")
+ fvc::div + fvc::div(mu*gradDU.T() + lambda*(I*tr(gradDU)), "div(sigma)");
( }
mu*gradDU.T() else
+ lambda*(I*tr(gradDU)), {
"div(sigma)" FatalErrorIn(args.executable())
); << "divDSigmaExp method " << divDSigmaExpMethod << " not found!"
} << abort(FatalError);
else }
{
FatalError << "divDSigmaExp method " << divDSigmaExpMethod << " not found!" << endl;
}

View file

@ -1,19 +1,19 @@
{ {
// force residual is the net force on the model // force residual is the net force on the model
// this should got to zero in a converged steady state model // this should got to zero in a converged steady state model
// should be altered for parallel runs // should be altered for parallel runs
vector netForce = vector::zero; vector netForce = vector::zero;
forAll(mesh.boundary(), patchi) forAll(mesh.boundary(), patchi)
{ {
netForce += netForce += sum
sum(
mesh.Sf().boundaryField()[patchi]
&
( (
2*mu.boundaryField()[patchi]*symm(gradU.boundaryField()[patchi]) mesh.Sf().boundaryField()[patchi]
+ lambda*tr(gradU.boundaryField()[patchi])*I &
) (
2*mu.boundaryField()[patchi]*symm(gradU.boundaryField()[patchi])
+ lambda*tr(gradU.boundaryField()[patchi])*I
)
); );
} }
forceResidual = mag(netForce); forceResidual = mag(netForce);
} }

View file

@ -1,22 +1,22 @@
{ {
surfaceVectorField n = mesh.Sf()/mesh.magSf(); surfaceVectorField n = mesh.Sf()/mesh.magSf();
// traction = (n&fvc::interpolate(sigma)); // traction = (n & fvc::interpolate(sigma));
// surfaceTensorField sGradU = // surfaceTensorField sGradU =
// ((I - n*n)&fvc::interpolate(gradU)); // ((I - n*n) & fvc::interpolate(gradU));
// traction = // traction =
// (2*mu + lambda)*snGradU // (2*mu + lambda)*snGradU
// - (mu + lambda)*(snGradU&(I - n*n)) // - (mu + lambda)*(snGradU&(I - n*n))
// + mu*(sGradU&n) // + mu*(sGradU & n)
// + lambda*tr(sGradU&(I - n*n))*n; // + lambda*tr(sGradU&(I - n*n))*n;
// traction = // traction =
// (2*mu + lambda)*fvc::snGrad(U) // (2*mu + lambda)*fvc::snGrad(U)
// - (mu + lambda)*(n&sGradU) // - (mu + lambda)*(n & sGradU)
// + mu*(sGradU&n) // + mu*(sGradU & n)
// + lambda*tr(sGradU)*n; // + lambda*tr(sGradU)*n;
// philipc // philipc
// I am having trouble with back-calculation of interface tractions from solid interface // I am having trouble with back-calculation of interface tractions from solid interface
@ -27,15 +27,15 @@
traction = (n&fvc::interpolate(sigma+DSigma)); traction = (n&fvc::interpolate(sigma+DSigma));
// forAll(traction.boundaryField(), patchi) // forAll(traction.boundaryField(), patchi)
// { // {
// if (mesh.boundary()[patchi].type() == "cohesive") // if (mesh.boundary()[patchi].type() == "cohesive")
// { // {
// forAll(traction.boundaryField()[patchi], facei) // forAll(traction.boundaryField()[patchi], facei)
// { // {
// Pout << "face " << facei << " with traction magnitude " // Pout << "face " << facei << " with traction magnitude "
// << mag(traction.boundaryField()[patchi][facei])/1e6 << " MPa and traction " // << mag(traction.boundaryField()[patchi][facei])/1e6 << " MPa and traction "
// << traction.boundaryField()[patchi][facei]/1e6 << " MPa" << endl; // << traction.boundaryField()[patchi][facei]/1e6 << " MPa" << endl;
// } // }
// } // }
// } // }
} }

View file

@ -1,53 +1,53 @@
label cohesivePatchID = -1; label cohesivePatchID = -1;
solidCohesiveFvPatchVectorField* cohesivePatchDUPtr = NULL; solidCohesiveFvPatchVectorField* cohesivePatchDUPtr = NULL;
solidCohesiveFixedModeMixFvPatchVectorField* cohesivePatchDUFixedModePtr = NULL; solidCohesiveFixedModeMixFvPatchVectorField* cohesivePatchDUFixedModePtr = NULL;
forAll (DU.boundaryField(), patchI) forAll (DU.boundaryField(), patchI)
{ {
if (isA<solidCohesiveFvPatchVectorField>(DU.boundaryField()[patchI])) if (isA<solidCohesiveFvPatchVectorField>(DU.boundaryField()[patchI]))
{ {
cohesivePatchID = patchI; cohesivePatchID = patchI;
cohesivePatchDUPtr = cohesivePatchDUPtr =
&refCast<solidCohesiveFvPatchVectorField> &refCast<solidCohesiveFvPatchVectorField>
( (
DU.boundaryField()[cohesivePatchID] DU.boundaryField()[cohesivePatchID]
); );
break; break;
}
else if (isA<solidCohesiveFixedModeMixFvPatchVectorField>(DU.boundaryField()[patchI]))
{
cohesivePatchID = patchI;
cohesivePatchDUFixedModePtr =
&refCast<solidCohesiveFixedModeMixFvPatchVectorField>
(
DU.boundaryField()[cohesivePatchID]
);
break;
} }
else if (isA<solidCohesiveFixedModeMixFvPatchVectorField>(DU.boundaryField()[patchI]))
{
cohesivePatchID = patchI;
cohesivePatchDUFixedModePtr =
&refCast<solidCohesiveFixedModeMixFvPatchVectorField>
(
DU.boundaryField()[cohesivePatchID]
);
break;
}
} }
if(cohesivePatchID == -1) if(cohesivePatchID == -1)
{ {
FatalErrorIn(args.executable()) FatalErrorIn(args.executable())
<< "Can't find cohesiveLawFvPatch" << nl << "Can't find cohesiveLawFvPatch" << nl
<< "One of the boundary patches in " << DU.name() << ".boundaryField() " << "One of the boundary patches in " << DU.name() << ".boundaryField() "
<< "should be of type " << solidCohesiveFvPatchVectorField::typeName << "should be of type " << solidCohesiveFvPatchVectorField::typeName
<< "or " << solidCohesiveFixedModeMixFvPatchVectorField::typeName << "or " << solidCohesiveFixedModeMixFvPatchVectorField::typeName
<< abort(FatalError); << abort(FatalError);
} }
// solidCohesiveFvPatchVectorField& cohesivePatchDU = // solidCohesiveFvPatchVectorField& cohesivePatchDU =
// refCast<solidCohesiveFvPatchVectorField> // refCast<solidCohesiveFvPatchVectorField>
// ( // (
// DU.boundaryField()[cohesivePatchID] // DU.boundaryField()[cohesivePatchID]
// ); // );
// philipc: I have moved cohesive stuff to constitutiveModel // philipc: I have moved cohesive stuff to constitutiveModel
// cohesiveZone is an index field // cohesiveZone is an index field
// which allows the user to limit the crack to certain areas at runtime // which allows the user to limit the crack to certain areas at runtime
// 1 for faces within cohesiveZone // 1 for faces within cohesiveZone
// 0 for faces outside cohesiveZone // 0 for faces outside cohesiveZone
surfaceScalarField cohesiveZone surfaceScalarField cohesiveZone
( (
IOobject IOobject
@ -59,110 +59,111 @@
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
//dimensionedScalar("one", dimless, 1.0)
dimensionedScalar("zero", dimless, 0.0) dimensionedScalar("zero", dimless, 0.0)
); );
// limit crack to specified boxes // limit crack to specified boxes
{ {
const dictionary& stressControl = const dictionary& stressControl =
mesh.solutionDict().subDict("solidMechanics"); mesh.solutionDict().subDict("solidMechanics");
List<boundBox> userBoxes(stressControl.lookup("crackLimitingBoxes")); List<boundBox> userBoxes(stressControl.lookup("crackLimitingBoxes"));
const surfaceVectorField& Cf = mesh.Cf(); const surfaceVectorField& Cf = mesh.Cf();
//int numPossibleCrackFaces = 0; //int numPossibleCrackFaces = 0;
forAll(cohesiveZone.internalField(), faceI) forAll(cohesiveZone.internalField(), faceI)
{
bool faceInsideBox = false;
forAll(userBoxes, boxi)
{ {
if(userBoxes[boxi].contains(Cf.internalField()[faceI])) faceInsideBox = true; bool faceInsideBox = false;
}
if(faceInsideBox) forAll(userBoxes, boxi)
{
cohesiveZone.internalField()[faceI] = 1.0;
//numPossibleCrackFaces++;
}
}
//reduce(numPossibleCrackFaces, sumOp<int>());
forAll(cohesiveZone.boundaryField(), patchI)
{
// cracks may go along proc boundaries
if(mesh.boundaryMesh()[patchI].type() == processorPolyPatch::typeName)
{
forAll(cohesiveZone.boundaryField()[patchI], faceI)
{
bool faceInsideBox = false;
forAll(userBoxes, boxi)
{ {
if(userBoxes[boxi].contains(Cf.boundaryField()[patchI][faceI])) faceInsideBox = true; if(userBoxes[boxi].contains(Cf.internalField()[faceI])) faceInsideBox = true;
} }
if(faceInsideBox) if(faceInsideBox)
{ {
cohesiveZone.boundaryField()[patchI][faceI] = 1.0; cohesiveZone.internalField()[faceI] = 1.0;
//numPossibleCrackFaces++;
} }
} }
//reduce(numPossibleCrackFaces, sumOp<int>());
// numPossibleCrackFaces += int(sum(cohesiveZone.boundaryField()[patchI])); forAll(cohesiveZone.boundaryField(), patchI)
// philipc multiMat cracks not working on proc boundaries yet... disable for now {
// found the problem: solidInterface needs to know about mesh changes so // cracks may go along proc boundaries
// I make a new one each time there is a crack if(mesh.boundaryMesh()[patchI].type() == processorPolyPatch::typeName)
// int numProcFaces = int(sum(cohesiveZone.boundaryField()[patchI])); {
forAll(cohesiveZone.boundaryField()[patchI], faceI)
{
bool faceInsideBox = false;
forAll(userBoxes, boxi)
{
if(userBoxes[boxi].contains(Cf.boundaryField()[patchI][faceI])) faceInsideBox = true;
}
if(faceInsideBox)
{
cohesiveZone.boundaryField()[patchI][faceI] = 1.0;
}
}
// numPossibleCrackFaces += int(sum(cohesiveZone.boundaryField()[patchI]));
// philipc multiMat cracks not working on proc boundaries yet... disable for now
// found the problem: solidInterface needs to know about mesh changes so
// I make a new one each time there is a crack
// int numProcFaces = int(sum(cohesiveZone.boundaryField()[patchI]));
// if(numProcFaces > 0) // if(numProcFaces > 0)
// { // {
// cohesiveZone.boundaryField()[patchI] = 0.0; // cohesiveZone.boundaryField()[patchI] = 0.0;
// Warning << "Processor boundary cracking is " // Warning << "Processor boundary cracking is "
// << "disabled because it is not working yet for multi-materials." << nl // << "disabled because it is not working yet for multi-materials." << nl
// << "There are " << numProcFaces << " possible cracks " // << "There are " << numProcFaces << " possible cracks "
// << "faces on processor boundary " << mesh.boundary()[patchI].name() // << "faces on processor boundary " << mesh.boundary()[patchI].name()
// << ", which are not allowed to crack." << endl; // << ", which are not allowed to crack." << endl;
// } // }
}
} }
}
// Info << "\nNumber of possible cracking faces is " << numPossibleCrackFaces << endl; // Info << "\nNumber of possible cracking faces is " << numPossibleCrackFaces << endl;
Info << "\nThere are " << gSum(cohesiveZone.internalField()) << " potential internal crack faces" << nl << endl; Info << "\nThere are " << gSum(cohesiveZone.internalField()) << " potential internal crack faces" << nl << endl;
Info << "\nThere are " << gSum(cohesiveZone.boundaryField())/2 << " potential coupled boundary crack faces" << nl << endl; Info << "\nThere are " << gSum(cohesiveZone.boundaryField())/2 << " potential coupled boundary crack faces" << nl << endl;
// write field for visualisation // write field for visualisation
volScalarField cohesiveZoneVol volScalarField cohesiveZoneVol
( (
IOobject IOobject
( (
"cohesiveZoneVol", "cohesiveZoneVol",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedScalar("zero", dimless, 0.0) dimensionedScalar("zero", dimless, 0.0)
); );
forAll(cohesiveZone.internalField(), facei)
{ forAll(cohesiveZone.internalField(), facei)
if(cohesiveZone.internalField()[facei])
{ {
cohesiveZoneVol.internalField()[mesh.owner()[facei]] = 1.0; if(cohesiveZone.internalField()[facei])
cohesiveZoneVol.internalField()[mesh.neighbour()[facei]] = 1.0; {
cohesiveZoneVol.internalField()[mesh.owner()[facei]] = 1.0;
cohesiveZoneVol.internalField()[mesh.neighbour()[facei]] = 1.0;
}
} }
}
forAll(cohesiveZone.boundaryField(), patchi) forAll(cohesiveZone.boundaryField(), patchi)
{
forAll(cohesiveZone.boundaryField()[patchi], facei)
{ {
if(cohesiveZone.boundaryField()[patchi][facei]) forAll(cohesiveZone.boundaryField()[patchi], facei)
{ {
cohesiveZoneVol.boundaryField()[patchi][facei] = 1.0; if(cohesiveZone.boundaryField()[patchi][facei] > 0.0)
{
cohesiveZoneVol.boundaryField()[patchi][facei] = 1.0;
}
}
} }
} Info << "Writing cohesiveZone field" << endl;
} cohesiveZoneVol.write();
Info << "Writing cohesiveZone field" << endl;
cohesiveZoneVol.write();
} }

View file

@ -36,8 +36,8 @@
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimless, vector::zero) dimensionedVector("zero", dimless, vector::zero)
); );
Info<< "Creating field U\n" << endl; Info<< "Creating field U\n" << endl;
@ -59,15 +59,15 @@
( (
IOobject IOobject
( (
"DEpsilon", "DEpsilon",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedSymmTensor("zero", dimless, symmTensor::zero) dimensionedSymmTensor("zero", dimless, symmTensor::zero)
); );
volSymmTensorField DSigma volSymmTensorField DSigma
( (
@ -111,23 +111,23 @@
dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero) dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero)
); );
volVectorField divDSigmaExp volVectorField divDSigmaExp
( (
IOobject IOobject
( (
"divDSigmaExp", "divDSigmaExp",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimForce/dimVolume, vector::zero) dimensionedVector("zero", dimForce/dimVolume, vector::zero)
); );
constitutiveModel rheology(sigma, DU); constitutiveModel rheology(sigma, DU);
//solidInterface interface(mesh, rheology); //solidInterface interface(mesh, rheology);
// solidInterface* interfacePtr = new solidInterface(mesh, rheology); //solidInterface* interfacePtr = new solidInterface(mesh, rheology);
surfaceVectorField traction surfaceVectorField traction
( (
@ -143,8 +143,8 @@ constitutiveModel rheology(sigma, DU);
dimensionedVector("zero", dimForce/dimArea, vector::zero) dimensionedVector("zero", dimForce/dimArea, vector::zero)
); );
// for aitken relaxation // for aitken relaxation
volVectorField aitkenDelta volVectorField aitkenDelta
( (
IOobject IOobject
( (
@ -155,8 +155,9 @@ constitutiveModel rheology(sigma, DU);
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimLength, vector::zero) dimensionedVector("zero", dimLength, vector::zero)
); );
// aitken relaxation factor
scalar aitkenInitialRes = 1.0; // aitken relaxation factor
scalar aitkenTheta = 0.1; scalar aitkenInitialRes = 1.0;
scalar aitkenTheta = 0.1;

View file

@ -2,17 +2,17 @@ OFstream * filePtr(NULL);
word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch")); word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch"));
label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName); label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName);
if(historyPatchID == -1) if(historyPatchID == -1)
{ {
Warning << "history patch " << historyPatchName Warning << "history patch " << historyPatchName
<< " not found. Force-displacement will not be written" << " not found. Force-displacement will not be written"
<< endl; << endl;
} }
else if(Pstream::master()) else if(Pstream::master())
{ {
Info << "Force-displacement for patch " << historyPatchName Info << "Force-displacement for patch " << historyPatchName
<< " will be written to forceDisp.dat" << " will be written to forceDisp.dat"
<< endl; << endl;
filePtr = new OFstream("forceDisp.dat"); filePtr = new OFstream("forceDisp.dat");
OFstream& forceDispFile = *filePtr; OFstream& forceDispFile = *filePtr;
forceDispFile << "#Disp(mm)\tForce(N)" << endl; forceDispFile << "#Disp(mm)\tForce(N)" << endl;
} }

View file

@ -34,6 +34,7 @@ Author
Philip Cardiff UCD Philip Cardiff UCD
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "fvCFD.H" #include "fvCFD.H"
#include "constitutiveModel.H" #include "constitutiveModel.H"
//#include "componentReferenceList.H" //#include "componentReferenceList.H"
@ -48,196 +49,197 @@ Author
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
# include "setRootCase.H" # include "setRootCase.H"
# include "createTime.H" # include "createTime.H"
# include "createCrackerMesh.H" # include "createCrackerMesh.H"
# include "createFields.H" # include "createFields.H"
# include "createCrack.H" # include "createCrack.H"
//# include "createReference.H" //# include "createReference.H"
# include "createHistory.H" # include "createHistory.H"
# include "readDivDSigmaExpMethod.H" # include "readDivDSigmaExpMethod.H"
# include "createSolidInterfaceIncrNoModify.H" # include "createSolidInterfaceIncrNoModify.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl; Info<< "\nStarting time loop\n" << endl;
lduMatrix::debug = 0; lduMatrix::debug = 0;
scalar maxEffTractionFraction = 0; scalar maxEffTractionFraction = 0;
while (runTime.run()) while (runTime.run())
{ {
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
# include "setDeltaT.H" # include "setDeltaT.H"
runTime++; runTime++;
Info<< "\nTime: " << runTime.timeName() << " s\n" << endl; Info<< "\nTime = " << runTime.timeName() << " s\n" << endl;
volScalarField rho = rheology.rho(); volScalarField rho = rheology.rho();
volScalarField mu = rheology.mu(); volScalarField mu = rheology.mu();
volScalarField lambda = rheology.lambda(); volScalarField lambda = rheology.lambda();
surfaceScalarField muf = fvc::interpolate(mu); surfaceScalarField muf = fvc::interpolate(mu);
surfaceScalarField lambdaf = fvc::interpolate(lambda); surfaceScalarField lambdaf = fvc::interpolate(lambda);
solidInterfacePtr->modifyProperties(muf, lambdaf); solidInterfacePtr->modifyProperties(muf, lambdaf);
//# include "waveCourantNo.H" //# include "waveCourantNo.H"
int iCorr = 0; int iCorr = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar initialResidual = 0; scalar initialResidual = 0;
scalar relativeResidual = 1; scalar relativeResidual = 1;
//scalar forceResidual = 1; //scalar forceResidual = 1;
label nFacesToBreak = 0; label nFacesToBreak = 0;
label nCoupledFacesToBreak = 0; label nCoupledFacesToBreak = 0;
bool topoChange = false; bool topoChange = false;
// DU from the previous timestep is usually a good guess // DU from the previous timestep is usually a good guess
// for the next timestep, but it can cause faces to prematurely // for the next timestep, but it can cause faces to prematurely
// crack. // crack.
// so I will reduce DU here to stop this happening // so I will reduce DU here to stop this happening
if (!predictor) if (!predictor)
{ {
DU *= 0.0; DU *= 0.0;
} }
do do
{ {
surfaceVectorField n = mesh.Sf()/mesh.magSf(); surfaceVectorField n = mesh.Sf()/mesh.magSf();
do do
{ {
DU.storePrevIter(); DU.storePrevIter();
# include "calculateDivDSigmaExp.H" # include "calculateDivDSigmaExp.H"
fvVectorMatrix DUEqn fvVectorMatrix DUEqn
( (
rho*fvm::d2dt2(DU) rho*fvm::d2dt2(DU)
== ==
fvm::laplacian(2*muf + lambdaf, DU, "laplacian(DDU,DU)") fvm::laplacian(2*muf + lambdaf, DU, "laplacian(DDU,DU)")
+ divDSigmaExp + divDSigmaExp
); );
//# include "setReference.H" //# include "setReference.H"
if(solidInterfacePtr) if(solidInterfacePtr)
{ {
solidInterfacePtr->correct(DUEqn); solidInterfacePtr->correct(DUEqn);
} }
//DUEqn.relax(); //DUEqn.relax();
solverPerf = DUEqn.solve(); solverPerf = DUEqn.solve();
if (aitkenRelax) if (aitkenRelax)
{ {
# include "aitkenRelaxation.H" # include "aitkenRelaxation.H"
} }
else else
{ {
DU.relax(); DU.relax();
} }
if (iCorr == 0) if (iCorr == 0)
{ {
initialResidual = solverPerf.initialResidual(); initialResidual = solverPerf.initialResidual();
aitkenInitialRes = gMax(mag(DU.internalField())); aitkenInitialRes = gMax(mag(DU.internalField()));
} }
//gradDU = solidInterfacePtr->grad(DU); //gradDU = solidInterfacePtr->grad(DU);
// use leastSquaresSolidInterface grad scheme // use leastSquaresSolidInterface grad scheme
gradDU = fvc::grad(DU); gradDU = fvc::grad(DU);
# include "calculateRelativeResidual.H" # include "calculateRelativeResidual.H"
if (iCorr % infoFrequency == 0) if (iCorr % infoFrequency == 0)
{ {
Info << "\tTime " << runTime.value() Info<< "\tTime " << runTime.value()
<< ", Corr " << iCorr << ", Corr " << iCorr
<< ", Solving for " << DU.name() << ", Solving for " << DU.name()
<< " using " << solverPerf.solverName() << " using " << solverPerf.solverName()
<< ", res = " << solverPerf.initialResidual() << ", res = " << solverPerf.initialResidual()
<< ", rel res = " << relativeResidual; << ", rel res = " << relativeResidual;
if (aitkenRelax) if (aitkenRelax)
{ {
Info << ", aitken = " << aitkenTheta; Info << ", aitken = " << aitkenTheta;
} }
Info << ", inner iters " << solverPerf.nIterations() << endl; Info << ", inner iters " << solverPerf.nIterations() << endl;
} }
} }
while while
( (
//iCorr++ == 0 //iCorr++ == 0
iCorr++ < 10 iCorr++ < 10
|| ||
( (
//solverPerf.initialResidual() > convergenceTolerance //solverPerf.initialResidual() > convergenceTolerance
relativeResidual > convergenceTolerance relativeResidual > convergenceTolerance
&& &&
iCorr < nCorr iCorr < nCorr
) )
); );
Info<< "Solving for " << DU.name() << " using " Info<< "Solving for " << DU.name() << " using "
<< solverPerf.solverName() << solverPerf.solverName()
<< ", Initial residual = " << initialResidual << ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual() << ", Final residual = " << solverPerf.initialResidual()
<< ", No outer iterations " << iCorr << ", No outer iterations " << iCorr
<< ", Relative residual " << relativeResidual << endl; << ", Relative residual " << relativeResidual << endl;
# include "calculateTraction.H" # include "calculateTraction.H"
# include "updateCrack.H" # include "updateCrack.H"
Info<< "Max effective traction fraction: " Info<< "Max effective traction fraction: "
<< maxEffTractionFraction << endl; << maxEffTractionFraction << endl;
// reset counter if faces want to crack // reset counter if faces want to crack
if ((nFacesToBreak > 0) || (nCoupledFacesToBreak > 0)) iCorr = 0; if ((nFacesToBreak > 0) || (nCoupledFacesToBreak > 0)) iCorr = 0;
} }
while( (nFacesToBreak > 0) || (nCoupledFacesToBreak > 0)); while( (nFacesToBreak > 0) || (nCoupledFacesToBreak > 0));
if (cohesivePatchDUPtr) if (cohesivePatchDUPtr)
{ {
if (returnReduce(cohesivePatchDUPtr->size(), sumOp<label>())) if (returnReduce(cohesivePatchDUPtr->size(), sumOp<label>()))
{ {
cohesivePatchDUPtr->cracking(); cohesivePatchDUPtr->cracking();
} }
} }
else else
{ {
if if
( (
returnReduce returnReduce
( (
cohesivePatchDUFixedModePtr->size(), cohesivePatchDUFixedModePtr->size(),
sumOp<label>()) sumOp<label>()
) )
{ )
Pout << "Number of faces in crack: " {
<< cohesivePatchDUFixedModePtr->size() << endl; Pout << "Number of faces in crack: "
cohesivePatchDUFixedModePtr->relativeSeparationDistance(); << cohesivePatchDUFixedModePtr->size() << endl;
} cohesivePatchDUFixedModePtr->relativeSeparationDistance();
} }
}
# include "calculateDEpsilonDSigma.H" # include "calculateDEpsilonDSigma.H"
// update total quantities // update total quantities
U += DU; U += DU;
epsilon += DEpsilon; epsilon += DEpsilon;
sigma += DSigma; sigma += DSigma;
# include "writeFields.H" # include "writeFields.H"
# include "writeHistory.H" # include "writeHistory.H"
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s\n\n" << " ClockTime = " << runTime.elapsedClockTime() << " s\n\n"
<< endl; << endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;
return(0); return(0);
} }

View file

@ -4,6 +4,6 @@ Info << "Selecting divDSigmaExp calculation method " << divDSigmaExpMethod << e
if(divDSigmaExpMethod != "standard" && divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose" && divDSigmaExpMethod != "laplacian") if(divDSigmaExpMethod != "standard" && divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose" && divDSigmaExpMethod != "laplacian")
{ {
FatalError << "divDSigmaExp method " << divDSigmaExpMethod << " not found!" << nl FatalError << "divDSigmaExp method " << divDSigmaExpMethod << " not found!" << nl
<< "valid methods are:\nstandard\nsurface\ndecompose\nlaplacian" << "valid methods are:\nstandard\nsurface\ndecompose\nlaplacian"
<< exit(FatalError); << exit(FatalError);
} }

View file

@ -1,36 +1,36 @@
if (dynamicTimeStep) if (dynamicTimeStep)
{ {
if if
( (
//(maxEffTraction < 0.999*CzLaw.sigmaMax().value()) //(maxEffTraction < 0.999*CzLaw.sigmaMax().value())
(returnReduce(maxEffTractionFraction, maxOp<scalar>()) < 0.99) (returnReduce(maxEffTractionFraction, maxOp<scalar>()) < 0.99)
//&& (cohesivePatchU.size() == 0) //&& (cohesivePatchU.size() == 0)
&& (mag(runTime.deltaT().value() - deltaTmax) < SMALL) && (mag(runTime.deltaT().value() - deltaTmax) < SMALL)
) )
{ {
runTime.setDeltaT(deltaTmax); runTime.setDeltaT(deltaTmax);
} }
else else
{ {
scalar newDeltaT = deltaTmin; scalar newDeltaT = deltaTmin;
if (newDeltaT/runTime.deltaT().value() < 0.5) if (newDeltaT/runTime.deltaT().value() < 0.5)
{ {
newDeltaT = 0.5*runTime.deltaT().value(); newDeltaT = 0.5*runTime.deltaT().value();
Info << "Reducing time step" << nl; Info << "Reducing time step" << nl;
} }
runTime.setDeltaT(newDeltaT); runTime.setDeltaT(newDeltaT);
} }
Pout << "Current time step size: " Pout << "Current time step size: "
<< runTime.deltaT().value() << " s" << endl; << runTime.deltaT().value() << " s" << endl;
scalar maxDT = runTime.deltaT().value(); scalar maxDT = runTime.deltaT().value();
if(mag(returnReduce(maxDT, maxOp<scalar>()) - runTime.deltaT().value()) > SMALL) if(mag(returnReduce(maxDT, maxOp<scalar>()) - runTime.deltaT().value()) > SMALL)
{ {
FatalError << "Processors have different time-steps!" FatalError << "Processors have different time-steps!"
<< exit(FatalError); << exit(FatalError);
} }
} }

View file

@ -10,15 +10,15 @@ nCoupledFacesToBreak = 0;
cohesiveZone.internalField()* cohesiveZone.internalField()*
( n.internalField() & traction.internalField() ); ( n.internalField() & traction.internalField() );
// only consider tensile tractions // only consider tensile tractions
normalTraction = max(normalTraction, scalar(0)); normalTraction = max(normalTraction, scalar(0));
scalarField shearTraction = scalarField shearTraction =
cohesiveZone.internalField() * cohesiveZone.internalField()*
mag( (I - Foam::sqr(n.internalField())) & traction.internalField() ); mag( (I - Foam::sqr(n.internalField())) & traction.internalField() );
// the traction fraction is monitored to decide which faces to break: // the traction fraction is monitored to decide which faces to break:
// ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face // ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face
const surfaceScalarField sigmaMax = rheology.cohLaw().sigmaMax(); const surfaceScalarField sigmaMax = rheology.cohLaw().sigmaMax();
const surfaceScalarField tauMax = rheology.cohLaw().tauMax(); const surfaceScalarField tauMax = rheology.cohLaw().tauMax();
@ -91,6 +91,7 @@ nCoupledFacesToBreak = 0;
faceToBreakIndex = facesToBreak[faceI]; faceToBreakIndex = facesToBreak[faceI];
} }
} }
scalar gMaxEffTractionFraction = scalar gMaxEffTractionFraction =
returnReduce(faceToBreakEffTractionFraction, maxOp<scalar>()); returnReduce(faceToBreakEffTractionFraction, maxOp<scalar>());
@ -111,7 +112,6 @@ nCoupledFacesToBreak = 0;
} }
// Check if maximum is present on more then one processors // Check if maximum is present on more then one processors
label procID = Pstream::nProcs(); label procID = Pstream::nProcs();
if (procHasFaceToBreak) if (procHasFaceToBreak)
{ {
@ -132,46 +132,47 @@ nCoupledFacesToBreak = 0;
SLList<label> coupledFacesToBreakList; SLList<label> coupledFacesToBreakList;
SLList<scalar> coupledFacesToBreakEffTractionFractionList; SLList<scalar> coupledFacesToBreakEffTractionFractionList;
forAll(mesh.boundary(), patchI) forAll(mesh.boundary(), patchI)
{ {
if (mesh.boundary()[patchI].coupled()) if (mesh.boundary()[patchI].coupled())
{ {
// scalarField pEffTraction = // scalarField pEffTraction =
// cohesiveZone.boundaryField()[patchI] * // cohesiveZone.boundaryField()[patchI]*
// mag(traction.boundaryField()[patchI]); // mag(traction.boundaryField()[patchI]);
// scalarField pEffTractionFraction = pEffTraction/sigmaMax.boundaryField()[patchI]; // scalarField pEffTractionFraction = pEffTraction/sigmaMax.boundaryField()[patchI];
scalarField pNormalTraction = scalarField pNormalTraction =
cohesiveZone.boundaryField()[patchI]* cohesiveZone.boundaryField()[patchI]*
( n.boundaryField()[patchI] & traction.boundaryField()[patchI] ); ( n.boundaryField()[patchI] & traction.boundaryField()[patchI] );
// only consider tensile tractions // only consider tensile tractions
pNormalTraction = max(pNormalTraction, scalar(0)); pNormalTraction = max(pNormalTraction, scalar(0));
scalarField pShearTraction = scalarField pShearTraction =
cohesiveZone.boundaryField()[patchI] * cohesiveZone.boundaryField()[patchI]*
mag( (I - Foam::sqr(n.boundaryField()[patchI])) & traction.boundaryField()[patchI] ); mag( (I - Foam::sqr(n.boundaryField()[patchI])) & traction.boundaryField()[patchI] );
// the traction fraction is monitored to decide which faces to break: // the traction fraction is monitored to decide which faces to break:
// ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face // ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face
const scalarField& pSigmaMax = sigmaMax.boundaryField()[patchI]; const scalarField& pSigmaMax = sigmaMax.boundaryField()[patchI];
const scalarField& pTauMax = tauMax.boundaryField()[patchI]; const scalarField& pTauMax = tauMax.boundaryField()[patchI];
// scalarField pEffTractionFraction = // scalarField pEffTractionFraction =
// (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) + (pShearTraction/pTauMax)*(pShearTraction/pTauMax); // (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) + (pShearTraction/pTauMax)*(pShearTraction/pTauMax);
scalarField pEffTractionFraction(pNormalTraction.size(), 0.0); scalarField pEffTractionFraction(pNormalTraction.size(), 0.0);
if(cohesivePatchDUPtr) if(cohesivePatchDUPtr)
{ {
pEffTractionFraction = pEffTractionFraction =
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) + (pShearTraction/pTauMax)*(pShearTraction/pTauMax); (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
} + (pShearTraction/pTauMax)*(pShearTraction/pTauMax);
else }
{ else
// solidCohesiveFixedModeMix only uses sigmaMax {
pEffTractionFraction = // solidCohesiveFixedModeMix only uses sigmaMax
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) + (pShearTraction/pSigmaMax)*(pShearTraction/pSigmaMax); pEffTractionFraction =
} (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
+ (pShearTraction/pSigmaMax)*(pShearTraction/pSigmaMax);
}
label start = mesh.boundaryMesh()[patchI].start(); label start = mesh.boundaryMesh()[patchI].start();
@ -182,9 +183,9 @@ nCoupledFacesToBreak = 0;
maxEffTractionFraction = pEffTractionFraction[faceI]; maxEffTractionFraction = pEffTractionFraction[faceI];
} }
if (pEffTractionFraction[faceI] > 1.0) if (pEffTractionFraction[faceI] > 1.0)
{ {
//Pout << "coupled face to break " << faceI << endl; //Pout << "coupled face to break " << faceI << endl;
coupledFacesToBreakList.insert(start + faceI); coupledFacesToBreakList.insert(start + faceI);
coupledFacesToBreakEffTractionFractionList.insert coupledFacesToBreakEffTractionFractionList.insert
( (
@ -227,7 +228,6 @@ nCoupledFacesToBreak = 0;
} }
} }
scalar gMaxCoupledEffTractionFraction = scalar gMaxCoupledEffTractionFraction =
returnReduce(coupledFaceToBreakEffTractionFraction, maxOp<scalar>()); returnReduce(coupledFaceToBreakEffTractionFraction, maxOp<scalar>());
@ -249,7 +249,6 @@ nCoupledFacesToBreak = 0;
} }
// Check if maximum is present on more then one processors // Check if maximum is present on more then one processors
label procID = Pstream::nProcs(); label procID = Pstream::nProcs();
if (procHasCoupledFaceToBreak) if (procHasCoupledFaceToBreak)
{ {
@ -283,6 +282,7 @@ nCoupledFacesToBreak = 0;
{ {
label patchID = label patchID =
mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex); mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex);
label start = mesh.boundaryMesh()[patchID].start(); label start = mesh.boundaryMesh()[patchID].start();
label localIndex = coupledFaceToBreakIndex - start; label localIndex = coupledFaceToBreakIndex - start;
@ -347,30 +347,38 @@ nCoupledFacesToBreak = 0;
faceToBreakNormal = n.internalField()[faceToBreakIndex]; faceToBreakNormal = n.internalField()[faceToBreakIndex];
// Scale broken face traction // Scale broken face traction
// The scale factor is derived by solving the following eqn for alpha: // The scale factor is derived by solving the following eqn for alpha:
// (alpha*tN/tNC)^2 + (alpha*tS/tSC)^2 = 1 // (alpha*tN/tNC)^2 + (alpha*tS/tSC)^2 = 1
faceToBreakSigmaMax = sigmaMaxI[faceToBreakIndex]; faceToBreakSigmaMax = sigmaMaxI[faceToBreakIndex];
faceToBreakTauMax = tauMaxI[faceToBreakIndex]; faceToBreakTauMax = tauMaxI[faceToBreakIndex];
scalar normalTrac = faceToBreakNormal & faceToBreakTraction; scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
normalTrac = max(normalTrac, 0.0); normalTrac = max(normalTrac, 0.0);
scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction ); scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
scalar scaleFactor = 1; scalar scaleFactor = 1;
if(cohesivePatchDUPtr) if(cohesivePatchDUPtr)
{
scaleFactor =
::sqrt(1 / (
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
) );
}
else
{ {
// solidCohesiveFixedModeMix only uses sigmaMax scaleFactor =
scaleFactor = Foam::sqrt
::sqrt(1 / ( (
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax) 1 /
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax) (
) ); (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
)
);
}
else
{
// solidCohesiveFixedModeMix only uses sigmaMax
scaleFactor =
Foam::sqrt
(
1 /
(
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
)
);
} }
faceToBreakTraction *= scaleFactor; faceToBreakTraction *= scaleFactor;
@ -388,44 +396,41 @@ nCoupledFacesToBreak = 0;
faceToBreakNormal = n.boundaryField()[patchID][localIndex]; faceToBreakNormal = n.boundaryField()[patchID][localIndex];
// Scale broken face traction // Scale broken face traction
faceToBreakSigmaMax = sigmaMax.boundaryField()[patchID][localIndex]; faceToBreakSigmaMax = sigmaMax.boundaryField()[patchID][localIndex];
faceToBreakTauMax = tauMax.boundaryField()[patchID][localIndex]; faceToBreakTauMax = tauMax.boundaryField()[patchID][localIndex];
scalar normalTrac = faceToBreakNormal & faceToBreakTraction; scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
normalTrac = max(normalTrac, scalar(0)); normalTrac = max(normalTrac, 0.0);
scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction ); scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
scalar scaleFactor = 1; scalar scaleFactor = 1;
if(cohesivePatchDUPtr) if(cohesivePatchDUPtr)
{ {
scaleFactor = scaleFactor =
Foam::sqrt Foam::sqrt
(
1/
( (
(normalTrac/faceToBreakSigmaMax)* 1 /
(normalTrac/faceToBreakSigmaMax) (
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax) (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
) + (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
); )
} );
else }
{ else
// solidCohesiveFixedModeMix only uses sigmaMax {
scaleFactor = // solidCohesiveFixedModeMix only uses sigmaMax
Foam::sqrt scaleFactor =
( Foam::sqrt
1/
( (
(normalTrac/faceToBreakSigmaMax)* 1 /
(normalTrac/faceToBreakSigmaMax) (
+ (shearTrac/faceToBreakSigmaMax)* (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
(shearTrac/faceToBreakSigmaMax) + (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
) )
); );
} }
faceToBreakTraction *= scaleFactor; faceToBreakTraction *= scaleFactor;
topoChange = true; topoChange = true;
} }
reduce(topoChange, orOp<bool>()); reduce(topoChange, orOp<bool>());
@ -447,7 +452,7 @@ nCoupledFacesToBreak = 0;
Pout << "Coupled face to break: " << coupledFaceToBreak << endl; Pout << "Coupled face to break: " << coupledFaceToBreak << endl;
mesh.setBreak(faceToBreak, faceToBreakFlip, coupledFaceToBreak); mesh.setBreak(faceToBreak, faceToBreakFlip, coupledFaceToBreak);
mesh.update(); mesh.update();
const labelList& faceMap = mesh.topoChangeMap().faceMap(); const labelList& faceMap = mesh.topoChangeMap().faceMap();
label start = mesh.boundaryMesh()[cohesivePatchID].start(); label start = mesh.boundaryMesh()[cohesivePatchID].start();
@ -457,19 +462,19 @@ nCoupledFacesToBreak = 0;
muf = fvc::interpolate(mu); muf = fvc::interpolate(mu);
lambdaf = fvc::interpolate(lambda); lambdaf = fvc::interpolate(lambda);
// we need to modify propertiess after cracking otherwise momentum equation is wrong // we need to modify propertiess after cracking otherwise momentum equation is wrong
// but solidInterface seems to hold some information about old mesh // but solidInterface seems to hold some information about old mesh
// so we will delete it and make another // so we will delete it and make another
// we could probably add a public clearout function // we could probably add a public clearout function
// create new solidInterface // create new solidInterface
if(rheology.solidInterfaceActive()) if(rheology.solidInterfaceActive())
{ {
rheology.solInterface().clearOut(); rheology.solInterface().clearOut();
solidInterfacePtr->modifyProperties(muf, lambdaf); solidInterfacePtr->modifyProperties(muf, lambdaf);
} }
// All values on the new crack faces get set to zero // All values on the new crack faces get set to zero
// so we must manually correct them // so we must manually correct them
const vectorField DUpI = const vectorField DUpI =
DU.boundaryField()[cohesivePatchID].patchInternalField(); DU.boundaryField()[cohesivePatchID].patchInternalField();
const vectorField oldDUpI = const vectorField oldDUpI =
@ -492,8 +497,8 @@ nCoupledFacesToBreak = 0;
const scalarField globalMuPI = mesh.globalCrackField(muPI); const scalarField globalMuPI = mesh.globalCrackField(muPI);
const scalarField globalLambdaPI = mesh.globalCrackField(lambdaPI); const scalarField globalLambdaPI = mesh.globalCrackField(lambdaPI);
// cohesivePatchU.size() // cohesivePatchU.size()
int cohesivePatchSize(cohesivePatchDUPtr ? cohesivePatchDUPtr->size() : cohesivePatchDUFixedModePtr->size()); int cohesivePatchSize(cohesivePatchDUPtr ? cohesivePatchDUPtr->size() : cohesivePatchDUFixedModePtr->size());
// Initialise fields for new cohesive face // Initialise fields for new cohesive face
const labelList& gcfa = mesh.globalCrackFaceAddressing(); const labelList& gcfa = mesh.globalCrackFaceAddressing();
@ -506,9 +511,9 @@ nCoupledFacesToBreak = 0;
// If new face // If new face
if (oldFaceIndex == faceToBreakIndex) if (oldFaceIndex == faceToBreakIndex)
{ {
// set to average of old cell centres // set to average of old cell centres
// hmnnn it would be better to interpolate // hmnnn it would be better to interpolate
// using weights... OK for now: future work // using weights... OK for now: future work
DU.boundaryField()[cohesivePatchID][i] = DU.boundaryField()[cohesivePatchID][i] =
0.5 0.5
*( *(
@ -540,10 +545,10 @@ nCoupledFacesToBreak = 0;
+ globalsigmapI[gcfa[globalIndex]] + globalsigmapI[gcfa[globalIndex]]
); );
// initialise mu and lambda on new faces // initialise mu and lambda on new faces
// set new face value to value of internal cell // set new face value to value of internal cell
muf.boundaryField()[cohesivePatchID][i] = globalMuPI[globalIndex]; muf.boundaryField()[cohesivePatchID][i] = globalMuPI[globalIndex];
lambdaf.boundaryField()[cohesivePatchID][i] = globalLambdaPI[globalIndex]; lambdaf.boundaryField()[cohesivePatchID][i] = globalLambdaPI[globalIndex];
globalIndex++; globalIndex++;
} }
@ -554,24 +559,24 @@ nCoupledFacesToBreak = 0;
} }
// we must calculate grad using interface // we must calculate grad using interface
// DU at the interface has not been calculated yet as interface.correct() // DU at the interface has not been calculated yet as interface.correct()
// has not been called yet // has not been called yet
// not really a problem as gradDU is correct in second outer iteration // 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. // as long as this does not cause convergence problems for the first iterations.
// we should be able to calculate the interface displacements without // we should be able to calculate the interface displacements without
// having to call interface.correct() // having to call interface.correct()
// todo: add calculateInterfaceDU() function // todo: add calculateInterfaceDU() function
// interface grad uses Gauss, we need least squares // interface grad uses Gauss, we need least squares
gradDU = fvc::grad(DU); // leastSquaresSolidInterface grad scheme gradDU = fvc::grad(DU); // leastSquaresSolidInterface grad scheme
//gradDU = solidInterfacePtr->grad(DU); //gradDU = solidInterfacePtr->grad(DU);
//snGradDU = fvc::snGrad(DU); //snGradDU = fvc::snGrad(DU);
# include "calculateTraction.H" # include "calculateTraction.H"
//if (nFacesToBreak || nCoupledFacesToBreak) mesh.write(); traction.write(); //if (nFacesToBreak || nCoupledFacesToBreak) mesh.write(); traction.write();
// Initialise initiation traction for new cohesive patch face // Initialise initiation traction for new cohesive patch face
// we also need to update the traction_ field in the crack boundary condition // we also need to update the traction_ field in the crack boundary condition
// this is because it cannot set itself during mapping. // this is because it cannot set itself during mapping.
//for (label i=0; i<cohesivePatchDU.size(); i++) //for (label i=0; i<cohesivePatchDU.size(); i++)
for (label i=0; i<cohesivePatchSize; i++) for (label i=0; i<cohesivePatchSize; i++)
{ {
@ -589,51 +594,52 @@ nCoupledFacesToBreak = 0;
/mesh.magSf().boundaryField()[cohesivePatchID][i]; /mesh.magSf().boundaryField()[cohesivePatchID][i];
//vector n1 = -n0; //vector n1 = -n0;
if ((n0&faceToBreakNormal) > SMALL) if ((n0 & faceToBreakNormal) > SMALL)
{ {
traction.boundaryField()[cohesivePatchID][i] = traction.boundaryField()[cohesivePatchID][i] =
faceToBreakTraction; faceToBreakTraction;
traction.oldTime().boundaryField()[cohesivePatchID][i] = traction.oldTime().boundaryField()[cohesivePatchID][i] =
faceToBreakTraction; faceToBreakTraction;
// this seems to slow convergence in some simple test cases... // this seems to slow convergence in some simple test cases...
// but surely it should be better update it // but surely it should be better update it
//cohesivePatchDU.traction()[i] = faceToBreakTraction; //cohesivePatchDU.traction()[i] = faceToBreakTraction;
if(cohesivePatchDUPtr) if(cohesivePatchDUPtr)
{ {
cohesivePatchDUPtr->traction()[i] = faceToBreakTraction; cohesivePatchDUPtr->traction()[i] = faceToBreakTraction;
} }
else else
{ {
cohesivePatchDUFixedModePtr->traction()[i] = faceToBreakTraction; cohesivePatchDUFixedModePtr->traction()[i] = faceToBreakTraction;
cohesivePatchDUFixedModePtr->initiationTraction()[i] = faceToBreakTraction; cohesivePatchDUFixedModePtr->initiationTraction()[i] = faceToBreakTraction;
} }
} }
else else
{ {
traction.boundaryField()[cohesivePatchID][i] = traction.boundaryField()[cohesivePatchID][i] =
-faceToBreakTraction; -faceToBreakTraction;
traction.oldTime().boundaryField()[cohesivePatchID][i] =
-faceToBreakTraction;
traction.oldTime().boundaryField()[cohesivePatchID][i] = //cohesivePatchDU.traction()[i] = -faceToBreakTraction;
-faceToBreakTraction; if(cohesivePatchDUPtr)
{
//cohesivePatchDU.traction()[i] = -faceToBreakTraction; cohesivePatchDUPtr->traction()[i] = -faceToBreakTraction;
if(cohesivePatchDUPtr) }
{ else
cohesivePatchDUPtr->traction()[i] = -faceToBreakTraction; {
} cohesivePatchDUFixedModePtr->traction()[i] =
else -faceToBreakTraction;
{ cohesivePatchDUFixedModePtr->initiationTraction()[i] =
cohesivePatchDUFixedModePtr->traction()[i] = -faceToBreakTraction; -faceToBreakTraction;
cohesivePatchDUFixedModePtr->initiationTraction()[i] = -faceToBreakTraction; }
}
} }
} }
} }
// hmmnn we only need a reference for very small groups of cells // hmmnn we only need a reference for very small groups of cells
// turn off for now // turn off for now
//# include "updateReference.H" //# include "updateReference.H"
} }
} }

View file

@ -4,20 +4,21 @@
forAll(U.boundaryField(), patchI) forAll(U.boundaryField(), patchI)
{ {
// philipc - this used to set a reference on // philipc - this used to set a reference on
// processors which did not have a patch that fixesValue // processors which did not have a patch that fixesValue
// so processor in the centre of the domain all had // so processor in the centre of the domain all had
// a referece set causing stress peaks and resulting // a referece set causing stress peaks and resulting
// in an incorrect solution // in an incorrect solution
// so a quick fix is to not set a reference on regions // so a quick fix is to not set a reference on regions
// with a processor boundary // with a processor boundary
//if (U.boundaryField()[patchI].fixesValue()) //if (U.boundaryField()[patchI].fixesValue())
if ( if
U.boundaryField()[patchI].fixesValue() (
|| U.boundaryField()[patchI].fixesValue()
mesh.boundaryMesh()[patchI].type() ||
== processorPolyPatch::typeName mesh.boundaryMesh()[patchI].type()
) == processorPolyPatch::typeName
)
{ {
const unallocLabelList& curFaceCells = const unallocLabelList& curFaceCells =
mesh.boundary()[patchI].faceCells(); mesh.boundary()[patchI].faceCells();

View file

@ -85,87 +85,90 @@ if (runTime.outputTime() || topoChange)
// //- boundary traction // //- boundary traction
// volVectorField tractionBoundary // volVectorField tractionBoundary
// ( // (
// IOobject // IOobject
// ( // (
// "tractionBoundary", // "tractionBoundary",
// runTime.timeName(), // runTime.timeName(),
// mesh, // mesh,
// IOobject::NO_READ, // IOobject::NO_READ,
// IOobject::AUTO_WRITE // IOobject::AUTO_WRITE
// ), // ),
// mesh, // mesh,
// dimensionedVector("zero", dimForce/dimArea, vector::zero) // dimensionedVector("zero", dimForce/dimArea, vector::zero)
// ); // );
// surfaceVectorField n = mesh.Sf()/mesh.magSf(); // surfaceVectorField n = mesh.Sf()/mesh.magSf();
// forAll(tractionBoundary.boundaryField(), patchi) // forAll(tractionBoundary.boundaryField(), patchi)
// { // {
// if(mesh.boundaryMesh()[patchi].type() != processorPolyPatch::typeName) // if(mesh.boundaryMesh()[patchi].type() != processorPolyPatch::typeName)
// { // {
// tractionBoundary.boundaryField()[patchi] = // tractionBoundary.boundaryField()[patchi] =
// n.boundaryField()[patchi] & sigma.boundaryField()[patchi]; // n.boundaryField()[patchi] & sigma.boundaryField()[patchi];
// } // }
// } // }
//- cohesive damage and cracking, and GII and GII //- cohesive damage and cracking, and GII and GII
volScalarField damageAndCracks volScalarField damageAndCracks
( (
IOobject IOobject
( (
"damageAndCracks", "damageAndCracks",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedScalar("zero", dimless, 0.0), dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName calculatedFvPatchVectorField::typeName
); );
volScalarField GI
(
IOobject
(
"GI",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName
);
volScalarField GII
(
IOobject
(
"GII",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName
);
forAll(DU.boundaryField(), patchi)
{
// if(DU.boundaryField()[patchi].type() == cohesiveLawMultiMatFvPatchVectorField::typeName)
if(DU.boundaryField()[patchi].type() == solidCohesiveFvPatchVectorField::typeName)
{
// cohesiveLawMultiMatFvPatchVectorField& DUpatch =
// refCast<cohesiveLawMultiMatFvPatchVectorField>(DU.boundaryField()[patchi]);
solidCohesiveFvPatchVectorField& DUpatch =
refCast<solidCohesiveFvPatchVectorField>(DU.boundaryField()[patchi]);
GI.boundaryField()[patchi] = DUpatch.GI(); volScalarField GI
GII.boundaryField()[patchi] = DUpatch.GII(); (
damageAndCracks.boundaryField()[patchi] = DUpatch.crackingAndDamage(); IOobject
} (
} "GI",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName
);
volScalarField GII
(
IOobject
(
"GII",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName
);
forAll(DU.boundaryField(), patchi)
{
// if(DU.boundaryField()[patchi].type() == cohesiveLawMultiMatFvPatchVectorField::typeName)
if(DU.boundaryField()[patchi].type() == solidCohesiveFvPatchVectorField::typeName)
{
// cohesiveLawMultiMatFvPatchVectorField& DUpatch =
// refCast<cohesiveLawMultiMatFvPatchVectorField>(DU.boundaryField()[patchi]);
solidCohesiveFvPatchVectorField& DUpatch =
refCast<solidCohesiveFvPatchVectorField>(DU.boundaryField()[patchi]);
GI.boundaryField()[patchi] = DUpatch.GI();
GII.boundaryField()[patchi] = DUpatch.GII();
damageAndCracks.boundaryField()[patchi] = DUpatch.crackingAndDamage();
}
}
//Info << "done" << endl; //Info << "done" << endl;

View file

@ -1,40 +1,41 @@
//- write force displacement to file //- write force displacement to file
if(historyPatchID != -1) if(historyPatchID != -1)
{ {
Info << "Found patch "<<historyPatchName<<", writing y force and displacement to file" Info << "Found patch "<<historyPatchName<<", writing y force and displacement to file"
<< endl; << endl;
//- calculate force in specified direction on topClamp patch //- calculate force in specified direction on topClamp patch
vector direction(0, 1, 0); vector direction(0, 1, 0);
//- for small strain or moving mesh //- for small strain or moving mesh
scalar force = gSum( scalar force = gSum
direction & (
(mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID]) direction &
); (mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID])
);
//- for large strain total lagrangian //- for large strain total lagrangian
// tensorField F = I + gradU.boundaryField()[historyPatchID]; // tensorField F = I + gradU.boundaryField()[historyPatchID];
// vectorField totalForce = mesh.Sf().boundaryField()[historyPatchID] & (sigma.boundaryField()[historyPatchID] & F); // vectorField totalForce = mesh.Sf().boundaryField()[historyPatchID] & (sigma.boundaryField()[historyPatchID] & F);
//vector force = sum( totalForce ); //vector force = sum( totalForce );
//scalar force = force[vector::Y]; //scalar force = force[vector::Y];
//- patchIntegrate utility integrates it this way but this is worng because the sigma tensor should //- patchIntegrate utility integrates it this way but this is worng because the sigma tensor should
//- be dotted with the surface normal to give the actual traction/force //- be dotted with the surface normal to give the actual traction/force
//- you cannot just take the component of the sigma tensor //- you cannot just take the component of the sigma tensor
//scalar forcePatchIntegrateMethod = gSum( //scalar forcePatchIntegrateMethod = gSum(
// mesh.magSf().boundaryField()[historyPatchID] // mesh.magSf().boundaryField()[historyPatchID]
// *sigma.boundaryField()[historyPatchID].component(symmTensor::XY) // *sigma.boundaryField()[historyPatchID].component(symmTensor::XY)
// ); // );
scalar disp = max(U.boundaryField()[historyPatchID].component(vector::Y)); scalar disp = max(U.boundaryField()[historyPatchID].component(vector::Y));
//- write to file //- write to file
if(Pstream::master()) if(Pstream::master())
{ {
OFstream& forceDispFile = *filePtr; OFstream& forceDispFile = *filePtr;
forceDispFile << disp << "\t" << force << endl; forceDispFile << disp << "\t" << force << endl;
} }
} }

View file

@ -10,33 +10,34 @@ else if(divDSigmaExpMethod == "surface")
{ {
divDSigmaExp = fvc::div divDSigmaExp = fvc::div
( (
muf*(mesh.Sf() & fvc::interpolate(gradDU.T())) muf*(mesh.Sf() & fvc::interpolate(gradDU.T()))
+ lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU))) + lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU)))
- (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU)) - (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU))
); );
} }
else if(divDSigmaExpMethod == "decompose") else if(divDSigmaExpMethod == "decompose")
{ {
surfaceTensorField shearGradDU = surfaceTensorField shearGradDU = ((I - n*n) & fvc::interpolate(gradDU));
((I - n*n) & fvc::interpolate(gradDU));
divDSigmaExp = fvc::div divDSigmaExp = fvc::div
( (
mesh.magSf()* mesh.magSf()*
( (
- (muf + lambdaf)*(fvc::snGrad(DU) & (I - n*n)) - (muf + lambdaf)*(fvc::snGrad(DU) & (I - n*n))
+ lambdaf*tr(shearGradDU&(I - n*n))*n + lambdaf*tr(shearGradDU&(I - n*n))*n
+ muf*(shearGradDU&n) + muf*(shearGradDU&n)
) )
); );
} }
else if(divDSigmaExpMethod == "laplacian") else if(divDSigmaExpMethod == "laplacian")
{ {
divDSigmaExp = - fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)") divDSigmaExp =
- fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)")
+ fvc::div(mu*gradDU.T() + lambda*(I*tr(gradDU)), "div(sigma)"); + fvc::div(mu*gradDU.T() + lambda*(I*tr(gradDU)), "div(sigma)");
} }
else else
{ {
FatalError << "divDSigmaExp method " << divDSigmaExpMethod FatalErrorIn(args.executable())
<< " not found!" << endl; << "divDSigmaExp method " << divDSigmaExpMethod << " not found!"
<< abort(FatalError);
} }

View file

@ -63,7 +63,7 @@ int main(int argc, char *argv[])
while(runTime.loop()) while(runTime.loop())
{ {
Info<< "Time: " << runTime.timeName() << nl << endl; Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"

View file

@ -7,18 +7,20 @@ if(leftPatchID == -1)
} }
//- calculate force in x direction on leftClamp patch //- calculate force in x direction on leftClamp patch
scalar leftForce = gSum( scalar leftForce = gSum
vector(1, 0, 0) & (
(mesh.boundary()[leftPatchID].Sf() & sigma.boundaryField()[leftPatchID]) vector(1, 0, 0) &
); (mesh.boundary()[leftPatchID].Sf() & sigma.boundaryField()[leftPatchID])
);
//- patchIntegrate utility integrates it this way but this is worng because the sigma tensor should //- patchIntegrate utility integrates it this way but this is worng because the sigma tensor should
//- be dotted with the surface normal to give the actual traction/force //- be dotted with the surface normal to give the actual traction/force
//- you cannot just take the component of the sigma tensor //- you cannot just take the component of the sigma tensor
//scalar leftForcePatchIntegrateMethod = gSum( //scalar leftForcePatchIntegrateMethod = gSum
// mesh.magSf().boundaryField()[leftPatchID] //(
// *sigma.boundaryField()[leftPatchID].component(symmTensor::XY) // mesh.magSf().boundaryField()[leftPatchID]*
// ); // sigma.boundaryField()[leftPatchID].component(symmTensor::XY)
//);
vector gaugeU1 = vector::zero; vector gaugeU1 = vector::zero;
vector gaugeU2 = vector::zero; vector gaugeU2 = vector::zero;

View file

@ -24,8 +24,8 @@
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimLength, vector::zero) dimensionedVector("zero", dimLength, vector::zero)
); );
volTensorField gradU volTensorField gradU
@ -38,8 +38,8 @@
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedTensor("zero", dimless, tensor::zero) dimensionedTensor("zero", dimless, tensor::zero)
); );
//- increment of Green finite strain tensor //- increment of Green finite strain tensor
@ -53,8 +53,8 @@
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedSymmTensor("zero", dimless, symmTensor::zero) dimensionedSymmTensor("zero", dimless, symmTensor::zero)
); );
//- Green strain tensor //- Green strain tensor
@ -68,8 +68,8 @@
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedSymmTensor("zero", dimless, symmTensor::zero) dimensionedSymmTensor("zero", dimless, symmTensor::zero)
); );
@ -99,8 +99,8 @@
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero) dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero)
); );
constitutiveModel rheology(sigma, DU); constitutiveModel rheology(sigma, DU);

View file

@ -43,105 +43,108 @@ Author
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
# include "setRootCase.H" # include "setRootCase.H"
# include "createTime.H" # include "createTime.H"
# include "createMesh.H" # include "createMesh.H"
# include "createFields.H" # include "createFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl; Info<< "\nStarting time loop\n" << endl;
while(runTime.loop()) while(runTime.loop())
{ {
Info<< "Time: " << runTime.timeName() << nl << endl; Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
int iCorr = 0; int iCorr = 0;
scalar initialResidual = 0; scalar initialResidual = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar relativeResidual = 1.0; scalar relativeResidual = 1.0;
lduMatrix::debug=0; lduMatrix::debug=0;
do do
{ {
DU.storePrevIter(); DU.storePrevIter();
fvVectorMatrix DUEqn fvVectorMatrix DUEqn
( (
fvm::d2dt2(rho, DU) fvm::d2dt2(rho, DU)
== ==
fvm::laplacian(2*mu + lambda, DU, "laplacian(DDU,DU)") fvm::laplacian(2*mu + lambda, DU, "laplacian(DDU,DU)")
+ fvc::div( + fvc::div
-( (mu + lambda) * gradDU ) (
+ ( mu * ( - ( (mu + lambda) * gradDU )
gradDU.T() + (
+ (gradDU & gradU.T()) mu *
+ (gradU & gradDU.T()) (
+ (gradDU & gradDU.T()) gradDU.T()
) ) + (gradDU & gradU.T())
+ ( lambda * tr(DEpsilon) * I ) + (gradU & gradDU.T())
+ ( DSigma & gradU ) + (gradDU & gradDU.T())
+ ( (sigma + DSigma) & gradDU ), )
"div(sigma)" )
) + ( lambda * tr(DEpsilon) * I )
); + ( DSigma & gradU )
+ ( (sigma + DSigma) & gradDU ),
"div(sigma)"
)
);
solverPerf = DUEqn.solve(); solverPerf = DUEqn.solve();
if (iCorr == 0) if (iCorr == 0)
{ {
initialResidual = solverPerf.initialResidual(); initialResidual = solverPerf.initialResidual();
}
DU.relax();
gradDU = fvc::grad(DU);
# include "calculateDEpsilonDSigma.H"
# include "calculateRelativeResidual.H"
Info<< "\tTime " << runTime.value()
<< ", Corrector " << iCorr
<< ", Solving for " << DU.name()
<< " using " << solverPerf.solverName()
<< ", residual = " << solverPerf.initialResidual()
<< ", relative residual = " << relativeResidual
<< ", inner iterations = " << solverPerf.nIterations() << endl;
} }
while
(
solverPerf.initialResidual() > convergenceTolerance
//relativeResidual > convergenceTolerance
&& ++iCorr < nCorr
);
DU.relax(); Info<< nl << "Time " << runTime.value() << ", Solving for " << DU.name()
<< ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual()
<< ", Relative residual = " << relativeResidual
<< ", No outer iterations " << iCorr
<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< endl;
gradDU = fvc::grad(DU); U += DU;
gradU += gradDU;
epsilon += DEpsilon;
sigma += DSigma;
# include "calculateDEpsilonDSigma.H" # include "writeFields.H"
# include "calculateRelativeResidual.H"
Info << "\tTime " << runTime.value() Info<< "ExecutionTime = "
<< ", Corrector " << iCorr << runTime.elapsedCpuTime()
<< ", Solving for " << DU.name() << " s\n\n" << endl;
<< " using " << solverPerf.solverName()
<< ", residual = " << solverPerf.initialResidual()
<< ", relative residual = " << relativeResidual
<< ", inner iterations = " << solverPerf.nIterations() << endl;
}
while
(
solverPerf.initialResidual() > convergenceTolerance
//relativeResidual > convergenceTolerance
&&
++iCorr < nCorr
);
Info << nl << "Time " << runTime.value() << ", Solving for " << DU.name()
<< ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual()
<< ", Relative residual = " << relativeResidual
<< ", No outer iterations " << iCorr
<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< endl;
U += DU;
gradU += gradDU;
epsilon += DEpsilon;
sigma += DSigma;
# include "writeFields.H"
Info<< "ExecutionTime = "
<< runTime.elapsedCpuTime()
<< " s\n\n" << endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;
return(0); return(0);
} }

View file

@ -1,36 +1,36 @@
if (runTime.outputTime()) if (runTime.outputTime())
{ {
volScalarField epsilonEq volScalarField epsilonEq
( (
IOobject IOobject
( (
"epsilonEq", "epsilonEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((2.0/3.0)*magSqr(dev(epsilon))) sqrt((2.0/3.0)*magSqr(dev(epsilon)))
); );
Info<< "Max epsilonEq = " << max(epsilonEq).value() Info<< "Max epsilonEq = " << max(epsilonEq).value()
<< endl; << endl;
volScalarField sigmaEq volScalarField sigmaEq
( (
IOobject IOobject
( (
"sigmaEq", "sigmaEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((3.0/2.0)*magSqr(dev(sigma))) sqrt((3.0/2.0)*magSqr(dev(sigma)))
); );
Info<< "Max sigmaEq = " << max(sigmaEq).value() Info<< "Max sigmaEq = " << max(sigmaEq).value()
<< endl; << endl;
//- Calculate Cauchy stress //- Calculate Cauchy stress
volTensorField F = I + gradU; volTensorField F = I + gradU;
@ -40,70 +40,70 @@ if (runTime.outputTime())
rho = rho/J; rho = rho/J;
volSymmTensorField sigmaCauchy volSymmTensorField sigmaCauchy
( (
IOobject IOobject
( (
"sigmaCauchy", "sigmaCauchy",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
(1/J) * symm(F.T() & sigma & F) (1/J) * symm(F.T() & sigma & F)
); );
//- Cauchy von Mises stress //- Cauchy von Mises stress
volScalarField sigmaCauchyEq volScalarField sigmaCauchyEq
( (
IOobject IOobject
( (
"sigmaCauchyEq", "sigmaCauchyEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((3.0/2.0)*magSqr(dev(sigmaCauchy))) sqrt((3.0/2.0)*magSqr(dev(sigmaCauchy)))
); );
Info<< "Max sigmaCauchyEq = " << max(sigmaCauchyEq).value() Info<< "Max sigmaCauchyEq = " << max(sigmaCauchyEq).value()
<< endl; << endl;
volTensorField Finv = inv(F); volTensorField Finv = inv(F);
volSymmTensorField epsilonAlmansi volSymmTensorField epsilonAlmansi
( (
IOobject IOobject
( (
"epsilonAlmansi", "epsilonAlmansi",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
symm(Finv & epsilon & Finv.T()) symm(Finv & epsilon & Finv.T())
); );
//- boundary traction //- boundary traction
volVectorField traction volVectorField traction
( (
IOobject IOobject
( (
"tractionCauchy", "tractionCauchy",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimForce/dimArea, vector::zero) dimensionedVector("zero", dimForce/dimArea, vector::zero)
); );
forAll(traction.boundaryField(), patchi) forAll(traction.boundaryField(), patchi)
{ {
tensorField Fpatch = I + gradU.boundaryField()[patchi]; tensorField Fpatch = I + gradU.boundaryField()[patchi];
traction.boundaryField()[patchi] = traction.boundaryField()[patchi] =
n.boundaryField()[patchi] & (sigma.boundaryField()[patchi] & Fpatch); n.boundaryField()[patchi] & (sigma.boundaryField()[patchi] & Fpatch);
} }
runTime.write(); runTime.write();
} }

View file

@ -1,33 +1,33 @@
{ {
forAll(mesh.boundary(), patchID) forAll(mesh.boundary(), patchID)
{ {
if(U.boundaryField()[patchID].type() if(U.boundaryField()[patchID].type()
== solidDirectionMixedFvPatchVectorField::typeName == solidDirectionMixedFvPatchVectorField::typeName
) )
{ {
solidDirectionMixedFvPatchVectorField& loadingPatch = solidDirectionMixedFvPatchVectorField& loadingPatch =
refCast<solidDirectionMixedFvPatchVectorField> refCast<solidDirectionMixedFvPatchVectorField>
( (
U.boundaryField()[patchID] U.boundaryField()[patchID]
); );
tensorField Finv = inv(I + gradU); tensorField Finv = inv(I + gradU);
vectorField newN = Finv & n.boundaryField()[patchID]; vectorField newN = Finv & n.boundaryField()[patchID];
newN /= mag(newN); newN /= mag(newN);
loadingPatch.valueFraction() = sqr(newN); loadingPatch.valueFraction() = sqr(newN);
//- set gradient //- set gradient
loadingPatch.refGrad() = loadingPatch.refGrad() =
( (
//Traction //Traction
( (mu.boundaryField()[patchID] + lambda.boundaryField()[patchID]) * (n.boundaryField()[patchID] & gradU.boundaryField()[patchID]) ) ( (mu.boundaryField()[patchID] + lambda.boundaryField()[patchID]) * (n.boundaryField()[patchID] & gradU.boundaryField()[patchID]) )
- ( mu.boundaryField()[patchID] * (n.boundaryField()[patchID] & gradU.boundaryField()[patchID].T()) ) - ( mu.boundaryField()[patchID] * (n.boundaryField()[patchID] & gradU.boundaryField()[patchID].T()) )
- ( mu.boundaryField()[patchID] * ( n.boundaryField()[patchID] & (gradU.boundaryField()[patchID] & gradU.boundaryField()[patchID].T()) ) ) - ( mu.boundaryField()[patchID] * ( n.boundaryField()[patchID] & (gradU.boundaryField()[patchID] & gradU.boundaryField()[patchID].T()) ) )
- ( lambda.boundaryField()[patchID] * tr(gradU.boundaryField()[patchID]) * n.boundaryField()[patchID] ) - ( lambda.boundaryField()[patchID] * tr(gradU.boundaryField()[patchID]) * n.boundaryField()[patchID] )
- ( 0.5 * lambda.boundaryField()[patchID] * tr(gradU.boundaryField()[patchID] & gradU.boundaryField()[patchID].T()) * n.boundaryField()[patchID] ) - ( 0.5 * lambda.boundaryField()[patchID] * tr(gradU.boundaryField()[patchID] & gradU.boundaryField()[patchID].T()) * n.boundaryField()[patchID] )
) )
/ /
(2.0*mu.boundaryField()[patchID] + lambda.boundaryField()[patchID]); (2.0*mu.boundaryField()[patchID] + lambda.boundaryField()[patchID]);
} }
} }
} }

View file

@ -3,19 +3,19 @@ bool solidInterfaceCorr = rheology.solidInterfaceActive();
solidInterface* solidInterfacePtr(NULL); solidInterface* solidInterfacePtr(NULL);
if(solidInterfaceCorr) if(solidInterfaceCorr)
{ {
solidInterfacePtr = &rheology.solInterface(); solidInterfacePtr = &rheology.solInterface();
solidInterfacePtr->modifyProperties(muf, lambdaf); solidInterfacePtr->modifyProperties(muf, lambdaf);
//- solidInterface needs muf and lambdaf to be used for divDSigmaExp //- solidInterface needs muf and lambdaf to be used for divDSigmaExp
// if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose") // if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose")
// { // {
// FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on" // FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on"
// << exit(FatalError); // << exit(FatalError);
// } // }
// if(divDSigmaLargeStrainExpMethod != "surface") // if(divDSigmaLargeStrainExpMethod != "surface")
// { // {
// FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on" // FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on"
// << exit(FatalError); // << exit(FatalError);
// } // }
} }

View file

@ -56,105 +56,104 @@ int main(int argc, char *argv[])
while(runTime.loop()) while(runTime.loop())
{ {
Info<< "Time: " << runTime.timeName() << nl << endl; Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
int iCorr = 0; int iCorr = 0;
scalar initialResidual = 0; scalar initialResidual = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar relativeResidual = 1.0; scalar relativeResidual = 1.0;
lduMatrix::debug = 0; lduMatrix::debug = 0;
do do
{ {
U.storePrevIter(); U.storePrevIter();
surfaceTensorField shearGradU surfaceTensorField shearGradU
( (
"shearGradU", "shearGradU",
(I - sqr(n)) & fvc::interpolate(gradU) (I - sqr(n)) & fvc::interpolate(gradU)
); );
fvVectorMatrix UEqn fvVectorMatrix UEqn
( (
fvm::d2dt2(rho, U) fvm::d2dt2(rho, U)
== ==
fvm::laplacian(2*muf + lambdaf, U, "laplacian(DU,U)") fvm::laplacian(2*muf + lambdaf, U, "laplacian(DU,U)")
// + fvc::div // + fvc::div
// ( // (
// -(mu + lambda)*gradU // -(mu + lambda)*gradU
// + mu*gradU.T() // + mu*gradU.T()
// + mu*(gradU & gradU.T()) // + mu*(gradU & gradU.T())
// + lambda*tr(gradU)*I // + lambda*tr(gradU)*I
// + 0.5*lambda*tr(gradU & gradU.T())*I // + 0.5*lambda*tr(gradU & gradU.T())*I
// + (sigma & gradU), // + (sigma & gradU),
// "div(sigma)" // "div(sigma)"
// ) // )
+ fvc::div + fvc::div
( (
mesh.magSf()* mesh.magSf()*
( (
- (muf + lambdaf)*(fvc::snGrad(U) & (I - n*n)) - (muf + lambdaf)*(fvc::snGrad(U) & (I - n*n))
+ lambdaf*tr(shearGradU & (I - n*n))*n + lambdaf*tr(shearGradU & (I - n*n))*n
+ muf*(shearGradU & n) + muf*(shearGradU & n)
+ muf*(n & fvc::interpolate(gradU & gradU.T())) + muf*(n & fvc::interpolate(gradU & gradU.T()))
+ 0.5*lambdaf*(n*tr(fvc::interpolate(gradU & gradU.T()))) + 0.5*lambdaf*(n*tr(fvc::interpolate(gradU & gradU.T())))
+ (n & fvc::interpolate(sigma & gradU)) + (n & fvc::interpolate(sigma & gradU))
) )
) )
); );
if (solidInterfaceCorr) if (solidInterfaceCorr)
{ {
solidInterfacePtr->correct(UEqn); solidInterfacePtr->correct(UEqn);
} }
solverPerf = UEqn.solve(); solverPerf = UEqn.solve();
if (iCorr == 0) if (iCorr == 0)
{ {
initialResidual = solverPerf.initialResidual(); initialResidual = solverPerf.initialResidual();
} }
U.relax(); U.relax();
//gradU = solidInterfacePtr->grad(U); //gradU = solidInterfacePtr->grad(U);
gradU = fvc::grad(U); gradU = fvc::grad(U);
# include "calculateEpsilonSigma.H" # include "calculateEpsilonSigma.H"
# include "calculateRelativeResidual.H" # include "calculateRelativeResidual.H"
Info<< "\tTime " << runTime.value() Info<< "\tTime " << runTime.value()
<< ", Corrector " << iCorr << ", Corrector " << iCorr
<< ", Solving for " << U.name() << ", Solving for " << U.name()
<< " using " << solverPerf.solverName() << " using " << solverPerf.solverName()
<< ", residual = " << solverPerf.initialResidual() << ", residual = " << solverPerf.initialResidual()
<< ", relative residual = " << relativeResidual << ", relative residual = " << relativeResidual
<< ", inner iterations " << solverPerf.nIterations() << endl; << ", inner iterations " << solverPerf.nIterations() << endl;
} }
while while
( (
solverPerf.initialResidual() > convergenceTolerance solverPerf.initialResidual() > convergenceTolerance
//relativeResidual > convergenceTolerance //relativeResidual > convergenceTolerance
&& && ++iCorr < nCorr
++iCorr < nCorr );
);
Info<< nl << "Time " << runTime.value() << ", Solving for " << U.name() Info<< nl << "Time " << runTime.value() << ", Solving for " << U.name()
<< ", Initial residual = " << initialResidual << ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual() << ", Final residual = " << solverPerf.initialResidual()
<< ", Relative residual = " << relativeResidual << ", Relative residual = " << relativeResidual
<< ", No outer iterations " << iCorr << ", No outer iterations " << iCorr
<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s"
<< endl; << endl;
# include "writeFields.H" # include "writeFields.H"
Info<< "ExecutionTime = " Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< runTime.elapsedCpuTime() << " ClockTime = " << runTime.elapsedClockTime() << " s"
<< " s\n\n" << endl; << endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;

View file

@ -2,7 +2,7 @@
//- move mesh //- move mesh
//--------------------------------------------------// //--------------------------------------------------//
if(min(J.internalField()) > 0) if(min(J.internalField()) > 0)
{ {
Info << "Moving mesh using least squares interpolation" << endl; Info << "Moving mesh using least squares interpolation" << endl;
leastSquaresVolPointInterpolation pointInterpolation(mesh); leastSquaresVolPointInterpolation pointInterpolation(mesh);
@ -11,46 +11,45 @@ if(min(J.internalField()) > 0)
pointMesh pMesh(mesh); pointMesh pMesh(mesh);
wordList types wordList types
( (
pMesh.boundary().size(), pMesh.boundary().size(),
calculatedFvPatchVectorField::typeName calculatedFvPatchVectorField::typeName
); );
pointVectorField pointU pointVectorField pointU
( (
IOobject IOobject
( (
"pointU", "pointU",
runTime.timeName(), runTime.timeName(),
mesh mesh
), ),
pMesh, pMesh,
dimensionedVector("zero", dimLength, vector::zero), dimensionedVector("zero", dimLength, vector::zero),
types types
); );
pointInterpolation.interpolate(U, pointU); pointInterpolation.interpolate(U, pointU);
const vectorField& pointUI = const vectorField& pointUI = pointU.internalField();
pointU.internalField();
//- Move mesh //- Move mesh
vectorField newPoints = mesh.allPoints(); vectorField newPoints = mesh.allPoints();
forAll (pointUI, pointI) forAll (pointUI, pointI)
{ {
newPoints[pointI] += pointUI[pointI]; newPoints[pointI] += pointUI[pointI];
} }
twoDPointCorrector twoDCorrector(mesh); twoDPointCorrector twoDCorrector(mesh);
twoDCorrector.correctPoints(newPoints); twoDCorrector.correctPoints(newPoints);
mesh.movePoints(newPoints); mesh.movePoints(newPoints);
mesh.V00(); mesh.V00();
mesh.moving(false); mesh.moving(false);
} }
else else
{ {
FatalErrorIn(args.executable()) FatalErrorIn(args.executable())
<< "Negative Jacobian" << "Negative Jacobian"
<< exit(FatalError); << exit(FatalError);
} }

View file

@ -1,36 +1,36 @@
if (runTime.outputTime()) if (runTime.outputTime())
{ {
volScalarField epsilonEq volScalarField epsilonEq
( (
IOobject IOobject
( (
"epsilonEq", "epsilonEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((2.0/3.0)*magSqr(dev(epsilon))) sqrt((2.0/3.0)*magSqr(dev(epsilon)))
); );
Info<< "Max epsilonEq = " << max(epsilonEq).value() Info<< "Max epsilonEq = " << max(epsilonEq).value()
<< endl; << endl;
volScalarField sigmaEq volScalarField sigmaEq
( (
IOobject IOobject
( (
"sigmaEq", "sigmaEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((3.0/2.0)*magSqr(dev(sigma))) sqrt((3.0/2.0)*magSqr(dev(sigma)))
); );
Info<< "Max sigmaEq = " << max(sigmaEq).value() Info<< "Max sigmaEq = " << max(sigmaEq).value()
<< endl; << endl;
//- Calculate Cauchy stress //- Calculate Cauchy stress
volTensorField F = I + gradU; volTensorField F = I + gradU;
@ -40,49 +40,49 @@ if (runTime.outputTime())
rho = rho/J; rho = rho/J;
volSymmTensorField sigmaCauchy volSymmTensorField sigmaCauchy
( (
IOobject IOobject
( (
"sigmaCauchy", "sigmaCauchy",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
(1/J) * symm(F.T() & sigma & F) (1/J) * symm(F.T() & sigma & F)
); );
//- Cauchy von Mises stress //- Cauchy von Mises stress
volScalarField sigmaCauchyEq volScalarField sigmaCauchyEq
( (
IOobject IOobject
( (
"sigmaCauchyEq", "sigmaCauchyEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((3.0/2.0)*magSqr(dev(sigmaCauchy))) sqrt((3.0/2.0)*magSqr(dev(sigmaCauchy)))
); );
Info<< "Max sigmaCauchyEq = " << max(sigmaCauchyEq).value() Info<< "Max sigmaCauchyEq = " << max(sigmaCauchyEq).value()
<< endl; << endl;
volTensorField Finv = inv(F); volTensorField Finv = inv(F);
volSymmTensorField epsilonAlmansi volSymmTensorField epsilonAlmansi
( (
IOobject IOobject
( (
"epsilonAlmansi", "epsilonAlmansi",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
symm(Finv & epsilon & Finv.T()) symm(Finv & epsilon & Finv.T())
); );
// volVectorField traction // volVectorField traction
// ( // (
@ -163,4 +163,4 @@ if (runTime.outputTime())
// } // }
runTime.write(); runTime.write();
} }

View file

@ -1,47 +1,43 @@
if(divDSigmaExpMethod == "standard") if(divDSigmaExpMethod == "standard")
{ {
divDSigmaExp = fvc::div divDSigmaExp = fvc::div
( (
mu*gradDU.T() + lambda*(I*tr(gradDU)) - (mu + lambda)*gradDU, mu*gradDU.T() + lambda*(I*tr(gradDU)) - (mu + lambda)*gradDU,
"div(sigma)" "div(sigma)"
);
}
else if(divDSigmaExpMethod == "surface")
{
divDSigmaExp = fvc::div
(
muf*(mesh.Sf() & fvc::interpolate(gradDU.T()))
+ lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU)))
- (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU))
); );
} }
else if(divDSigmaExpMethod == "decompose") else if(divDSigmaExpMethod == "surface")
{ {
surfaceTensorField shearGradDU = divDSigmaExp = fvc::div
((I - n*n)&fvc::interpolate(gradDU)); (
muf*(mesh.Sf() & fvc::interpolate(gradDU.T()))
+ lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU)))
- (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU))
);
}
else if(divDSigmaExpMethod == "decompose")
{
surfaceTensorField shearGradDU = ((I - n*n) & fvc::interpolate(gradDU));
divDSigmaExp = fvc::div divDSigmaExp = fvc::div
( (
mesh.magSf() mesh.magSf()*
*( (
- (muf + lambdaf)*(fvc::snGrad(DU)&(I - n*n)) - (muf + lambdaf)*(fvc::snGrad(DU) & (I - n*n))
+ lambdaf*tr(shearGradDU&(I - n*n))*n + lambdaf*tr(shearGradDU & (I - n*n))*n
+ muf*(shearGradDU&n) + muf*(shearGradDU & n)
) )
); );
} }
else if(divDSigmaExpMethod == "laplacian") else if(divDSigmaExpMethod == "laplacian")
{ {
divDSigmaExp = divDSigmaExp =
- fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)") - fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)")
+ fvc::div + fvc::div(mu*gradDU.T() + lambda*(I*tr(gradDU)), "div(sigma)");
( }
mu*gradDU.T() else
+ lambda*(I*tr(gradDU)), {
"div(sigma)" FatalErrorIn(args.executable())
); << "divDSigmaExp method " << divDSigmaExpMethod << " not found!"
} << abort(FatalError);
else }
{
FatalError << "divDSigmaExp method " << divDSigmaExpMethod << " not found!" << endl;
}

View file

@ -2,30 +2,28 @@
//- sigma explicit non linear explicit terms //- sigma explicit non linear explicit terms
//----------------------------------------------------// //----------------------------------------------------//
if(divDSigmaLargeStrainExpMethod == "standard") if(divDSigmaLargeStrainExpMethod == "standard")
{ {
divDSigmaLargeStrainExp = divDSigmaLargeStrainExp = fvc::div
fvc::div (
( mu*(gradDU & gradDU.T())
mu*(gradDU & gradDU.T()) //+ 0.5*lambda*(gradDU && gradDU)*I //- equivalent to 0.5*lambda*(I*tr(gradDU & gradDU.T()))
//+ 0.5*lambda*(gradDU && gradDU)*I //- equivalent to 0.5*lambda*(I*tr(gradDU & gradDU.T())) + 0.5*lambda*tr(gradDU & gradDU.T())*I
+ 0.5*lambda*tr(gradDU & gradDU.T())*I + ((sigma + DSigma) & gradDU),
+ ((sigma + DSigma) & gradDU), "div(sigma)"
"div(sigma)"
);
}
else if(divDSigmaLargeStrainExpMethod == "surface")
{
divDSigmaLargeStrainExp =
fvc::div
(
muf * (mesh.Sf() & fvc::interpolate(gradDU & gradDU.T()))
+ 0.5*lambdaf * (mesh.Sf() & (fvc::interpolate(gradDU && gradDU)*I))
+ (mesh.Sf() & fvc::interpolate( (sigma + DSigma) & gradDU ))
); );
} }
else else if(divDSigmaLargeStrainExpMethod == "surface")
{ {
FatalError divDSigmaLargeStrainExp = fvc::div
<< "divDSigmaLargeStrainMethod not found!" (
<< exit(FatalError); muf * (mesh.Sf() & fvc::interpolate(gradDU & gradDU.T()))
} + 0.5*lambdaf * (mesh.Sf() & (fvc::interpolate(gradDU && gradDU)*I))
+ (mesh.Sf() & fvc::interpolate( (sigma + DSigma) & gradDU ))
);
}
else
{
FatalError
<< "divDSigmaLargeStrainMethod not found!"
<< exit(FatalError);
}

View file

@ -15,59 +15,57 @@
FieldField<Field, vector> extraVecs(ptc.size()); FieldField<Field, vector> extraVecs(ptc.size());
{ {
const labelListList& pfaces = mesh.pointFaces(); const labelListList& pfaces = mesh.pointFaces();
const volVectorField& centres = mesh.C(); const volVectorField& centres = mesh.C();
const fvBoundaryMesh& bm = mesh.boundary(); const fvBoundaryMesh& bm = mesh.boundary();
forAll (ptc, pointI) forAll (ptc, pointI)
{ {
const label curPoint = ptc[pointI]; const label curPoint = ptc[pointI];
const labelList& curFaces = pfaces[curPoint]; const labelList& curFaces = pfaces[curPoint];
// extraVecs.hook(new vectorField(curFaces.size())); //- no hook function // extraVecs.hook(new vectorField(curFaces.size())); //- no hook function
extraVecs.set extraVecs.set
(
pointI,
new vectorField(curFaces.size())
);
vectorField& curExtraVectors = extraVecs[pointI];
label nFacesAroundPoint = 0;
const vector& pointLoc = mesh.points()[curPoint];
// Go through all the faces
forAll (curFaces, faceI)
{
if (!mesh.isInternalFace(curFaces[faceI]))
{
// This is a boundary face. If not in the empty patch
// or coupled calculate the extrapolation vector
label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
if
( (
!isA<emptyFvPatch>(bm[patchID]) pointI,
&& !bm[patchID].coupled() new vectorField(curFaces.size())
) );
vectorField& curExtraVectors = extraVecs[pointI];
label nFacesAroundPoint = 0;
const vector& pointLoc = mesh.points()[curPoint];
// Go through all the faces
forAll (curFaces, faceI)
{ {
// Found a face for extrapolation if (!mesh.isInternalFace(curFaces[faceI]))
curExtraVectors[nFacesAroundPoint] = {
pointLoc // This is a boundary face. If not in the empty patch
- centres.boundaryField()[patchID] // or coupled calculate the extrapolation vector
[bm[patchID].patch().whichFace(curFaces[faceI])]; label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
nFacesAroundPoint++; if
(
!isA<emptyFvPatch>(bm[patchID]) && !bm[patchID].coupled()
)
{
// Found a face for extrapolation
curExtraVectors[nFacesAroundPoint] =
pointLoc
- centres.boundaryField()[patchID]
[bm[patchID].patch().whichFace(curFaces[faceI])];
nFacesAroundPoint++;
}
}
} }
}
}
curExtraVectors.setSize(nFacesAroundPoint); curExtraVectors.setSize(nFacesAroundPoint);
} }
} }

View file

@ -8,114 +8,114 @@
FieldField<Field, scalar> w(ptc.size()); FieldField<Field, scalar> w(ptc.size());
{ {
const labelListList& pf = mesh.pointFaces(); const labelListList& pf = mesh.pointFaces();
const volVectorField& centres = mesh.C(); const volVectorField& centres = mesh.C();
const fvBoundaryMesh& bm = mesh.boundary(); const fvBoundaryMesh& bm = mesh.boundary();
pointScalarField volPointSumWeights pointScalarField volPointSumWeights
( (
IOobject IOobject
(
"volPointSumWeights",
mesh.polyMesh::instance(),
mesh
),
pMesh,
dimensionedScalar("zero", dimless, 0)
);
forAll (ptc, pointI)
{
const label curPoint = ptc[pointI];
const labelList& curFaces = pf[curPoint];
//w.hook(new scalarField(curFaces.size())); //philipc no hook function
w.set
(
pointI,
new scalarField(curFaces.size())
);
scalarField& curWeights = w[pointI];
label nFacesAroundPoint = 0;
const vector& pointLoc = mesh.points()[curPoint];
// Go through all the faces
forAll (curFaces, faceI)
{
if (!mesh.isInternalFace(curFaces[faceI]))
{
// This is a boundary face. If not in the empty patch
// or coupled calculate the extrapolation vector
label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
if
( (
!isA<emptyFvPatch>(bm[patchID]) "volPointSumWeights",
&& !( mesh.polyMesh::instance(),
bm[patchID].coupled() mesh
//&& Pstream::parRun() ),
//&& !mesh.parallelData().cyclicParallel() pMesh,
) dimensionedScalar("zero", dimless, 0)
)
{
curWeights[nFacesAroundPoint] =
1.0/mag
(
pointLoc
- centres.boundaryField()[patchID]
[
bm[patchID].patch().whichFace(curFaces[faceI])
]
);
nFacesAroundPoint++;
}
}
}
// Reset the sizes of the local weights
curWeights.setSize(nFacesAroundPoint);
// Collect the sum of weights for parallel correction
volPointSumWeights[curPoint] += sum(curWeights);
}
// Do parallel correction of weights
// Update coupled boundaries
// Work-around for cyclic parallels.
/*if (Pstream::parRun() && !mesh.parallelData().cyclicParallel())
{
forAll (volPointSumWeights.boundaryField(), patchI)
{
if (volPointSumWeights.boundaryField()[patchI].coupled())
{
volPointSumWeights.boundaryField()[patchI].initAddField();
}
}
forAll (volPointSumWeights.boundaryField(), patchI)
{
if (volPointSumWeights.boundaryField()[patchI].coupled())
{
volPointSumWeights.boundaryField()[patchI].addField
(
volPointSumWeights.internalField()
); );
forAll (ptc, pointI)
{
const label curPoint = ptc[pointI];
const labelList& curFaces = pf[curPoint];
//w.hook(new scalarField(curFaces.size())); //philipc no hook function
w.set
(
pointI,
new scalarField(curFaces.size())
);
scalarField& curWeights = w[pointI];
label nFacesAroundPoint = 0;
const vector& pointLoc = mesh.points()[curPoint];
// Go through all the faces
forAll (curFaces, faceI)
{
if (!mesh.isInternalFace(curFaces[faceI]))
{
// This is a boundary face. If not in the empty patch
// or coupled calculate the extrapolation vector
label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
if
(
!isA<emptyFvPatch>(bm[patchID])
&& !(
bm[patchID].coupled()
//&& Pstream::parRun()
//&& !mesh.parallelData().cyclicParallel()
)
)
{
curWeights[nFacesAroundPoint] =
1.0/mag
(
pointLoc
- centres.boundaryField()[patchID]
[
bm[patchID].patch().whichFace(curFaces[faceI])
]
);
nFacesAroundPoint++;
}
}
}
// Reset the sizes of the local weights
curWeights.setSize(nFacesAroundPoint);
// Collect the sum of weights for parallel correction
volPointSumWeights[curPoint] += sum(curWeights);
} }
}
// Do parallel correction of weights
// Update coupled boundaries
// Work-around for cyclic parallels.
/*if (Pstream::parRun() && !mesh.parallelData().cyclicParallel())
{
forAll (volPointSumWeights.boundaryField(), patchI)
{
if (volPointSumWeights.boundaryField()[patchI].coupled())
{
volPointSumWeights.boundaryField()[patchI].initAddField();
}
}
forAll (volPointSumWeights.boundaryField(), patchI)
{
if (volPointSumWeights.boundaryField()[patchI].coupled())
{
volPointSumWeights.boundaryField()[patchI].addField
(
volPointSumWeights.internalField()
);
}
}
}*/ }*/
// Re-scale the weights for the current point // Re-scale the weights for the current point
forAll (ptc, pointI) forAll (ptc, pointI)
{ {
w[pointI] /= volPointSumWeights[ptc[pointI]]; w[pointI] /= volPointSumWeights[ptc[pointI]];
} }
} }

View file

@ -92,31 +92,31 @@
//- explicit terms in the momentum equation //- explicit terms in the momentum equation
volVectorField divDSigmaExp volVectorField divDSigmaExp
( (
IOobject IOobject
( (
"divDSigmaExp", "divDSigmaExp",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimensionSet(1, -2, -2, 0, 0, 0, 0), vector::zero) dimensionedVector("zero", dimensionSet(1, -2, -2, 0, 0, 0, 0), vector::zero)
); );
volVectorField divDSigmaLargeStrainExp volVectorField divDSigmaLargeStrainExp
( (
IOobject IOobject
( (
"divDSigmaLargeStrainExp", "divDSigmaLargeStrainExp",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimensionSet(1, -2, -2, 0, 0, 0, 0), vector::zero) dimensionedVector("zero", dimensionSet(1, -2, -2, 0, 0, 0, 0), vector::zero)
); );
constitutiveModel rheology(sigma, DU); constitutiveModel rheology(sigma, DU);

View file

@ -4,26 +4,26 @@ solidInterface* solidInterfacePtr(NULL);
{ {
const dictionary& stressControl = const dictionary& stressControl =
mesh.solutionDict().subDict("solidMechanics"); mesh.solutionDict().subDict("solidMechanics");
solidInterfaceCorr = Switch(stressControl.lookup("solidInterface")); solidInterfaceCorr = Switch(stressControl.lookup("solidInterface"));
if(solidInterfaceCorr) if(solidInterfaceCorr)
{ {
Info << "Creating solid interface correction" << endl; Info << "Creating solid interface correction" << endl;
solidInterfacePtr = new solidInterface(mesh, rheology); solidInterfacePtr = new solidInterface(mesh, rheology);
solidInterfacePtr->modifyProperties(muf, lambdaf); solidInterfacePtr->modifyProperties(muf, lambdaf);
//- solidInterface needs muf and lambdaf to be used for divDSigmaExp //- solidInterface needs muf and lambdaf to be used for divDSigmaExp
if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose") if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose")
{ {
FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on" FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on"
<< exit(FatalError); << exit(FatalError);
} }
if(divDSigmaLargeStrainExpMethod == "surface") if(divDSigmaLargeStrainExpMethod == "surface")
{ {
FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on" FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on"
<< exit(FatalError); << exit(FatalError);
} }
} }
} }

View file

@ -3,20 +3,19 @@ bool solidInterfaceCorr = rheology.solidInterfaceActive();
solidInterface* solidInterfacePtr(NULL); solidInterface* solidInterfacePtr(NULL);
if(solidInterfaceCorr) if(solidInterfaceCorr)
{ {
solidInterfacePtr = &rheology.solInterface(); solidInterfacePtr = &rheology.solInterface();
solidInterfacePtr->modifyProperties(muf, lambdaf); solidInterfacePtr->modifyProperties(muf, lambdaf);
//- solidInterface needs muf and lambdaf to be used for divDSigmaExp //- solidInterface needs muf and lambdaf to be used for divDSigmaExp
if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose") if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose")
{ {
FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on" FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on"
<< exit(FatalError); << exit(FatalError);
} }
if(divDSigmaLargeStrainExpMethod != "surface") if(divDSigmaLargeStrainExpMethod != "surface")
{ {
FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on" FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on"
<< exit(FatalError); << exit(FatalError);
} }
} }

View file

@ -52,100 +52,101 @@ Author
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
# include "setRootCase.H" # include "setRootCase.H"
# include "createTime.H" # include "createTime.H"
# include "createMesh.H" # include "createMesh.H"
# include "createFields.H" # include "createFields.H"
# include "readDivDSigmaExpMethod.H" # include "readDivDSigmaExpMethod.H"
# include "readDivDSigmaLargeStrainExpMethod.H" # include "readDivDSigmaLargeStrainExpMethod.H"
# include "readMoveMeshMethod.H" # include "readMoveMeshMethod.H"
# include "createSolidInterfaceNonLin.H" # include "createSolidInterfaceNonLin.H"
# include "findGlobalFaceZones.H" # include "findGlobalFaceZones.H"
//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info << "\nStarting time loop\n" << endl; Info<< "\nStarting time loop\n" << endl;
for (runTime++; !runTime.end(); runTime++) while(runTime.loop())
{ {
Info<< "Time = " << runTime.timeName() << nl << endl; Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
int iCorr = 0; int iCorr = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar initialResidual = 1.0; scalar initialResidual = 1.0;
scalar relativeResidual = 1.0; scalar relativeResidual = 1.0;
lduMatrix::debug = 0; lduMatrix::debug = 0;
do do
{ {
DU.storePrevIter(); DU.storePrevIter();
# include "calculateDivDSigmaExp.H" # include "calculateDivDSigmaExp.H"
# include "calculateDivDSigmaLargeStrainExp.H" # include "calculateDivDSigmaLargeStrainExp.H"
//- Updated lagrangian momentum equation //- Updated lagrangian momentum equation
fvVectorMatrix DUEqn fvVectorMatrix DUEqn
( (
fvm::d2dt2(rho,DU) fvm::d2dt2(rho,DU)
== ==
fvm::laplacian(2*muf + lambdaf, DU, "laplacian(DDU,DU)") fvm::laplacian(2*muf + lambdaf, DU, "laplacian(DDU,DU)")
+ divDSigmaExp + divDSigmaExp
+ divDSigmaLargeStrainExp + divDSigmaLargeStrainExp
); );
if (solidInterfaceCorr) if (solidInterfaceCorr)
{ {
solidInterfacePtr->correct(DUEqn); solidInterfacePtr->correct(DUEqn);
} }
solverPerf = DUEqn.solve(); solverPerf = DUEqn.solve();
if (iCorr == 0) if (iCorr == 0)
{ {
initialResidual = solverPerf.initialResidual(); initialResidual = solverPerf.initialResidual();
} }
DU.relax(); DU.relax();
gradDU = fvc::grad(DU); gradDU = fvc::grad(DU);
# include "calculateDEpsilonDSigma.H" # include "calculateDEpsilonDSigma.H"
# include "calculateRelativeResidual.H" # include "calculateRelativeResidual.H"
Info << "\tTime " << runTime.value() Info<< "\tTime " << runTime.value()
<< ", Corrector " << iCorr << ", Corrector " << iCorr
<< ", Solving for " << DU.name() << ", Solving for " << DU.name()
<< " using " << solverPerf.solverName() << " using " << solverPerf.solverName()
<< ", res = " << solverPerf.initialResidual() << ", res = " << solverPerf.initialResidual()
<< ", rel res = " << relativeResidual << ", rel res = " << relativeResidual
<< ", inner iters " << solverPerf.nIterations() << endl; << ", inner iters " << solverPerf.nIterations() << endl;
} }
while while
( (
//solverPerf.initialResidual() > convergenceTolerance //solverPerf.initialResidual() > convergenceTolerance
relativeResidual > convergenceTolerance relativeResidual > convergenceTolerance
&& ++iCorr < nCorr && ++iCorr < nCorr
); );
Info << nl << "Time " << runTime.value() << ", Solving for " << DU.name() Info << nl << "Time " << runTime.value() << ", Solving for " << DU.name()
<< ", Initial residual = " << initialResidual << ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual() << ", Final residual = " << solverPerf.initialResidual()
<< ", No outer iterations " << iCorr << endl; << ", No outer iterations " << iCorr << endl;
# include "moveMesh.H" # include "moveMesh.H"
# include "rotateFields.H" # include "rotateFields.H"
# include "writeFields.H" # include "writeFields.H"
Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s"
<< endl; << endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;
return(0); return(0);
} }
// ************************************************************************* // // ************************************************************************* //

View file

@ -8,26 +8,26 @@ const fvBoundaryMesh& bm = mesh.boundary();
forAll (bm, patchI) forAll (bm, patchI)
{ {
// If the patch is empty, skip it // If the patch is empty, skip it
// If the patch is coupled, and there are no cyclic parallels, skip it // If the patch is coupled, and there are no cyclic parallels, skip it
if if
( (
!isA<emptyFvPatch>(bm[patchI]) !isA<emptyFvPatch>(bm[patchI])
&& !( && !(
bm[patchI].coupled() bm[patchI].coupled()
//&& Pstream::parRun() //&& Pstream::parRun()
//&& !mesh.parallelData().cyclicParallel() //&& !mesh.parallelData().cyclicParallel()
) )
) )
{ {
const labelList& bp = bm[patchI].patch().boundaryPoints(); const labelList& bp = bm[patchI].patch().boundaryPoints();
const labelList& meshPoints = bm[patchI].patch().meshPoints(); const labelList& meshPoints = bm[patchI].patch().meshPoints();
forAll (bp, pointI) forAll (bp, pointI)
{ {
pointsCorrectionMap.insert(meshPoints[bp[pointI]]); pointsCorrectionMap.insert(meshPoints[bp[pointI]]);
} }
} }
} }

View file

@ -2,7 +2,7 @@
//- move mesh //- move mesh
//--------------------------------------------------// //--------------------------------------------------//
// if(min(J.internalField()) > 0) // if(min(J.internalField()) > 0)
{ {
Info << "Move solid mesh using inverse distance interpolation" << endl; Info << "Move solid mesh using inverse distance interpolation" << endl;
// Create point mesh // Create point mesh
@ -12,23 +12,23 @@
volPointInterpolation pointInterpolation(mesh); volPointInterpolation pointInterpolation(mesh);
wordList types wordList types
( (
pMesh.boundary().size(), pMesh.boundary().size(),
calculatedFvPatchVectorField::typeName calculatedFvPatchVectorField::typeName
); );
pointVectorField pointDU pointVectorField pointDU
( (
IOobject IOobject
( (
"pointDU", "pointDU",
runTime.timeName(), runTime.timeName(),
mesh mesh
), ),
pMesh, pMesh,
dimensionedVector("zero", dimLength, vector::zero), dimensionedVector("zero", dimLength, vector::zero),
types types
); );
// Calculate mesh points displacement // Calculate mesh points displacement
pointInterpolation.interpolate(DU, pointDU); pointInterpolation.interpolate(DU, pointDU);
@ -36,27 +36,27 @@
//- correct edge interpolation //- correct edge interpolation
//- this is the stuff from edgeCorrectedVolPointInterpolation but //- this is the stuff from edgeCorrectedVolPointInterpolation but
//- that class no longer works //- that class no longer works
# include "performEdgeCorrectedVolPointInterpolation.H" # include "performEdgeCorrectedVolPointInterpolation.H"
const vectorField& pointDUI = const vectorField& pointDUI =
pointDU.internalField(); pointDU.internalField();
//- see the effect of correctBCs //- see the effect of correctBCs
// Move mesh // Move mesh
vectorField newPoints = mesh.allPoints(); vectorField newPoints = mesh.allPoints();
forAll (pointDUI, pointI) forAll (pointDUI, pointI)
{ {
newPoints[pointI] += pointDUI[pointI]; newPoints[pointI] += pointDUI[pointI];
} }
twoDPointCorrector twoDCorrector(mesh); twoDPointCorrector twoDCorrector(mesh);
twoDCorrector.correctPoints(newPoints); twoDCorrector.correctPoints(newPoints);
mesh.movePoints(newPoints); mesh.movePoints(newPoints);
mesh.V00(); mesh.V00();
mesh.moving(false); mesh.moving(false);
} }
// else // else
// { // {
// FatalErrorIn(args.executable()) // FatalErrorIn(args.executable())

View file

@ -2,7 +2,7 @@
//- move mesh //- move mesh
//--------------------------------------------------// //--------------------------------------------------//
{ {
//Info << "Moving mesh using least squares interpolation" << endl; //Info << "Moving mesh using least squares interpolation" << endl;
leastSquaresVolPointInterpolation pointInterpolation(mesh); leastSquaresVolPointInterpolation pointInterpolation(mesh);
@ -112,4 +112,4 @@
// Update n // Update n
n = mesh.Sf()/mesh.magSf(); n = mesh.Sf()/mesh.magSf();
} }

View file

@ -7,38 +7,40 @@ pointVectorField& pf = pointDU;
// Do the correction // Do the correction
//GeometricField<Type, pointPatchField, pointMesh> pfCorr //GeometricField<Type, pointPatchField, pointMesh> pfCorr
/*pointVectorField pfCorr /*
pointVectorField pfCorr
( (
IOobject IOobject
( (
// "edgeCorrectedVolPointInterpolate(" + vf.name() + ")Corr", // "edgeCorrectedVolPointInterpolate(" + vf.name() + ")Corr",
"edgeCorrectedVolPointInterpolate(" + DU.name() + ")Corr", "edgeCorrectedVolPointInterpolate(" + DU.name() + ")Corr",
//vf.instance(), //vf.instance(),
DU, DU,
pMesh, pMesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
pMesh, pMesh,
//dimensioned<Type>("zero", pf.dimensions(), pTraits<Type>::zero), //dimensioned<Type>("zero", pf.dimensions(), pTraits<Type>::zero),
dimensionedVector("zero", pf.dimensions(), vector::zero), dimensionedVector("zero", pf.dimensions(), vector::zero),
pf.boundaryField().types() pf.boundaryField().types()
);*/ );
*/
pointVectorField pfCorr pointVectorField pfCorr
( (
IOobject IOobject
( (
"pointDUcorr", "pointDUcorr",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
pMesh, pMesh,
dimensionedVector("vector", dimLength, vector::zero), dimensionedVector("vector", dimLength, vector::zero),
"calculated" "calculated"
); );
//const labelList& ptc = boundaryPoints(); //const labelList& ptc = boundaryPoints();
#include "findBoundaryPoints.H" #include "findBoundaryPoints.H"
@ -57,64 +59,68 @@ const labelListList& PointFaces = mesh.pointFaces();
forAll (ptc, pointI) forAll (ptc, pointI)
{ {
const label curPoint = ptc[pointI]; const label curPoint = ptc[pointI];
const labelList& curFaces = PointFaces[curPoint]; const labelList& curFaces = PointFaces[curPoint];
label fI = 0; label fI = 0;
// Go through all the faces // Go through all the faces
forAll (curFaces, faceI) forAll (curFaces, faceI)
{ {
if (!mesh.isInternalFace(curFaces[faceI])) if (!mesh.isInternalFace(curFaces[faceI]))
{
// This is a boundary face. If not in the empty patch
// or coupled calculate the extrapolation vector
label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
if
(
!isA<emptyFvPatch>(mesh.boundary()[patchID])
&& !mesh.boundary()[patchID].coupled()
)
{ {
label faceInPatchID = // This is a boundary face. If not in the empty patch
bm[patchID].patch().whichFace(curFaces[faceI]); // or coupled calculate the extrapolation vector
label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
pfCorr[curPoint] += if
w[pointI][fI]* (
( !isA<emptyFvPatch>(mesh.boundary()[patchID])
extraVecs[pointI][fI] && !mesh.boundary()[patchID].coupled()
& gradDU.boundaryField()[patchID][faceInPatchID] )
); {
label faceInPatchID =
bm[patchID].patch().whichFace(curFaces[faceI]);
fI++; pfCorr[curPoint] +=
w[pointI][fI]*
(
extraVecs[pointI][fI]
& gradDU.boundaryField()[patchID][faceInPatchID]
);
fI++;
}
} }
} }
}
} }
// Update coupled boundaries // Update coupled boundaries
/*forAll (pfCorr.boundaryField(), patchI) /*
forAll (pfCorr.boundaryField(), patchI)
{ {
if (pfCorr.boundaryField()[patchI].coupled()) if (pfCorr.boundaryField()[patchI].coupled())
{ {
pfCorr.boundaryField()[patchI].initAddField(); pfCorr.boundaryField()[patchI].initAddField();
} }
}*/ }
*/
/*forAll (pfCorr.boundaryField(), patchI) /*
forAll (pfCorr.boundaryField(), patchI)
{ {
if (pfCorr.boundaryField()[patchI].coupled()) if (pfCorr.boundaryField()[patchI].coupled())
{ {
pfCorr.boundaryField()[patchI].addField(pfCorr.internalField()); pfCorr.boundaryField()[patchI].addField(pfCorr.internalField());
} }
}*/ }
*/
//Info << "pfCorr: " << pfCorr << endl; //Info << "pfCorr: " << pfCorr << endl;
pfCorr.correctBoundaryConditions(); pfCorr.correctBoundaryConditions();
//pfCorr.write(); //pfCorr.write();

View file

@ -1,36 +1,36 @@
if (runTime.outputTime()) if (runTime.outputTime())
{ {
volScalarField epsilonEq volScalarField epsilonEq
( (
IOobject IOobject
( (
"epsilonEq", "epsilonEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((2.0/3.0)*magSqr(dev(epsilon))) sqrt((2.0/3.0)*magSqr(dev(epsilon)))
); );
Info<< "Max epsilonEq = " << max(epsilonEq).value() Info<< "Max epsilonEq = " << max(epsilonEq).value()
<< endl; << endl;
volScalarField sigmaEq volScalarField sigmaEq
( (
IOobject IOobject
( (
"sigmaEq", "sigmaEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((3.0/2.0)*magSqr(dev(sigma))) sqrt((3.0/2.0)*magSqr(dev(sigma)))
); );
Info<< "Max sigmaEq = " << max(sigmaEq).value() Info<< "Max sigmaEq = " << max(sigmaEq).value()
<< endl; << endl;
runTime.write(); runTime.write();
} }

View file

@ -6,26 +6,24 @@ aitkenDelta = (U - U.prevIter()) / aitkenInitialRes;
// update relaxation factor // update relaxation factor
if(iCorr == 0) if(iCorr == 0)
{ {
aitkenTheta = 0.01; aitkenTheta = 0.01;
} }
else else
{ {
vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField(); vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField();
//scalar sumMagB = gSum(mag(b)); //scalar sumMagB = gSum(mag(b));
scalar sumMagB = gSum(magSqr(b)); scalar sumMagB = gSum(magSqr(b));
if(sumMagB < SMALL) if(sumMagB < SMALL)
{ {
//Warning << "Aitken under-relaxation: denominator less then SMALL" //Warning << "Aitken under-relaxation: denominator less then SMALL"
// << endl; // << endl;
sumMagB += SMALL; sumMagB += SMALL;
} }
aitkenTheta = -aitkenTheta* aitkenTheta = -aitkenTheta*
gSum(aitkenDelta.prevIter().internalField() & b) gSum(aitkenDelta.prevIter().internalField() & b)/sumMagB;
/ }
sumMagB;
}
// correction to the latest U // correction to the latest U
U += aitkenTheta*aitkenDelta*aitkenInitialRes; U += aitkenTheta*aitkenDelta*aitkenInitialRes;

View file

@ -1,25 +1,27 @@
if(divSigmaExpMethod == "standard") if(divSigmaExpMethod == "standard")
{ {
//- calculating the full gradient has good convergence and no high freq oscillations //- calculating the full gradient has good convergence and no high freq oscillations
divSigmaExp = fvc::div(C && epsilon) - fvc::div(K & gradU); divSigmaExp = fvc::div(C && epsilon) - fvc::div(K & gradU);
} }
else if(divSigmaExpMethod == "surface") else if(divSigmaExpMethod == "surface")
{ {
//- this form seems to have the best convergence //- this form seems to have the best convergence
divSigmaExp = divSigmaExp = fvc::div
fvc::div(mesh.magSf()* (
mesh.magSf()*
( (
(n&(Cf && fvc::interpolate(symm(gradU)))) (n & (Cf && fvc::interpolate(symm(gradU))))
- (n&(Kf & fvc::interpolate(gradU))) - (n & (Kf & fvc::interpolate(gradU)))
) )
); );
} }
else if(divSigmaExpMethod == "laplacian") else if(divSigmaExpMethod == "laplacian")
{ {
//- causes high freq oscillations and slow convergence //- causes high freq oscillations and slow convergence
divSigmaExp = fvc::div(sigma) - fvc::laplacian(K,U); divSigmaExp = fvc::div(sigma) - fvc::laplacian(K, U);
} }
else else
{ {
FatalError << "divSigmaExp method " << divSigmaExpMethod << " not found!" << endl; FatalErrorIn(args.executable())
} << "divSigmaExp method " << divSigmaExpMethod << " not found!" << endl;
}

View file

@ -1,19 +1,19 @@
{ {
// force residual is the net force on the model // force residual is the net force on the model
// this should got to zero in a converged steady state model // this should got to zero in a converged steady state model
// should be altered for parallel runs // should be altered for parallel runs
vector netForce = vector::zero; vector netForce = vector::zero;
forAll(mesh.boundary(), patchi) forAll(mesh.boundary(), patchi)
{ {
netForce += netForce += sum
sum(
mesh.Sf().boundaryField()[patchi]
&
( (
2*mu.boundaryField()[patchi]*symm(gradU.boundaryField()[patchi]) mesh.Sf().boundaryField()[patchi]
+ lambda*tr(gradU.boundaryField()[patchi])*I &
) (
2*mu.boundaryField()[patchi]*symm(gradU.boundaryField()[patchi])
+ lambda*tr(gradU.boundaryField()[patchi])*I
)
); );
} }
forceResidual = mag(netForce); forceResidual = mag(netForce);
} }

View file

@ -1,22 +1,22 @@
{ {
surfaceVectorField n = mesh.Sf()/mesh.magSf(); surfaceVectorField n = mesh.Sf()/mesh.magSf();
// traction = (n&fvc::interpolate(sigma)); // traction = (n & fvc::interpolate(sigma));
// surfaceTensorField sGradU = // surfaceTensorField sGradU =
// ((I - n*n)&fvc::interpolate(gradU)); // ((I - n*n) & fvc::interpolate(gradU));
// traction = // traction =
// (2*mu + lambda)*snGradU // (2*mu + lambda)*snGradU
// - (mu + lambda)*(snGradU&(I - n*n)) // - (mu + lambda)*(snGradU&(I - n*n))
// + mu*(sGradU&n) // + mu*(sGradU & n)
// + lambda*tr(sGradU&(I - n*n))*n; // + lambda*tr(sGradU&(I - n*n))*n;
// traction = // traction =
// (2*mu + lambda)*fvc::snGrad(U) // (2*mu + lambda)*fvc::snGrad(U)
// - (mu + lambda)*(n&sGradU) // - (mu + lambda)*(n & sGradU)
// + mu*(sGradU&n) // + mu*(sGradU & n)
// + lambda*tr(sGradU)*n; // + lambda*tr(sGradU)*n;
// philipc // philipc
// I am having trouble with back-calculation of interface tractions from solid interface // I am having trouble with back-calculation of interface tractions from solid interface
@ -27,15 +27,15 @@
traction = (n&fvc::interpolate(sigma)); traction = (n&fvc::interpolate(sigma));
// forAll(traction.boundaryField(), patchi) // forAll(traction.boundaryField(), patchi)
// { // {
// if (mesh.boundary()[patchi].type() == "cohesive") // if (mesh.boundary()[patchi].type() == "cohesive")
// { // {
// forAll(traction.boundaryField()[patchi], facei) // forAll(traction.boundaryField()[patchi], facei)
// { // {
// Pout << "face " << facei << " with traction magnitude " // Pout << "face " << facei << " with traction magnitude "
// << mag(traction.boundaryField()[patchi][facei])/1e6 << " MPa and traction " // << mag(traction.boundaryField()[patchi][facei])/1e6 << " MPa and traction "
// << traction.boundaryField()[patchi][facei]/1e6 << " MPa" << endl; // << traction.boundaryField()[patchi][facei]/1e6 << " MPa" << endl;
// } // }
// } // }
// } // }
} }

View file

@ -1,53 +1,53 @@
label cohesivePatchID = -1; label cohesivePatchID = -1;
solidCohesiveFvPatchVectorField* cohesivePatchUPtr = NULL; solidCohesiveFvPatchVectorField* cohesivePatchUPtr = NULL;
solidCohesiveFixedModeMixFvPatchVectorField* cohesivePatchUFixedModePtr = NULL; solidCohesiveFixedModeMixFvPatchVectorField* cohesivePatchUFixedModePtr = NULL;
forAll (U.boundaryField(), patchI) forAll (U.boundaryField(), patchI)
{ {
if (isA<solidCohesiveFvPatchVectorField>(U.boundaryField()[patchI])) if (isA<solidCohesiveFvPatchVectorField>(U.boundaryField()[patchI]))
{ {
cohesivePatchID = patchI; cohesivePatchID = patchI;
cohesivePatchUPtr = cohesivePatchUPtr =
&refCast<solidCohesiveFvPatchVectorField> &refCast<solidCohesiveFvPatchVectorField>
( (
U.boundaryField()[cohesivePatchID] U.boundaryField()[cohesivePatchID]
); );
break; break;
}
else if (isA<solidCohesiveFixedModeMixFvPatchVectorField>(U.boundaryField()[patchI]))
{
cohesivePatchID = patchI;
cohesivePatchUFixedModePtr =
&refCast<solidCohesiveFixedModeMixFvPatchVectorField>
(
U.boundaryField()[cohesivePatchID]
);
break;
} }
else if (isA<solidCohesiveFixedModeMixFvPatchVectorField>(U.boundaryField()[patchI]))
{
cohesivePatchID = patchI;
cohesivePatchUFixedModePtr =
&refCast<solidCohesiveFixedModeMixFvPatchVectorField>
(
U.boundaryField()[cohesivePatchID]
);
break;
}
} }
if(cohesivePatchID == -1) if(cohesivePatchID == -1)
{ {
FatalErrorIn(args.executable()) FatalErrorIn(args.executable())
<< "Can't find cohesiveLawFvPatch" << nl << "Can't find cohesiveLawFvPatch" << nl
<< "One of the boundary patches in " << U.name() << ".boundaryField() " << "One of the boundary patches in " << U.name() << ".boundaryField() "
<< "should be of type " << solidCohesiveFvPatchVectorField::typeName << "should be of type " << solidCohesiveFvPatchVectorField::typeName
<< "or " << solidCohesiveFixedModeMixFvPatchVectorField::typeName << "or " << solidCohesiveFixedModeMixFvPatchVectorField::typeName
<< abort(FatalError); << abort(FatalError);
} }
// solidCohesiveFvPatchVectorField& cohesivePatchU = // solidCohesiveFvPatchVectorField& cohesivePatchU =
// refCast<solidCohesiveFvPatchVectorField> // refCast<solidCohesiveFvPatchVectorField>
// ( // (
// U.boundaryField()[cohesivePatchID] // U.boundaryField()[cohesivePatchID]
// ); // );
// philipc: I have moved cohesive stuff to constitutiveModel // philipc: I have moved cohesive stuff to constitutiveModel
// cohesiveZone is an index field // cohesiveZone is an index field
// which allows the user to limit the crack to certain areas at runtime // which allows the user to limit the crack to certain areas at runtime
// 1 for faces within cohesiveZone // 1 for faces within cohesiveZone
// 0 for faces outside cohesiveZone // 0 for faces outside cohesiveZone
surfaceScalarField cohesiveZone surfaceScalarField cohesiveZone
( (
IOobject IOobject
@ -64,85 +64,87 @@
// limit crack to specified boxes // limit crack to specified boxes
{ {
const dictionary& stressControl = const dictionary& stressControl =
mesh.solutionDict().subDict("solidMechanics"); mesh.solutionDict().subDict("solidMechanics");
List<boundBox> userBoxes(stressControl.lookup("crackLimitingBoxes")); List<boundBox> userBoxes(stressControl.lookup("crackLimitingBoxes"));
const surfaceVectorField& Cf = mesh.Cf(); const surfaceVectorField& Cf = mesh.Cf();
forAll(cohesiveZone.internalField(), faceI) forAll(cohesiveZone.internalField(), faceI)
{
bool faceInsideBox = false;
forAll(userBoxes, boxi)
{ {
if(userBoxes[boxi].contains(Cf.internalField()[faceI])) faceInsideBox = true; bool faceInsideBox = false;
}
if(faceInsideBox) forAll(userBoxes, boxi)
{
cohesiveZone.internalField()[faceI] = 1.0;
}
}
forAll(cohesiveZone.boundaryField(), patchI)
{
// cracks may go along proc boundaries
if(mesh.boundaryMesh()[patchI].type() == processorPolyPatch::typeName)
{
forAll(cohesiveZone.boundaryField()[patchI], faceI)
{
bool faceInsideBox = false;
forAll(userBoxes, boxi)
{ {
if(userBoxes[boxi].contains(Cf.boundaryField()[patchI][faceI])) faceInsideBox = true; if(userBoxes[boxi].contains(Cf.internalField()[faceI])) faceInsideBox = true;
} }
if(faceInsideBox) if(faceInsideBox)
{ {
cohesiveZone.boundaryField()[patchI][faceI] = 1.0; cohesiveZone.internalField()[faceI] = 1.0;
} }
} }
}
}
Info << "\nThere are " << gSum(cohesiveZone.internalField()) << " potential internal crack faces" << nl << endl; forAll(cohesiveZone.boundaryField(), patchI)
Info << "\nThere are " << gSum(cohesiveZone.boundaryField())/2 << " potential coupled boundary crack faces" << nl << endl; {
// cracks may go along proc boundaries
if(mesh.boundaryMesh()[patchI].type() == processorPolyPatch::typeName)
{
forAll(cohesiveZone.boundaryField()[patchI], faceI)
{
bool faceInsideBox = false;
// write field for visualisation forAll(userBoxes, boxi)
volScalarField cohesiveZoneVol {
( if(userBoxes[boxi].contains(Cf.boundaryField()[patchI][faceI])) faceInsideBox = true;
IOobject }
(
"cohesiveZoneVol", if(faceInsideBox)
runTime.timeName(), {
mesh, cohesiveZone.boundaryField()[patchI][faceI] = 1.0;
IOobject::NO_READ, }
IOobject::AUTO_WRITE }
), }
mesh,
dimensionedScalar("zero", dimless, 0.0)
);
forAll(cohesiveZone.internalField(), facei)
{
if(cohesiveZone.internalField()[facei])
{
cohesiveZoneVol.internalField()[mesh.owner()[facei]] = 1.0;
cohesiveZoneVol.internalField()[mesh.neighbour()[facei]] = 1.0;
} }
}
forAll(cohesiveZone.boundaryField(), patchi) Info << "\nThere are " << gSum(cohesiveZone.internalField()) << " potential internal crack faces" << nl << endl;
{ Info << "\nThere are " << gSum(cohesiveZone.boundaryField())/2 << " potential coupled boundary crack faces" << nl << endl;
forAll(cohesiveZone.boundaryField()[patchi], facei)
// write field for visualisation
volScalarField cohesiveZoneVol
(
IOobject
(
"cohesiveZoneVol",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0)
);
forAll(cohesiveZone.internalField(), facei)
{ {
if(cohesiveZone.boundaryField()[patchi][facei] > 0.0) if(cohesiveZone.internalField()[facei])
{
cohesiveZoneVol.internalField()[mesh.owner()[facei]] = 1.0;
cohesiveZoneVol.internalField()[mesh.neighbour()[facei]] = 1.0;
}
}
forAll(cohesiveZone.boundaryField(), patchi)
{ {
cohesiveZoneVol.boundaryField()[patchi][facei] = 1.0; forAll(cohesiveZone.boundaryField()[patchi], facei)
{
if(cohesiveZone.boundaryField()[patchi][facei] > 0.0)
{
cohesiveZoneVol.boundaryField()[patchi][facei] = 1.0;
}
}
} }
} Info << "Writing cohesiveZone field" << endl;
} cohesiveZoneVol.write();
Info << "Writing cohesiveZone field" << endl;
cohesiveZoneVol.write();
} }

View file

@ -35,8 +35,8 @@
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimless, vector::zero) dimensionedVector("zero", dimless, vector::zero)
); );
volVectorField V volVectorField V
@ -80,19 +80,19 @@
dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero) dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero)
); );
volVectorField divSigmaExp volVectorField divSigmaExp
( (
IOobject IOobject
( (
"divSigmaExp", "divSigmaExp",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimForce/dimVolume, vector::zero) dimensionedVector("zero", dimForce/dimVolume, vector::zero)
); );
constitutiveModel rheology(sigma, U); constitutiveModel rheology(sigma, U);
@ -122,11 +122,12 @@
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimLength, vector::zero) dimensionedVector("zero", dimLength, vector::zero)
); );
// aitken relaxation factor
scalar aitkenInitialRes = 1.0; // aitken relaxation factor
scalar aitkenTheta = 0.1; scalar aitkenInitialRes = 1.0;
scalar aitkenTheta = 0.1;
// volVectorField resid // volVectorField resid
// ( // (
@ -139,5 +140,5 @@ scalar aitkenTheta = 0.1;
// IOobject::AUTO_WRITE // IOobject::AUTO_WRITE
// ), // ),
// mesh, // mesh,
// dimensionedVector("zero", dimless, vector::zero) // dimensionedVector("zero", dimless, vector::zero)
// ); // );

View file

@ -1,14 +1,14 @@
OFstream * filePtr(NULL); OFstream* filePtr(NULL);
word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch")); word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch"));
label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName); label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName);
if(historyPatchID == -1) if(historyPatchID == -1)
{ {
Warning << "history patch " << historyPatchName Warning << "history patch " << historyPatchName
<< " not found. Force-displacement will not be written" << " not found. Force-displacement will not be written"
<< endl; << endl;
} }
else if(Pstream::master()) else if(Pstream::master())
{ {
Info << "Force-displacement for patch " << historyPatchName Info << "Force-displacement for patch " << historyPatchName
<< " will be written to forceDisp.dat" << " will be written to forceDisp.dat"
<< endl; << endl;
@ -17,4 +17,4 @@ if(historyPatchID == -1)
filePtr = new OFstream(hisDirName/historyPatchName+"forceDisp.dat"); filePtr = new OFstream(hisDirName/historyPatchName+"forceDisp.dat");
OFstream& forceDispFile = *filePtr; OFstream& forceDispFile = *filePtr;
forceDispFile << "#Disp(mm)\tForce(N)" << endl; forceDispFile << "#Disp(mm)\tForce(N)" << endl;
} }

View file

@ -58,213 +58,212 @@ Author
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
# include "setRootCase.H" # include "setRootCase.H"
# include "createTime.H" # include "createTime.H"
# include "createCrackerMesh.H" # include "createCrackerMesh.H"
# include "createFields.H" # include "createFields.H"
# include "createCrack.H" # include "createCrack.H"
//# include "createReference.H" //# include "createReference.H"
# include "createHistory.H" # include "createHistory.H"
# include "readDivSigmaExpMethod.H" # include "readDivSigmaExpMethod.H"
# include "createSolidInterfaceNoModify.H" # include "createSolidInterfaceNoModify.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl; Info<< "\nStarting time loop\n" << endl;
lduMatrix::debug = 0; lduMatrix::debug = 0;
scalar maxEffTractionFraction = 0; scalar maxEffTractionFraction = 0;
// time rates for predictor // time rates for predictor
volTensorField gradV = fvc::ddt(gradU); volTensorField gradV = fvc::ddt(gradU);
surfaceVectorField snGradV = surfaceVectorField snGradV =
(snGradU - snGradU.oldTime())/runTime.deltaT(); (snGradU - snGradU.oldTime())/runTime.deltaT();
//# include "initialiseSolution.H" //# include "initialiseSolution.H"
while (runTime.run()) while (runTime.run())
{ {
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
# include "setDeltaT.H" # include "setDeltaT.H"
runTime++; runTime++;
Info<< "\nTime: " << runTime.timeName() << " s\n" << endl; Info<< "\nTime = " << runTime.timeName() << " s\n" << endl;
volScalarField rho = rheology.rho(); volScalarField rho = rheology.rho();
volDiagTensorField K = rheology.K(); volDiagTensorField K = rheology.K();
surfaceDiagTensorField Kf = fvc::interpolate(K, "K"); surfaceDiagTensorField Kf = fvc::interpolate(K, "K");
volSymmTensor4thOrderField C = rheology.C(); volSymmTensor4thOrderField C = rheology.C();
surfaceSymmTensor4thOrderField Cf = fvc::interpolate(C, "C"); surfaceSymmTensor4thOrderField Cf = fvc::interpolate(C, "C");
solidInterfacePtr->modifyProperties(Cf, Kf); solidInterfacePtr->modifyProperties(Cf, Kf);
//# include "waveCourantNo.H" //# include "waveCourantNo.H"
int iCorr = 0; int iCorr = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar initialResidual = 0; scalar initialResidual = 0;
scalar relativeResidual = 1; scalar relativeResidual = 1;
//scalar forceResidual = 1; //scalar forceResidual = 1;
label nFacesToBreak = 0; label nFacesToBreak = 0;
label nCoupledFacesToBreak = 0; label nCoupledFacesToBreak = 0;
bool topoChange = false; bool topoChange = false;
//bool noMoreCracks = false; //bool noMoreCracks = false;
// Predictor step using time rates // Predictor step using time rates
if (predictor) if (predictor)
{ {
Info << "Predicting U, gradU and snGradU using velocity" Info<< "Predicting U, gradU and snGradU using velocity"
<< endl; << endl;
U += V*runTime.deltaT(); U += V*runTime.deltaT();
gradU += gradV*runTime.deltaT(); gradU += gradV*runTime.deltaT();
snGradU += snGradV*runTime.deltaT(); snGradU += snGradV*runTime.deltaT();
} }
do do
{ {
surfaceVectorField n = mesh.Sf()/mesh.magSf(); surfaceVectorField n = mesh.Sf()/mesh.magSf();
do do
{ {
U.storePrevIter(); U.storePrevIter();
# include "calculateDivSigmaExp.H" # include "calculateDivSigmaExp.H"
fvVectorMatrix UEqn fvVectorMatrix UEqn
( (
rho*fvm::d2dt2(U) rho*fvm::d2dt2(U)
== ==
fvm::laplacian(Kf, U, "laplacian(K,U)") fvm::laplacian(Kf, U, "laplacian(K,U)")
+ divSigmaExp + divSigmaExp
); );
//# include "setReference.H" //# include "setReference.H"
if(solidInterfacePtr) if(solidInterfacePtr)
{ {
solidInterfacePtr->correct(UEqn); solidInterfacePtr->correct(UEqn);
} }
if (relaxEqn) if (relaxEqn)
{ {
UEqn.relax(); UEqn.relax();
} }
solverPerf = UEqn.solve(); solverPerf = UEqn.solve();
if (aitkenRelax) if (aitkenRelax)
{ {
# include "aitkenRelaxation.H" # include "aitkenRelaxation.H"
} }
else else
{ {
U.relax(); U.relax();
} }
if (iCorr == 0) if (iCorr == 0)
{ {
initialResidual = solverPerf.initialResidual(); initialResidual = solverPerf.initialResidual();
aitkenInitialRes = gMax(mag(U.internalField())); aitkenInitialRes = gMax(mag(U.internalField()));
} }
//gradU = solidInterfacePtr->grad(U); //gradU = solidInterfacePtr->grad(U);
// use leastSquaresSolidInterface grad scheme // use leastSquaresSolidInterface grad scheme
gradU = fvc::grad(U); gradU = fvc::grad(U);
# include "calculateRelativeResidual.H"
# include "calculateRelativeResidual.H" if (iCorr % infoFrequency == 0)
{
Info<< "\tTime " << runTime.value()
<< ", Corr " << iCorr
<< ", Solving for " << U.name()
<< " using " << solverPerf.solverName()
<< ", res = " << solverPerf.initialResidual()
<< ", rel res = " << relativeResidual;
if (aitkenRelax)
{
Info << ", aitken = " << aitkenTheta;
}
Info << ", inner iters " << solverPerf.nIterations() << endl;
}
}
while
(
//iCorr++ == 0
iCorr++ < 10
||
(
//solverPerf.initialResidual() > convergenceTolerance
relativeResidual > convergenceTolerance
&& iCorr < nCorr
)
);
if (iCorr % infoFrequency == 0) Info<< "Solving for " << U.name() << " using "
{ << solverPerf.solverName()
Info << "\tTime " << runTime.value() << ", Initial residual = " << initialResidual
<< ", Corr " << iCorr << ", Final residual = " << solverPerf.initialResidual()
<< ", Solving for " << U.name() << ", No outer iterations " << iCorr
<< " using " << solverPerf.solverName() << ", Relative residual " << relativeResidual << endl;
<< ", res = " << solverPerf.initialResidual()
<< ", rel res = " << relativeResidual;
if (aitkenRelax)
{
Info << ", aitken = " << aitkenTheta;
}
Info << ", inner iters " << solverPerf.nIterations() << endl;
}
}
while
(
//iCorr++ == 0
iCorr++ < 10
||
(
//solverPerf.initialResidual() > convergenceTolerance
relativeResidual > convergenceTolerance
&&
iCorr < nCorr
)
);
Info<< "Solving for " << U.name() << " using " # include "calculateTraction.H"
<< solverPerf.solverName() # include "updateCrack.H"
<< ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual()
<< ", No outer iterations " << iCorr
<< ", Relative residual " << relativeResidual << endl;
# include "calculateTraction.H" Info<< "Max effective traction fraction: "
# include "updateCrack.H" << maxEffTractionFraction << endl;
Info << "Max effective traction fraction: " // reset counter if faces want to crack
<< maxEffTractionFraction << endl; if ((nFacesToBreak > 0) || (nCoupledFacesToBreak > 0)) iCorr = 0;
}
while( (nFacesToBreak > 0) || (nCoupledFacesToBreak > 0));
// reset counter if faces want to crack if (cohesivePatchUPtr)
if ((nFacesToBreak > 0) || (nCoupledFacesToBreak > 0)) iCorr = 0; {
} if (returnReduce(cohesivePatchUPtr->size(), sumOp<label>()))
while( (nFacesToBreak > 0) || (nCoupledFacesToBreak > 0)); {
cohesivePatchUPtr->cracking();
}
}
else
{
if
(
returnReduce
(
cohesivePatchUFixedModePtr->size(),
sumOp<label>()
)
)
{
Pout << "Number of faces in crack: "
<< cohesivePatchUFixedModePtr->size() << endl;
cohesivePatchUFixedModePtr->relativeSeparationDistance();
}
}
if (cohesivePatchUPtr) // update time rates for predictor
{ if (predictor)
if (returnReduce(cohesivePatchUPtr->size(), sumOp<label>())) {
{ V = fvc::ddt(U);
cohesivePatchUPtr->cracking(); gradV = fvc::ddt(gradU);
} snGradV = (snGradU - snGradU.oldTime())/runTime.deltaT();
} }
else
{
if
(
returnReduce
(
cohesivePatchUFixedModePtr->size(),
sumOp<label>())
)
{
Pout << "Number of faces in crack: "
<< cohesivePatchUFixedModePtr->size() << endl;
cohesivePatchUFixedModePtr->relativeSeparationDistance();
}
}
// update time rates for predictor # include "calculateEpsilonSigma.H"
if (predictor) # include "writeFields.H"
{ # include "writeHistory.H"
V = fvc::ddt(U);
gradV = fvc::ddt(gradU);
snGradV = (snGradU - snGradU.oldTime())/runTime.deltaT();
}
# include "calculateEpsilonSigma.H" Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
# include "writeFields.H" << " ClockTime = " << runTime.elapsedClockTime() << " s\n\n"
# include "writeHistory.H" << endl;
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s\n\n"
<< endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;
return(0); return(0);
} }

View file

@ -3,8 +3,8 @@ word divSigmaExpMethod(mesh.solutionDict().subDict("solidMechanics").lookup("div
Info << "Selecting divSigmaExp calculation method " << divSigmaExpMethod << endl; Info << "Selecting divSigmaExp calculation method " << divSigmaExpMethod << endl;
// if(divSigmaExpMethod != "standard" && divSigmaExpMethod != "surface" && divSigmaExpMethod != "decompose" && divSigmaExpMethod != "laplacian") // if(divSigmaExpMethod != "standard" && divSigmaExpMethod != "surface" && divSigmaExpMethod != "decompose" && divSigmaExpMethod != "laplacian")
if(divSigmaExpMethod != "standard" && divSigmaExpMethod != "surface" && divSigmaExpMethod != "laplacian") if(divSigmaExpMethod != "standard" && divSigmaExpMethod != "surface" && divSigmaExpMethod != "laplacian")
{ {
FatalError << "divSigmaExp method " << divSigmaExpMethod << " not found!" << nl FatalError << "divSigmaExp method " << divSigmaExpMethod << " not found!" << nl
<< "valid methods are:\nstandard\nsurface\nlaplacian" << "valid methods are:\nstandard\nsurface\nlaplacian"
<< exit(FatalError); << exit(FatalError);
} }

View file

@ -12,7 +12,7 @@ Switch aitkenRelax(stressControl.lookup("aitkenRelaxation"));
Switch relaxEqn(stressControl.lookup("relaxEqn")); Switch relaxEqn(stressControl.lookup("relaxEqn"));
if(relaxEqn && solidInterfaceCorr) if(relaxEqn && solidInterfaceCorr)
{ {
FatalError << "relaxEqn and solidInterface may not be used concurrently" FatalError << "relaxEqn and solidInterface may not be used concurrently"
<< exit(FatalError); << exit(FatalError);
} }

View file

@ -1,36 +1,36 @@
if (dynamicTimeStep) if (dynamicTimeStep)
{ {
if if
( (
//(maxEffTraction < 0.999*CzLaw.sigmaMax().value()) //(maxEffTraction < 0.999*CzLaw.sigmaMax().value())
(returnReduce(maxEffTractionFraction, maxOp<scalar>()) < 0.99) (returnReduce(maxEffTractionFraction, maxOp<scalar>()) < 0.99)
//&& (cohesivePatchU.size() == 0) //&& (cohesivePatchU.size() == 0)
&& (mag(runTime.deltaT().value() - deltaTmax) < SMALL) && (mag(runTime.deltaT().value() - deltaTmax) < SMALL)
) )
{ {
runTime.setDeltaT(deltaTmax); runTime.setDeltaT(deltaTmax);
} }
else else
{ {
scalar newDeltaT = deltaTmin; scalar newDeltaT = deltaTmin;
if (newDeltaT/runTime.deltaT().value() < 0.5) if (newDeltaT/runTime.deltaT().value() < 0.5)
{ {
newDeltaT = 0.5*runTime.deltaT().value(); newDeltaT = 0.5*runTime.deltaT().value();
Info << "Reducing time step" << nl; Info << "Reducing time step" << nl;
} }
runTime.setDeltaT(newDeltaT); runTime.setDeltaT(newDeltaT);
} }
Pout << "Current time step size: " Pout << "Current time step size: "
<< runTime.deltaT().value() << " s" << endl; << runTime.deltaT().value() << " s" << endl;
scalar maxDT = runTime.deltaT().value(); scalar maxDT = runTime.deltaT().value();
if(mag(returnReduce(maxDT, maxOp<scalar>()) - runTime.deltaT().value()) > SMALL) if(mag(returnReduce(maxDT, maxOp<scalar>()) - runTime.deltaT().value()) > SMALL)
{ {
FatalError << "Processors have different time-steps!" FatalError << "Processors have different time-steps!"
<< exit(FatalError); << exit(FatalError);
} }
} }

View file

@ -28,7 +28,7 @@ nCoupledFacesToBreak = 0;
//scalarField effTractionFraction = effTraction/sigmaMax; //scalarField effTractionFraction = effTraction/sigmaMax;
scalarField effTractionFraction(normalTraction.size(), 0.0); scalarField effTractionFraction(normalTraction.size(), 0.0);
if (cohesivePatchUPtr) if(cohesivePatchUPtr)
{ {
effTractionFraction = effTractionFraction =
(normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI) (normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI)
@ -41,6 +41,7 @@ nCoupledFacesToBreak = 0;
(normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI) (normalTraction/sigmaMaxI)*(normalTraction/sigmaMaxI)
+ (shearTraction/sigmaMaxI)*(shearTraction/sigmaMaxI); + (shearTraction/sigmaMaxI)*(shearTraction/sigmaMaxI);
} }
maxEffTractionFraction = gMax(effTractionFraction); maxEffTractionFraction = gMax(effTractionFraction);
SLList<label> facesToBreakList; SLList<label> facesToBreakList;
@ -85,7 +86,6 @@ nCoupledFacesToBreak = 0;
{ {
faceToBreakEffTractionFraction = faceToBreakEffTractionFraction =
facesToBreakEffTractionFraction[faceI]; facesToBreakEffTractionFraction[faceI];
faceToBreakIndex = facesToBreak[faceI]; faceToBreakIndex = facesToBreak[faceI];
} }
} }
@ -135,59 +135,59 @@ nCoupledFacesToBreak = 0;
if (mesh.boundary()[patchI].coupled()) if (mesh.boundary()[patchI].coupled())
{ {
// scalarField pEffTraction = // scalarField pEffTraction =
// cohesiveZone.boundaryField()[patchI] * // cohesiveZone.boundaryField()[patchI]*
// mag(traction.boundaryField()[patchI]); // mag(traction.boundaryField()[patchI]);
// scalarField pEffTractionFraction = pEffTraction/sigmaMax.boundaryField()[patchI]; // scalarField pEffTractionFraction = pEffTraction/sigmaMax.boundaryField()[patchI];
scalarField pNormalTraction = scalarField pNormalTraction =
cohesiveZone.boundaryField()[patchI] * cohesiveZone.boundaryField()[patchI]*
( n.boundaryField()[patchI] & traction.boundaryField()[patchI] ); ( n.boundaryField()[patchI] & traction.boundaryField()[patchI] );
// only consider tensile tractions // only consider tensile tractions
pNormalTraction = max(pNormalTraction, scalar(0)); 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: scalarField pShearTraction =
// ie (tN/tNC)^2 + (tS/tSC)^2 >1 to crack a face cohesiveZone.boundaryField()[patchI]*
const scalarField& pSigmaMax = sigmaMax.boundaryField()[patchI]; mag( (I - Foam::sqr(n.boundaryField()[patchI])) & traction.boundaryField()[patchI] );
const scalarField& pTauMax = tauMax.boundaryField()[patchI];
scalarField pEffTractionFraction(pNormalTraction.size(), 0); // 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];
if(cohesivePatchUPtr) scalarField pEffTractionFraction(pNormalTraction.size(), 0.0);
{ if(cohesivePatchUPtr)
pEffTractionFraction = {
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) pEffTractionFraction =
+ (pShearTraction/pTauMax)*(pShearTraction/pTauMax); (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
} + (pShearTraction/pTauMax)*(pShearTraction/pTauMax);
else }
{ else
// solidCohesiveFixedModeMix only uses sigmaMax {
pEffTractionFraction = // solidCohesiveFixedModeMix only uses sigmaMax
(pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax) pEffTractionFraction =
+ (pShearTraction/pSigmaMax)*(pShearTraction/pSigmaMax); (pNormalTraction/pSigmaMax)*(pNormalTraction/pSigmaMax)
} + (pShearTraction/pSigmaMax)*(pShearTraction/pSigmaMax);
}
label start = mesh.boundaryMesh()[patchI].start(); label start = mesh.boundaryMesh()[patchI].start();
forAll(pEffTractionFraction, faceI) forAll(pEffTractionFraction, faceI)
{ {
if (pEffTractionFraction[faceI] > maxEffTractionFraction) if (pEffTractionFraction[faceI] > maxEffTractionFraction)
{ {
maxEffTractionFraction = pEffTractionFraction[faceI]; maxEffTractionFraction = pEffTractionFraction[faceI];
} }
if (pEffTractionFraction[faceI] > 1.0) if (pEffTractionFraction[faceI] > 1.0)
{ {
coupledFacesToBreakList.insert(start + faceI); coupledFacesToBreakList.insert(start + faceI);
coupledFacesToBreakEffTractionFractionList.insert coupledFacesToBreakEffTractionFractionList.insert
( (
pEffTractionFraction[faceI] pEffTractionFraction[faceI]
); );
} }
} }
} }
} }
@ -274,8 +274,8 @@ nCoupledFacesToBreak = 0;
labelList index(Pstream::nProcs(), -1); labelList index(Pstream::nProcs(), -1);
if (nCoupledFacesToBreak) if (nCoupledFacesToBreak)
{ {
label patchID = label patchID =
mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex); mesh.boundaryMesh().whichPatch(coupledFaceToBreakIndex);
label start = mesh.boundaryMesh()[patchID].start(); label start = mesh.boundaryMesh()[patchID].start();
label localIndex = coupledFaceToBreakIndex - start; label localIndex = coupledFaceToBreakIndex - start;
@ -333,6 +333,7 @@ nCoupledFacesToBreak = 0;
vector faceToBreakNormal = vector::zero; vector faceToBreakNormal = vector::zero;
scalar faceToBreakSigmaMax = 0.0; scalar faceToBreakSigmaMax = 0.0;
scalar faceToBreakTauMax = 0.0; scalar faceToBreakTauMax = 0.0;
// Set faces to break // Set faces to break
if (nFacesToBreak > 0) if (nFacesToBreak > 0)
{ {
@ -340,31 +341,39 @@ nCoupledFacesToBreak = 0;
faceToBreakNormal = n.internalField()[faceToBreakIndex]; faceToBreakNormal = n.internalField()[faceToBreakIndex];
// Scale broken face traction // Scale broken face traction
faceToBreakSigmaMax = sigmaMaxI[faceToBreakIndex]; faceToBreakSigmaMax = sigmaMaxI[faceToBreakIndex];
faceToBreakTauMax = tauMaxI[faceToBreakIndex]; faceToBreakTauMax = tauMaxI[faceToBreakIndex];
scalar normalTrac = faceToBreakNormal & faceToBreakTraction; scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
normalTrac = max(normalTrac, 0.0); normalTrac = max(normalTrac, 0.0);
scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction ); scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
scalar scaleFactor = 1; scalar scaleFactor = 1;
if(cohesivePatchUPtr) if(cohesivePatchUPtr)
{
scaleFactor =
::sqrt(1 / (
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
) );
}
else
{ {
// solidCohesiveFixedModeMix only uses sigmaMax scaleFactor =
scaleFactor = Foam::sqrt
::sqrt(1 / ( (
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax) 1 /
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax) (
) ); (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
)
);
}
else
{
// solidCohesiveFixedModeMix only uses sigmaMax
scaleFactor =
Foam::sqrt
(
1 /
(
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
)
);
} }
faceToBreakTraction *= scaleFactor; faceToBreakTraction *= scaleFactor;
topoChange = true; topoChange = true;
} }
@ -379,29 +388,37 @@ nCoupledFacesToBreak = 0;
faceToBreakNormal = n.boundaryField()[patchID][localIndex]; faceToBreakNormal = n.boundaryField()[patchID][localIndex];
// Scale broken face traction // Scale broken face traction
faceToBreakSigmaMax = sigmaMax.boundaryField()[patchID][localIndex]; faceToBreakSigmaMax = sigmaMax.boundaryField()[patchID][localIndex];
faceToBreakTauMax = tauMax.boundaryField()[patchID][localIndex]; faceToBreakTauMax = tauMax.boundaryField()[patchID][localIndex];
scalar normalTrac = faceToBreakNormal & faceToBreakTraction; scalar normalTrac = faceToBreakNormal & faceToBreakTraction;
normalTrac = max(normalTrac, 0.0); normalTrac = max(normalTrac, 0.0);
scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction ); scalar shearTrac = mag( (I - sqr(faceToBreakNormal)) & faceToBreakTraction );
scalar scaleFactor = 1; scalar scaleFactor = 1;
if(cohesivePatchUPtr) if(cohesivePatchUPtr)
{ {
scaleFactor = scaleFactor =
::sqrt(1 / ( Foam::sqrt
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax) (
+ (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax) 1 /
) ); (
} (normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
else + (shearTrac/faceToBreakTauMax)*(shearTrac/faceToBreakTauMax)
{ )
// solidCohesiveFixedModeMix only uses sigmaMax );
scaleFactor = }
::sqrt(1 / ( else
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax) {
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax) // solidCohesiveFixedModeMix only uses sigmaMax
) ); scaleFactor =
} Foam::sqrt
(
1 /
(
(normalTrac/faceToBreakSigmaMax)*(normalTrac/faceToBreakSigmaMax)
+ (shearTrac/faceToBreakSigmaMax)*(shearTrac/faceToBreakSigmaMax)
)
);
}
faceToBreakTraction *= scaleFactor; faceToBreakTraction *= scaleFactor;
@ -441,20 +458,20 @@ nCoupledFacesToBreak = 0;
Cf = fvc::interpolate(C); Cf = fvc::interpolate(C);
Kf = fvc::interpolate(K); Kf = fvc::interpolate(K);
// we need to modify propertiess after cracking otherwise momentum equation is wrong // we need to modify propertiess after cracking otherwise momentum equation is wrong
// but solidInterface seems to hold some information about old mesh // but solidInterface seems to hold some information about old mesh
// so we will delete it and make another // so we will delete it and make another
// we could probably add a public clearout function // we could probably add a public clearout function
// create new solidInterface // create new solidInterface
//Pout << "Creating new solidInterface" << endl; //Pout << "Creating new solidInterface" << endl;
//delete solidInterfacePtr; //delete solidInterfacePtr;
//solidInterfacePtr = new solidInterface(mesh, rheology); //solidInterfacePtr = new solidInterface(mesh, rheology);
// delete demand driven data as the mesh has changed // delete demand driven data as the mesh has changed
if(rheology.solidInterfaceActive()) if(rheology.solidInterfaceActive())
{ {
rheology.solInterface().clearOut(); rheology.solInterface().clearOut();
solidInterfacePtr->modifyProperties(Cf, Kf); solidInterfacePtr->modifyProperties(Cf, Kf);
} }
// Local crack displacement // Local crack displacement
vectorField UpI = vectorField UpI =
@ -466,21 +483,21 @@ nCoupledFacesToBreak = 0;
vectorField globalUpI = mesh.globalCrackField(UpI); vectorField globalUpI = mesh.globalCrackField(UpI);
vectorField globalOldUpI = mesh.globalCrackField(oldUpI); vectorField globalOldUpI = mesh.globalCrackField(oldUpI);
// C and K field on new crack faces must be updated // C and K field on new crack faces must be updated
symmTensor4thOrderField CPI = C.boundaryField()[cohesivePatchID].patchInternalField(); symmTensor4thOrderField CPI = C.boundaryField()[cohesivePatchID].patchInternalField();
diagTensorField KPI = K.boundaryField()[cohesivePatchID].patchInternalField(); diagTensorField KPI = K.boundaryField()[cohesivePatchID].patchInternalField();
symmTensor4thOrderField globalCPI = mesh.globalCrackField(CPI); symmTensor4thOrderField globalCPI = mesh.globalCrackField(CPI);
diagTensorField globalKPI = mesh.globalCrackField(KPI); diagTensorField globalKPI = mesh.globalCrackField(KPI);
// cohesivePatchU.size() // cohesivePatchU.size()
int cohesivePatchSize(cohesivePatchUPtr ? cohesivePatchUPtr->size() : cohesivePatchUFixedModePtr->size()); int cohesivePatchSize(cohesivePatchUPtr ? cohesivePatchUPtr->size() : cohesivePatchUFixedModePtr->size());
// Initialise U for new cohesive face // Initialise U for new cohesive face
const labelList& gcfa = mesh.globalCrackFaceAddressing(); const labelList& gcfa = mesh.globalCrackFaceAddressing();
label globalIndex = mesh.localCrackStart(); label globalIndex = mesh.localCrackStart();
// for (label i=0; i<cohesivePatchU.size(); i++) // for (label i=0; i<cohesivePatchU.size(); i++)
for (label i=0; i<cohesivePatchSize; i++) for (label i=0; i<cohesivePatchSize; i++)
{ {
label oldFaceIndex = faceMap[start+i]; label oldFaceIndex = faceMap[start+i];
// If new face // If new face
@ -499,10 +516,10 @@ nCoupledFacesToBreak = 0;
+ globalOldUpI[gcfa[globalIndex]] + globalOldUpI[gcfa[globalIndex]]
); );
// initialise C and K on new faces // initialise C and K on new faces
// set new face value to value of internal cell // set new face value to value of internal cell
Cf.boundaryField()[cohesivePatchID][i] = globalCPI[globalIndex]; Cf.boundaryField()[cohesivePatchID][i] = globalCPI[globalIndex];
Kf.boundaryField()[cohesivePatchID][i] = globalKPI[globalIndex]; Kf.boundaryField()[cohesivePatchID][i] = globalKPI[globalIndex];
globalIndex++; globalIndex++;
} }
@ -513,87 +530,85 @@ nCoupledFacesToBreak = 0;
} }
// we must calculate grad using interface // we must calculate grad using interface
// U at the interface has not been calculated yet as interface.correct() // U at the interface has not been calculated yet as interface.correct()
// has not been called yet // has not been called yet
// not really a problem as gradU is correct in second outer iteration // not really a problem as gradU is correct in second outer iteration
// as long as this does not cause convergence problems for the first iterations. // as long as this does not cause convergence problems for the first iterations.
// we should be able to calculate the interface displacements without // we should be able to calculate the interface displacements without
// having to call interface.correct() // having to call interface.correct()
// todo: add calculateInterfaceU() function // todo: add calculateInterfaceU() function
// interface grad uses Gauss, we need least squares // interface grad uses Gauss, we need least squares
//gradU = solidInterfacePtr->grad(U); //gradU = solidInterfacePtr->grad(U);
gradU = fvc::grad(U); // leastSquaresSolidInterface grad scheme gradU = fvc::grad(U); // leastSquaresSolidInterface grad scheme
//snGradU = fvc::snGrad(U); //snGradU = fvc::snGrad(U);
# include "calculateTraction.H" # include "calculateTraction.H"
//if (nFacesToBreak || nCoupledFacesToBreak) mesh.write(); traction.write(); //if (nFacesToBreak || nCoupledFacesToBreak) mesh.write(); traction.write();
// Initialise initiation traction for new cohesive patch face // Initialise initiation traction for new cohesive patch face
// for (label i=0; i<cohesivePatchU.size(); i++) // for (label i=0; i<cohesivePatchU.size(); i++)
for (label i=0; i<cohesivePatchSize; i++) for (label i=0; i<cohesivePatchSize; i++)
{
label oldFaceIndex = faceMap[start+i];
// If new face
if
(
(oldFaceIndex == faceToBreakIndex)
|| (oldFaceIndex == coupledFaceToBreakIndex)
)
{ {
vector n0 = label oldFaceIndex = faceMap[start+i];
mesh.Sf().boundaryField()[cohesivePatchID][i]
/mesh.magSf().boundaryField()[cohesivePatchID][i];
//vector n1 = -n0;
if ((n0&faceToBreakNormal) > SMALL) // If new face
if
(
(oldFaceIndex == faceToBreakIndex)
|| (oldFaceIndex == coupledFaceToBreakIndex)
)
{ {
traction.boundaryField()[cohesivePatchID][i] = vector n0 =
faceToBreakTraction; mesh.Sf().boundaryField()[cohesivePatchID][i]
/mesh.magSf().boundaryField()[cohesivePatchID][i];
//vector n1 = -n0;
traction.oldTime().boundaryField()[cohesivePatchID][i] = if ((n0 & faceToBreakNormal) > SMALL)
faceToBreakTraction;
if(cohesivePatchUPtr)
{ {
cohesivePatchUPtr->traction()[i] = faceToBreakTraction; traction.boundaryField()[cohesivePatchID][i] =
faceToBreakTraction;
traction.oldTime().boundaryField()[cohesivePatchID][i] =
faceToBreakTraction;
if(cohesivePatchUPtr)
{
cohesivePatchUPtr->traction()[i] = faceToBreakTraction;
}
else
{
cohesivePatchUFixedModePtr->traction()[i] =
faceToBreakTraction;
cohesivePatchUFixedModePtr->initiationTraction()[i] =
faceToBreakTraction;
}
} }
else else
{ {
cohesivePatchUFixedModePtr->traction()[i] = traction.boundaryField()[cohesivePatchID][i] =
faceToBreakTraction; -faceToBreakTraction;
traction.oldTime().boundaryField()[cohesivePatchID][i] =
cohesivePatchUFixedModePtr->initiationTraction()[i] =
faceToBreakTraction;
}
}
else
{
traction.boundaryField()[cohesivePatchID][i] =
-faceToBreakTraction;
traction.oldTime().boundaryField()[cohesivePatchID][i] =
-faceToBreakTraction;
//cohesivePatchU.traction()[i] = -faceToBreakTraction;
if(cohesivePatchUPtr)
{
cohesivePatchUPtr->traction()[i] = -faceToBreakTraction;
}
else
{
cohesivePatchUFixedModePtr->traction()[i] =
-faceToBreakTraction; -faceToBreakTraction;
cohesivePatchUFixedModePtr->initiationTraction()[i] = //cohesivePatchU.traction()[i] = -faceToBreakTraction;
-faceToBreakTraction; if(cohesivePatchUPtr)
{
cohesivePatchUPtr->traction()[i] = -faceToBreakTraction;
}
else
{
cohesivePatchUFixedModePtr->traction()[i] =
-faceToBreakTraction;
cohesivePatchUFixedModePtr->initiationTraction()[i] =
-faceToBreakTraction;
}
} }
} }
} }
}
// hmmnn we only need a reference for very small groups of cells // hmmnn we only need a reference for very small groups of cells
// turn off for now // turn off for now
//# include "updateReference.H" //# include "updateReference.H"
} }
} }

View file

@ -4,20 +4,21 @@
forAll(U.boundaryField(), patchI) forAll(U.boundaryField(), patchI)
{ {
// philipc - this used to set a reference on // philipc - this used to set a reference on
// processors which did not have a patch that fixesValue // processors which did not have a patch that fixesValue
// so processor in the centre of the domain all had // so processor in the centre of the domain all had
// a referece set causing stress peaks and resulting // a referece set causing stress peaks and resulting
// in an incorrect solution // in an incorrect solution
// so a quick fix is to not set a reference on regions // so a quick fix is to not set a reference on regions
// with a processor boundary // with a processor boundary
//if (U.boundaryField()[patchI].fixesValue()) //if (U.boundaryField()[patchI].fixesValue())
if ( if
U.boundaryField()[patchI].fixesValue() (
|| U.boundaryField()[patchI].fixesValue()
mesh.boundaryMesh()[patchI].type() ||
== processorPolyPatch::typeName mesh.boundaryMesh()[patchI].type()
) == processorPolyPatch::typeName
)
{ {
const unallocLabelList& curFaceCells = const unallocLabelList& curFaceCells =
mesh.boundary()[patchI].faceCells(); mesh.boundary()[patchI].faceCells();

View file

@ -85,62 +85,62 @@ if (runTime.outputTime() || topoChange)
//- cohesive damage and cracking, and GII and GII //- cohesive damage and cracking, and GII and GII
volScalarField damageAndCracks volScalarField damageAndCracks
( (
IOobject IOobject
( (
"damageAndCracks", "damageAndCracks",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedScalar("zero", dimless, 0.0), dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName calculatedFvPatchVectorField::typeName
); );
volScalarField GI volScalarField GI
( (
IOobject IOobject
( (
"GI", "GI",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedScalar("zero", dimless, 0.0), dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName calculatedFvPatchVectorField::typeName
); );
volScalarField GII volScalarField GII
( (
IOobject IOobject
( (
"GII", "GII",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedScalar("zero", dimless, 0.0), dimensionedScalar("zero", dimless, 0.0),
calculatedFvPatchVectorField::typeName calculatedFvPatchVectorField::typeName
); );
forAll(U.boundaryField(), patchi) forAll(U.boundaryField(), patchi)
{ {
// if(U.boundaryField()[patchi].type() == cohesiveLawMultiMatFvPatchVectorField::typeName) // if(U.boundaryField()[patchi].type() == cohesiveLawMultiMatFvPatchVectorField::typeName)
if(U.boundaryField()[patchi].type() == solidCohesiveFvPatchVectorField::typeName) if(U.boundaryField()[patchi].type() == solidCohesiveFvPatchVectorField::typeName)
{ {
// cohesiveLawMultiMatFvPatchVectorField& Upatch = // cohesiveLawMultiMatFvPatchVectorField& Upatch =
// refCast<cohesiveLawMultiMatFvPatchVectorField>(U.boundaryField()[patchi]); // refCast<cohesiveLawMultiMatFvPatchVectorField>(U.boundaryField()[patchi]);
solidCohesiveFvPatchVectorField& Upatch = solidCohesiveFvPatchVectorField& Upatch =
refCast<solidCohesiveFvPatchVectorField>(U.boundaryField()[patchi]); refCast<solidCohesiveFvPatchVectorField>(U.boundaryField()[patchi]);
GI.boundaryField()[patchi] = Upatch.GI(); GI.boundaryField()[patchi] = Upatch.GI();
GII.boundaryField()[patchi] = Upatch.GII(); GII.boundaryField()[patchi] = Upatch.GII();
damageAndCracks.boundaryField()[patchi] = Upatch.crackingAndDamage(); damageAndCracks.boundaryField()[patchi] = Upatch.crackingAndDamage();
} }
} }
volScalarField GTotal("GTotal", GI + GII); volScalarField GTotal("GTotal", GI + GII);
GTotal.write(); GTotal.write();

View file

@ -1,19 +1,19 @@
//- write force displacement to file //- write force displacement to file
if(historyPatchID != -1) if(historyPatchID != -1)
{ {
Info << "Found patch "<<historyPatchName<<", writing y force and displacement to file" Info << "Found patch "<<historyPatchName<<", writing y force and displacement to file"
<< endl; << endl;
//- for small strain or moving mesh //- for small strain or moving mesh
vector force = gSum(mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID]); vector force = gSum(mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID]);
vector avDisp = gAverage(U.boundaryField()[historyPatchID]); vector avDisp = gAverage(U.boundaryField()[historyPatchID]);
//- write to file //- write to file
if(Pstream::master()) if(Pstream::master())
{ {
OFstream& forceDispFile = *filePtr; OFstream& forceDispFile = *filePtr;
forceDispFile << avDisp.x() << " " << avDisp.y() << " " << avDisp.z() << " " forceDispFile << avDisp.x() << " " << avDisp.y() << " " << avDisp.z() << " "
<< force.x() << " " << force.y() << " " << force.z() << endl; << force.x() << " " << force.y() << " " << force.z() << endl;
} }
} }

View file

@ -1,27 +1,35 @@
if(rheology.planeStress()) if(rheology.planeStress())
{ {
//- add higher order terms //- add higher order terms
volScalarField higherTerms = -0.5*volTensorField(gradDU&gradDU.T()).component(tensor::ZZ); volScalarField higherTerms = -0.5*volTensorField(gradDU&gradDU.T()).component(tensor::ZZ);
forAll(gradDU.internalField(), celli) forAll(gradDU.internalField(), celli)
{ {
gradDU.internalField()[celli][tensor::ZZ] = gradDU.internalField()[celli][tensor::ZZ] =
((-C.internalField()[celli][symmTensor4thOrder::XXZZ]*DEpsilon.internalField()[celli][symmTensor::XX] (
- C.internalField()[celli][symmTensor4thOrder::YYZZ]*DEpsilon.internalField()[celli][symmTensor::YY]) (-C.internalField()[celli][symmTensor4thOrder::XXZZ]*DEpsilon.internalField()[celli][symmTensor::XX]
/ - C.internalField()[celli][symmTensor4thOrder::YYZZ]*DEpsilon.internalField()[celli][symmTensor::YY]
C.internalField()[celli][symmTensor4thOrder::ZZZZ]) )
-higherTerms.internalField()[celli]; /
} C.internalField()[celli][symmTensor4thOrder::ZZZZ])
- higherTerms.internalField()[celli];
}
forAll(gradDU.boundaryField(), patchi) forAll(gradDU.boundaryField(), patchi)
{ {
forAll(gradDU.boundaryField()[patchi], facei) forAll(gradDU.boundaryField()[patchi], facei)
{ {
gradDU.boundaryField()[patchi][facei][tensor::ZZ] = gradDU.boundaryField()[patchi][facei][tensor::ZZ] =
((-C.boundaryField()[patchi][facei][symmTensor4thOrder::XXZZ]*DEpsilon.boundaryField()[patchi][facei][symmTensor::XX] (
- C.boundaryField()[patchi][facei][symmTensor4thOrder::YYZZ]*DEpsilon.boundaryField()[patchi][facei][symmTensor::YY]) (
/ - C.boundaryField()[patchi][facei][symmTensor4thOrder::XXZZ]*
C.boundaryField()[patchi][facei][symmTensor4thOrder::ZZZZ]) DEpsilon.boundaryField()[patchi][facei][symmTensor::XX]
- higherTerms.boundaryField()[patchi][facei]; - C.boundaryField()[patchi][facei][symmTensor4thOrder::YYZZ]*
} DEpsilon.boundaryField()[patchi][facei][symmTensor::YY]
} )
} /
C.boundaryField()[patchi][facei][symmTensor4thOrder::ZZZZ]
)
- higherTerms.boundaryField()[patchi][facei];
}
}
}

View file

@ -29,6 +29,7 @@
dimensionedVector("zero", dimLength, vector::zero) dimensionedVector("zero", dimLength, vector::zero)
); );
Info << "Reading accumulated strain field epsilon\n" << endl;
volSymmTensorField epsilon volSymmTensorField epsilon
( (
IOobject IOobject
@ -57,6 +58,7 @@
dimensionedSymmTensor("zero", dimless, symmTensor::zero) dimensionedSymmTensor("zero", dimless, symmTensor::zero)
); );
Info << "Reading accumulated stress field sigma\n" << endl;
volSymmTensorField sigma volSymmTensorField sigma
( (
IOobject IOobject
@ -72,6 +74,7 @@
); );
Info << "Reading incremental stress field DSigma\n" << endl;
volSymmTensorField DSigma volSymmTensorField DSigma
( (
IOobject IOobject
@ -86,16 +89,16 @@
dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero) dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero)
); );
//- material properties //- material properties
constitutiveModel rheology(sigma, DU); constitutiveModel rheology(sigma, DU);
volSymmTensor4thOrderField C = rheology.C(); volSymmTensor4thOrderField C = rheology.C();
volDiagTensorField K = rheology.K(); volDiagTensorField K = rheology.K();
//surfaceSymmTensor4thOrderField Cf = fvc::interpolate(C); //surfaceSymmTensor4thOrderField Cf = fvc::interpolate(C);
//surfaceDiagTensorField Kf = fvc::interpolate(K); //surfaceDiagTensorField Kf = fvc::interpolate(K);
surfaceVectorField n = mesh.Sf()/mesh.magSf(); surfaceVectorField n = mesh.Sf()/mesh.magSf();
//volScalarField rho = rheology.rho(); //volScalarField rho = rheology.rho();
volScalarField rho volScalarField rho
( (
IOobject IOobject
@ -109,7 +112,7 @@
rheology.rho() rheology.rho()
); );
// if(rheology.planeStress()) // if(rheology.planeStress())
// { // {
// Info << nl << "Plane stress is set to yes -> the zz stress will be zero" << nl << endl; // Info << nl << "Plane stress is set to yes -> the zz stress will be zero" << nl << endl;
// } // }

View file

@ -62,123 +62,123 @@ Author
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
# include "setRootCase.H" # include "setRootCase.H"
# include "createTime.H" # include "createTime.H"
# include "createMesh.H" # include "createMesh.H"
# include "createFields.H" # include "createFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl; Info<< "\nStarting time loop\n" << endl;
for (runTime++; !runTime.end(); runTime++) while(runTime.loop())
{ {
Info<< "Time: " << runTime.timeName() << nl << endl; Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
int iCorr = 0; int iCorr = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar initialResidual = 1.0; scalar initialResidual = 1.0;
lduMatrix::debug = 0; lduMatrix::debug = 0;
//- div(sigmaOld) should be zero but I will include //- div(sigmaOld) should be zero but I will include
//- it to make sure errors don't accumulate //- it to make sure errors don't accumulate
volVectorField* oldErrorPtr = NULL; volVectorField* oldErrorPtr = NULL;
if (ensureTotalEquilibrium) if (ensureTotalEquilibrium)
{ {
oldErrorPtr = new volVectorField oldErrorPtr = new volVectorField
( (
fvc::d2dt2(rho.oldTime(), U.oldTime()) fvc::d2dt2(rho.oldTime(), U.oldTime())
- fvc::div(sigma) - fvc::div(sigma)
); );
} }
do do
{ {
DU.storePrevIter(); DU.storePrevIter();
//- Updated lagrangian momentum equation //- Updated lagrangian momentum equation
fvVectorMatrix DUEqn fvVectorMatrix DUEqn
( (
fvm::d2dt2(rho, DU) fvm::d2dt2(rho, DU)
+ fvc::d2dt2(rho, U) + fvc::d2dt2(rho, U)
== ==
fvm::laplacian(K, DU, "laplacian(K,DU)") fvm::laplacian(K, DU, "laplacian(K,DU)")
+ fvc::div( + fvc::div
DSigma (
- (K & gradDU) DSigma
+ ( (sigma + DSigma) & gradDU ), - (K & gradDU)
"div(sigma)" + ( (sigma + DSigma) & gradDU ),
) "div(sigma)"
//- fvc::laplacian(K, DU) )
); //- fvc::laplacian(K, DU)
);
if (ensureTotalEquilibrium) if (ensureTotalEquilibrium)
{ {
//- to stop accumulation of errors //- to stop accumulation of errors
DUEqn += *oldErrorPtr; DUEqn += *oldErrorPtr;
} }
solverPerf = DUEqn.solve(); solverPerf = DUEqn.solve();
if (iCorr == 0) if (iCorr == 0)
{ {
initialResidual = solverPerf.initialResidual(); initialResidual = solverPerf.initialResidual();
} }
DU.relax(); DU.relax();
gradDU = fvc::grad(DU); gradDU = fvc::grad(DU);
//- for 2-D plane stress simulations, the zz component of gradDU //- for 2-D plane stress simulations, the zz component of gradDU
//- ensures sigma.zz() is zero //- ensures sigma.zz() is zero
//- it is assumed that z is the empty direction //- it is assumed that z is the empty direction
//# include "checkPlaneStress.H" //# include "checkPlaneStress.H"
//- sigma needs to be calculated inside the momentum loop as //- sigma needs to be calculated inside the momentum loop as
//- it is used in the momentum equation //- it is used in the momentum equation
DEpsilon = symm(gradDU) + 0.5*symm(gradDU & gradDU.T()); DEpsilon = symm(gradDU) + 0.5*symm(gradDU & gradDU.T());
DSigma = C && DEpsilon; DSigma = C && DEpsilon;
if (iCorr % infoFrequency == 0) if (iCorr % infoFrequency == 0)
{ {
Info << "\tTime " << runTime.value() Info<< "\tTime " << runTime.value()
<< ", Corr " << iCorr << ", Corr " << iCorr
<< ", Solving for " << DU.name() << ", Solving for " << DU.name()
<< " using " << solverPerf.solverName() << " using " << solverPerf.solverName()
<< ", res = " << solverPerf.initialResidual() << ", res = " << solverPerf.initialResidual()
//<< ", rel res = " << relativeResidual //<< ", rel res = " << relativeResidual
<< ", inner iters " << solverPerf.nIterations() << endl; << ", inner iters " << solverPerf.nIterations() << endl;
} }
} }
while while
( (
solverPerf.initialResidual() > convergenceTolerance solverPerf.initialResidual() > convergenceTolerance
&& && ++iCorr < nCorr
++iCorr < nCorr );
);
Info << nl << "Time " << runTime.value() << ", Solving for " << DU.name() Info<< nl << "Time " << runTime.value() << ", Solving for " << DU.name()
<< ", Initial residual = " << initialResidual << ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual() << ", Final residual = " << solverPerf.initialResidual()
<< ", No outer iterations " << iCorr << ", No outer iterations " << iCorr
<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s"
<< endl; << endl;
# include "moveMeshLeastSquares.H" # include "moveMeshLeastSquares.H"
# include "rotateFields.H" # include "rotateFields.H"
# include "writeFields.H" # include "writeFields.H"
Info<< "ExecutionTime = " Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< runTime.elapsedCpuTime() << " ClockTime = " << runTime.elapsedClockTime() << " s\n\n"
<< " s\n\n" << endl; << endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;
return(0); return(0);
} }

View file

@ -2,7 +2,7 @@
//- move mesh //- move mesh
//--------------------------------------------------// //--------------------------------------------------//
// if(min(J.internalField()) > 0) // if(min(J.internalField()) > 0)
{ {
Info << "Moving mesh using least squares interpolation" << endl; Info << "Moving mesh using least squares interpolation" << endl;
leastSquaresVolPointInterpolation pointInterpolation(mesh); leastSquaresVolPointInterpolation pointInterpolation(mesh);
@ -11,43 +11,42 @@
pointMesh pMesh(mesh); pointMesh pMesh(mesh);
wordList types wordList types
( (
pMesh.boundary().size(), pMesh.boundary().size(),
calculatedFvPatchVectorField::typeName calculatedFvPatchVectorField::typeName
); );
pointVectorField pointDU pointVectorField pointDU
( (
IOobject IOobject
( (
"pointDU", "pointDU",
runTime.timeName(), runTime.timeName(),
mesh mesh
), ),
pMesh, pMesh,
dimensionedVector("zero", dimLength, vector::zero), dimensionedVector("zero", dimLength, vector::zero),
types types
); );
pointInterpolation.interpolate(DU, pointDU); pointInterpolation.interpolate(DU, pointDU);
const vectorField& pointDUI = const vectorField& pointDUI = pointDU.internalField();
pointDU.internalField();
//- Move mesh //- Move mesh
vectorField newPoints = mesh.allPoints(); vectorField newPoints = mesh.allPoints();
forAll (pointDUI, pointI) forAll (pointDUI, pointI)
{ {
newPoints[pointI] += pointDUI[pointI]; newPoints[pointI] += pointDUI[pointI];
} }
twoDPointCorrector twoDCorrector(mesh); twoDPointCorrector twoDCorrector(mesh);
twoDCorrector.correctPoints(newPoints); twoDCorrector.correctPoints(newPoints);
mesh.movePoints(newPoints); mesh.movePoints(newPoints);
mesh.V00(); mesh.V00();
mesh.moving(false); mesh.moving(false);
} }
// else // else
// { // {
// FatalErrorIn(args.executable()) // FatalErrorIn(args.executable())

View file

@ -2,47 +2,47 @@
//- rotate fields //- rotate fields
//--------------------------------------------------// //--------------------------------------------------//
{ {
Info << "Rotating fields" << endl; Info << "Rotating fields" << endl;
volTensorField F = I + gradDU; volTensorField F = I + gradDU;
U += DU; U += DU;
epsilon += DEpsilon; epsilon += DEpsilon;
sigma += DSigma; sigma += DSigma;
volTensorField Finv = inv(F); volTensorField Finv = inv(F);
volScalarField J = det(F); volScalarField J = det(F);
if(min(J.internalField()) < 0) if(min(J.internalField()) < 0)
{ {
FatalErrorIn(args.executable()) FatalErrorIn(args.executable())
<< "Negative Jacobian - a cell volume has become negative!" << "Negative Jacobian - a cell volume has become negative!"
<< exit(FatalError); << exit(FatalError);
} }
rho = rho/J; rho = rho/J;
n = mesh.Sf()/mesh.magSf(); n = mesh.Sf()/mesh.magSf();
//- rotate strain //- rotate strain
//epsilon = symm(Finv & epsilon & Finv.T()); //epsilon = symm(Finv & epsilon & Finv.T());
epsilon = transform(Finv, epsilon); epsilon = transform(Finv, epsilon);
//- rotate stress //- rotate stress
//sigma = 1/J * symm(F.T() & sigma & F); //sigma = 1/J * symm(F.T() & sigma & F);
sigma = (1/J) * transform(F.T(), sigma); sigma = (1/J) * transform(F.T(), sigma);
//- rotate elastic constitutive tensor //- rotate elastic constitutive tensor
C = transform(F.T(), C); C = transform(F.T(), C);
// - update implicit stiffness tensor // - update implicit stiffness tensor
forAll(K, celli) forAll(K, celli)
{ {
K[celli].xx() = C[celli].xxxx(); K[celli].xx() = C[celli].xxxx();
K[celli].yy() = C[celli].yyyy(); K[celli].yy() = C[celli].yyyy();
K[celli].zz() = C[celli].zzzz(); K[celli].zz() = C[celli].zzzz();
} }
K.correctBoundaryConditions(); K.correctBoundaryConditions();
} }

View file

@ -1,61 +1,59 @@
if (runTime.outputTime()) if (runTime.outputTime())
{ {
//C.write(); //C.write();
volScalarField epsilonEq volScalarField epsilonEq
( (
IOobject IOobject
( (
"epsilonEq", "epsilonEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((2.0/3.0)*magSqr(dev(epsilon))) sqrt((2.0/3.0)*magSqr(dev(epsilon)))
); );
Info<< "Max epsilonEq = " << max(epsilonEq).value() Info<< "Max epsilonEq = " << max(epsilonEq).value() << endl;
<< endl;
volScalarField sigmaEq volScalarField sigmaEq
( (
IOobject IOobject
( (
"sigmaEq", "sigmaEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((3.0/2.0)*magSqr(dev(sigma))) sqrt((3.0/2.0)*magSqr(dev(sigma)))
); );
Info<< "Max sigmaEq = " << max(sigmaEq).value() Info<< "Max sigmaEq = " << max(sigmaEq).value() << endl;
<< endl;
// volVectorField traction // volVectorField traction
// ( // (
// IOobject // IOobject
// ( // (
// "traction", // "traction",
// runTime.timeName(), // runTime.timeName(),
// mesh,
// IOobject::NO_READ,
// IOobject::AUTO_WRITE
// ),
// mesh, // mesh,
// dimensionedVector("zero", dimForce/dimArea, vector::zero) // IOobject::NO_READ,
// ); // IOobject::AUTO_WRITE
// forAll(mesh.boundary(), patchi) // ),
// { // mesh,
// dimensionedVector("zero", dimForce/dimArea, vector::zero)
// );
// forAll(mesh.boundary(), patchi)
// {
// traction.boundaryField()[patchi] = // traction.boundaryField()[patchi] =
// n.boundaryField()[patchi] & sigma.boundaryField()[patchi]; // n.boundaryField()[patchi] & sigma.boundaryField()[patchi];
// } // }
// //- patch forces // //- patch forces
// forAll(mesh.boundary(), patchi) // forAll(mesh.boundary(), patchi)
// { // {
// Info << "Patch " << mesh.boundary()[patchi].name() << endl; // Info << "Patch " << mesh.boundary()[patchi].name() << endl;
// vectorField totalForce = mesh.Sf().boundaryField()[patchi] & sigma.boundaryField()[patchi]; // vectorField totalForce = mesh.Sf().boundaryField()[patchi] & sigma.boundaryField()[patchi];
// vector force = sum( totalForce ); // vector force = sum( totalForce );
@ -66,7 +64,7 @@ if (runTime.outputTime())
// Info << "\tnormal force is " << normalForce << " N" << endl; // Info << "\tnormal force is " << normalForce << " N" << endl;
// scalar shearForce = mag(sum( (I - sqr(n.boundaryField()[patchi])) & totalForce )); // scalar shearForce = mag(sum( (I - sqr(n.boundaryField()[patchi])) & totalForce ));
// Info << "\tshear force is " << shearForce << " N" << endl; // Info << "\tshear force is " << shearForce << " N" << endl;
// } // }
runTime.write(); runTime.write();
} }

View file

@ -1,32 +1,29 @@
if(divSigmaExpMethod == "standard") if(divSigmaExpMethod == "standard")
{ {
//- calculating the full gradient has good convergence and no high freq oscillations //- calculating the full gradient has good convergence and no high freq oscillations
divSigmaExp = divSigmaExp = fvc::div((C && symm(gradU)) - (K & gradU), "div(sigma)");
fvc::div( }
(C && symm(gradU)) else if(divSigmaExpMethod == "surface")
- (K & gradU), {
"div(sigma)" //- this form seems to have the best convergence
); divSigmaExp = fvc::div
} (
else if(divSigmaExpMethod == "surface") mesh.magSf()*
{
//- this form seems to have the best convergence
divSigmaExp =
fvc::div(mesh.magSf()*
( (
(n&(Cf && fvc::interpolate(symm(gradU)))) (n & (Cf && fvc::interpolate(symm(gradU))))
- (n&(Kf & fvc::interpolate(gradU))) - (n & (Kf & fvc::interpolate(gradU)))
) )
); );
} }
else if(divSigmaExpMethod == "laplacian") else if(divSigmaExpMethod == "laplacian")
{ {
//- can cause high freq oscillations and slow convergence //- can cause high freq oscillations and slow convergence
divSigmaExp = divSigmaExp =
fvc::div(C && symm(epsilon), "div(sigma)") fvc::div(C && symm(epsilon), "div(sigma)")
- fvc::laplacian(K,U, "laplacian(K,U)"); - fvc::laplacian(K, U, "laplacian(K, U)");
} }
else else
{ {
FatalError << "divSigmaExp method " << divSigmaExpMethod << " not found!" << endl; FatalErrorIn(args.executable())
} << "divSigmaExp method " << divSigmaExpMethod << " not found!" << endl;
}

View file

@ -1,14 +1,14 @@
OFstream * filePtr(NULL); OFstream* filePtr(NULL);
word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch")); word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch"));
label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName); label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName);
if(historyPatchID == -1) if(historyPatchID == -1)
{ {
Warning << "history patch " << historyPatchName Warning << "history patch " << historyPatchName
<< " not found. Force-displacement will not be written" << " not found. Force-displacement will not be written"
<< endl; << endl;
} }
else if(Pstream::master()) else if(Pstream::master())
{ {
Info << "Force-displacement for patch " << historyPatchName Info << "Force-displacement for patch " << historyPatchName
<< " will be written to forceDisp.dat" << " will be written to forceDisp.dat"
<< endl; << endl;
@ -17,4 +17,4 @@ if(historyPatchID == -1)
filePtr = new OFstream(hisDirName/historyPatchName+"forceDisp.dat"); filePtr = new OFstream(hisDirName/historyPatchName+"forceDisp.dat");
OFstream& forceDispFile = *filePtr; OFstream& forceDispFile = *filePtr;
forceDispFile << "#Disp(mm)\tForce(N)" << endl; forceDispFile << "#Disp(mm)\tForce(N)" << endl;
} }

View file

@ -48,103 +48,102 @@ Author
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
# include "setRootCase.H" # include "setRootCase.H"
# include "createTime.H" # include "createTime.H"
# include "createMesh.H" # include "createMesh.H"
# include "createFields.H" # include "createFields.H"
# include "createHistory.H" # include "createHistory.H"
# include "readDivSigmaExpMethod.H" # include "readDivSigmaExpMethod.H"
# include "createSolidInterfaceOrthotropic.H" # include "createSolidInterfaceOrthotropic.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl; Info<< "\nStarting time loop\n" << endl;
for (runTime++; !runTime.end(); runTime++) while(runTime.loop())
{ {
Info<< "Time: " << runTime.timeName() << nl << endl; Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
int iCorr = 0; int iCorr = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar initialResidual = 1.0; scalar initialResidual = 1.0;
scalar relativeResidual = 1.0; scalar relativeResidual = 1.0;
lduMatrix::debug = 0; lduMatrix::debug = 0;
do do
{ {
U.storePrevIter(); U.storePrevIter();
# include "calculateDivSigmaExp.H" # include "calculateDivSigmaExp.H"
//- Linear momentum equation //- Linear momentum equation
fvVectorMatrix UEqn fvVectorMatrix UEqn
( (
rho*fvm::d2dt2(U) rho*fvm::d2dt2(U)
== ==
fvm::laplacian(Kf, U, "laplacian(K,U)") fvm::laplacian(Kf, U, "laplacian(K,U)")
+ divSigmaExp + divSigmaExp
);
if (solidInterfaceCorr)
{
solidInterfacePtr->correct(UEqn);
}
solverPerf = UEqn.solve();
if (iCorr == 0)
{
initialResidual = solverPerf.initialResidual();
}
U.relax();
gradU = fvc::grad(U); // use leastSquaresSolidInterface
//# include "setPlaneStressGradU.H"
# include "calculateRelativeResidual.H"
if (iCorr % infoFrequency == 0)
{
Info << "\tTime " << runTime.value()
<< ", Corr " << iCorr
<< ", Solving for " << U.name()
<< " using " << solverPerf.solverName()
<< ", res = " << solverPerf.initialResidual()
<< ", rel res = " << relativeResidual
<< ", inner iters " << solverPerf.nIterations() << endl;
}
}
while
(
solverPerf.initialResidual() > convergenceTolerance
&&
++iCorr < nCorr
); );
Info<< nl << "Time " << runTime.value() << ", Solving for " << U.name() if (solidInterfaceCorr)
<< ", Initial residual = " << initialResidual {
<< ", Final residual = " << solverPerf.initialResidual() solidInterfacePtr->correct(UEqn);
<< ", No outer iterations " << iCorr }
<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< endl;
# include "calculateEpsilonSigma.H" solverPerf = UEqn.solve();
# include "writeFields.H"
# include "writeHistory.H"
Info<< "ExecutionTime = " if (iCorr == 0)
<< runTime.elapsedCpuTime() {
<< " s\n\n" << endl; initialResidual = solverPerf.initialResidual();
}
U.relax();
gradU = fvc::grad(U); // use leastSquaresSolidInterface
//# include "setPlaneStressGradU.H"
# include "calculateRelativeResidual.H"
if (iCorr % infoFrequency == 0)
{
Info<< "\tTime " << runTime.value()
<< ", Corr " << iCorr
<< ", Solving for " << U.name()
<< " using " << solverPerf.solverName()
<< ", res = " << solverPerf.initialResidual()
<< ", rel res = " << relativeResidual
<< ", inner iters " << solverPerf.nIterations() << endl;
}
}
while
(
solverPerf.initialResidual() > convergenceTolerance
&& ++iCorr < nCorr
);
Info<< nl << "Time " << runTime.value() << ", Solving for " << U.name()
<< ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual()
<< ", No outer iterations " << iCorr
<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< endl;
# include "calculateEpsilonSigma.H"
# include "writeFields.H"
# include "writeHistory.H"
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s\n\n"
<< endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;
return(0); return(0);
} }

View file

@ -2,8 +2,8 @@
word divSigmaExpMethod(mesh.solutionDict().subDict("solidMechanics").lookup("divSigmaExp")); word divSigmaExpMethod(mesh.solutionDict().subDict("solidMechanics").lookup("divSigmaExp"));
Info << "Calculation of divSigmaExp Method: " << divSigmaExpMethod << endl; Info << "Calculation of divSigmaExp Method: " << divSigmaExpMethod << endl;
if(divSigmaExpMethod != "standard" && divSigmaExpMethod != "surface" && divSigmaExpMethod != "laplacian") if(divSigmaExpMethod != "standard" && divSigmaExpMethod != "surface" && divSigmaExpMethod != "laplacian")
{ {
FatalError << "divSigmaExp method " << divSigmaExpMethod << " not found!" << nl FatalError << "divSigmaExp method " << divSigmaExpMethod << " not found!" << nl
<< "valid methods are:\nstandard\nsurface\nlaplacian" << "valid methods are:\nstandard\nsurface\nlaplacian"
<< exit(FatalError); << exit(FatalError);
} }

View file

@ -1,13 +1,15 @@
//- set gradU.zz() for plane stress //- set gradU.zz() for plane stress
if(rheology.planeStress()) if(rheology.planeStress())
{ {
forAll(gradU.internalField(), celli) forAll(gradU.internalField(), celli)
{ {
gradU.internalField()[celli].zz() = gradU.internalField()[celli].zz() =
(-C.internalField()[celli].xxzz()*epsilon.internalField()[celli].xx() (
- C.internalField()[celli].yyzz()*epsilon.internalField()[celli].yy()) - C.internalField()[celli].xxzz()*epsilon.internalField()[celli].xx()
- C.internalField()[celli].yyzz()*epsilon.internalField()[celli].yy()
)
/ /
C.internalField()[celli].zzzz(); C.internalField()[celli].zzzz();
} }
gradU.correctBoundaryConditions(); gradU.correctBoundaryConditions();
} }

View file

@ -1,38 +1,36 @@
if (runTime.outputTime()) if (runTime.outputTime())
{ {
//K.write(); //K.write();
volScalarField epsilonEq volScalarField epsilonEq
( (
IOobject IOobject
( (
"epsilonEq", "epsilonEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((2.0/3.0)*magSqr(dev(epsilon))) sqrt((2.0/3.0)*magSqr(dev(epsilon)))
); );
Info<< "Max epsilonEq = " << max(epsilonEq).value() Info<< "Max epsilonEq = " << max(epsilonEq).value() << endl;
<< endl;
volScalarField sigmaEq volScalarField sigmaEq
( (
IOobject IOobject
( (
"sigmaEq", "sigmaEq",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
sqrt((3.0/2.0)*magSqr(dev(sigma))) sqrt((3.0/2.0)*magSqr(dev(sigma)))
); );
Info<< "Max sigmaEq = " << max(sigmaEq).value() Info<< "Max sigmaEq = " << max(sigmaEq).value() << endl;
<< endl;
runTime.write(); runTime.write();
} }

View file

@ -1,19 +1,19 @@
//- write force displacement to file //- write force displacement to file
if(historyPatchID != -1) if(historyPatchID != -1)
{ {
Info << "Writing disp and force of patch "<<historyPatchName<<" to file" Info << "Writing disp and force of patch "<<historyPatchName<<" to file"
<< endl; << endl;
//- for small strain or moving mesh //- for small strain or moving mesh
vector force = gSum(mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID]); vector force = gSum(mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID]);
vector avDisp = gAverage(U.boundaryField()[historyPatchID]); vector avDisp = gAverage(U.boundaryField()[historyPatchID]);
//- write to file //- write to file
if(Pstream::master()) if(Pstream::master())
{ {
OFstream& forceDispFile = *filePtr; OFstream& forceDispFile = *filePtr;
forceDispFile << avDisp.x() << " " << avDisp.y() << " " << avDisp.z() << " " forceDispFile << avDisp.x() << " " << avDisp.y() << " " << avDisp.z() << " "
<< force.x() << " " << force.y() << " " << force.z() << endl; << force.x() << " " << force.y() << " " << force.z() << endl;
} }
} }

View file

@ -11,26 +11,24 @@ aitkenDelta = (DU - DU.prevIter()) / aitkenInitialRes;
// update relaxation factor // update relaxation factor
if(iCorr == 0) if(iCorr == 0)
{ {
aitkenTheta = 0.1; aitkenTheta = 0.1;
} }
else else
{ {
vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField(); vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField();
//scalar sumMagB = gSum(mag(b)); //scalar sumMagB = gSum(mag(b));
scalar sumMagB = gSum(magSqr(b)); scalar sumMagB = gSum(magSqr(b));
if(sumMagB < SMALL) if(sumMagB < SMALL)
{ {
//Warning << "Aitken under-relaxation: denominator less then SMALL" //Warning << "Aitken under-relaxation: denominator less then SMALL"
// << endl; // << endl;
sumMagB += SMALL; sumMagB += SMALL;
} }
aitkenTheta = -aitkenTheta* aitkenTheta = -aitkenTheta*
gSum(aitkenDelta.prevIter().internalField() & b) gSum(aitkenDelta.prevIter().internalField() & b)/sumMagB;
/ }
sumMagB;
}
// correction to the latest DU // correction to the latest DU
DU += aitkenTheta*aitkenDelta*aitkenInitialRes; DU += aitkenTheta*aitkenDelta*aitkenInitialRes;

View file

@ -2,9 +2,7 @@ if(divDSigmaExpMethod == "standard")
{ {
divDSigmaExp = fvc::div divDSigmaExp = fvc::div
( (
(mu*gradDU.T()) mu*gradDU.T() + lambda*(I*tr(gradDU)) - (mu + lambda)*gradDU,
+ (lambda*(I*tr(gradDU)))
- ((mu + lambda)*gradDU),
"div(sigma)" "div(sigma)"
); );
} }
@ -21,11 +19,11 @@ else if(divDSigmaExpMethod == "surface")
); );
// divDSigmaExp = fvc::div // divDSigmaExp = fvc::div
// ( // (
// muf*(mesh.Sf() & fvc::interpolate(gradDU.T())) // muf*(mesh.Sf() & fvc::interpolate(gradDU.T()))
// + lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU))) // + lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU)))
// - (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU)) // - (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU))
// ); // );
} }
else if(divDSigmaExpMethod == "decompose") else if(divDSigmaExpMethod == "decompose")
{ {
@ -42,25 +40,20 @@ else if(divDSigmaExpMethod == "decompose")
); );
// divDSigmaExp = fvc::div // divDSigmaExp = fvc::div
// ( // (
// mesh.magSf() // mesh.magSf()*
// *( // (
// - (muf + lambdaf)*(fvc::snGrad(DU)&(I - n*n)) // - (muf + lambdaf)*(fvc::snGrad(DU)&(I - n*n))
// + lambdaf*tr(shearGradDU&(I - n*n))*n // + lambdaf*tr(shearGradDU&(I - n*n))*n
// + muf*(shearGradDU&n) // + muf*(shearGradDU&n)
// ) // )
// ); // );
} }
else if(divDSigmaExpMethod == "laplacian") else if(divDSigmaExpMethod == "laplacian")
{ {
divDSigmaExp = divDSigmaExp =
- fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)") - fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)")
+ fvc::div + fvc::div(mu*gradDU.T() + lambda*(I*tr(gradDU)), "div(sigma)");
(
mu*gradDU.T()
+ lambda*(I*tr(gradDU)),
"div(sigma)"
);
} }
else else
{ {

View file

@ -6,17 +6,17 @@
// volVectorField divThirdOrderTerm // volVectorField divThirdOrderTerm
// ( // (
// IOobject // IOobject
// ( // (
// "divThirdOrderTerm", // "divThirdOrderTerm",
// runTime.timeName(), // runTime.timeName(),
// mesh, // mesh,
// IOobject::NO_READ, // IOobject::NO_READ,
// IOobject::NO_WRITE // IOobject::NO_WRITE
// ), // ),
// mesh, // mesh,
// dimensionedVector("zero", dimForce/dimVolume, vector::zero) // dimensionedVector("zero", dimForce/dimVolume, vector::zero)
// ); // );
// average gradDU of neighbouring cell centres // average gradDU of neighbouring cell centres
// interpolation scheme should be midPoint // interpolation scheme should be midPoint
@ -25,17 +25,17 @@ surfaceTensorField averageGradDU("averageGradDU", fvc::interpolate(gradDU, "aver
// average face gradDU extrapolated from neighbouring cell centres // average face gradDU extrapolated from neighbouring cell centres
surfaceTensorField extrapGradDU surfaceTensorField extrapGradDU
( (
IOobject IOobject
( (
"extrapGradDU", "extrapGradDU",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedTensor("zero", dimless, tensor::zero) dimensionedTensor("zero", dimless, tensor::zero)
); );
volVectorField gradGradDUcompXX = fvc::grad(gradDU.component(tensor::XX), "gradGradDU"); volVectorField gradGradDUcompXX = fvc::grad(gradDU.component(tensor::XX), "gradGradDU");
volVectorField gradGradDUcompXY = fvc::grad(gradDU.component(tensor::XY), "gradGradDU"); volVectorField gradGradDUcompXY = fvc::grad(gradDU.component(tensor::XY), "gradGradDU");
@ -86,180 +86,181 @@ volScalarField gradGradDUZZZ = gradGradDUcompZZ.component(vector::Z);
forAll(extrapGradDU.internalField(), facei) forAll(extrapGradDU.internalField(), facei)
{ {
const label own = mesh.owner()[facei]; const label own = mesh.owner()[facei];
const label nei = mesh.neighbour()[facei]; const label nei = mesh.neighbour()[facei];
const vector deltaOwn = mesh.Cf()[facei] - mesh.C()[own]; const vector deltaOwn = mesh.Cf()[facei] - mesh.C()[own];
const vector deltaNei = mesh.Cf()[facei] - mesh.C()[nei]; const vector deltaNei = mesh.Cf()[facei] - mesh.C()[nei];
const tensor& gradDUOwn = gradDU.internalField()[own]; const tensor& gradDUOwn = gradDU.internalField()[own];
const tensor& gradDUNei = gradDU.internalField()[nei]; const tensor& gradDUNei = gradDU.internalField()[nei];
// as there is there is no thirdOrderTensor class, we will // as there is there is no thirdOrderTensor class, we will
// calculate (deltaOwn&gradGradDUOwn) out manually // calculate (deltaOwn&gradGradDUOwn) out manually
// tensor deltaOwnDotgradGradDUOwn = tensor::zero; // tensor deltaOwnDotgradGradDUOwn = tensor::zero;
// tensor deltaNeiDotgradGradDUNei = tensor::zero; // tensor deltaNeiDotgradGradDUNei = tensor::zero;
// deltaOwnDotgradGradDUOwn[tensor::XX] = deltaOwn & gradGradDUcompXX.internalField()[own]; // deltaOwnDotgradGradDUOwn[tensor::XX] = deltaOwn & gradGradDUcompXX.internalField()[own];
// deltaNeiDotgradGradDUNei[tensor::XX] = deltaNei & gradGradDUcompXX.internalField()[nei]; // deltaNeiDotgradGradDUNei[tensor::XX] = deltaNei & gradGradDUcompXX.internalField()[nei];
// deltaOwnDotgradGradDUOwn[tensor::XY] = deltaOwn & gradGradDUcompXY.internalField()[own]; // deltaOwnDotgradGradDUOwn[tensor::XY] = deltaOwn & gradGradDUcompXY.internalField()[own];
// deltaNeiDotgradGradDUNei[tensor::XY] = deltaNei & gradGradDUcompXY.internalField()[nei]; // deltaNeiDotgradGradDUNei[tensor::XY] = deltaNei & gradGradDUcompXY.internalField()[nei];
// deltaOwnDotgradGradDUOwn[tensor::XZ] = deltaOwn & gradGradDUcompXZ.internalField()[own]; // deltaOwnDotgradGradDUOwn[tensor::XZ] = deltaOwn & gradGradDUcompXZ.internalField()[own];
// deltaNeiDotgradGradDUNei[tensor::XZ] = deltaNei & gradGradDUcompXZ.internalField()[nei]; // deltaNeiDotgradGradDUNei[tensor::XZ] = deltaNei & gradGradDUcompXZ.internalField()[nei];
// deltaOwnDotgradGradDUOwn[tensor::YX] = deltaOwn & gradGradDUcompYX.internalField()[own]; // deltaOwnDotgradGradDUOwn[tensor::YX] = deltaOwn & gradGradDUcompYX.internalField()[own];
// deltaNeiDotgradGradDUNei[tensor::YX] = deltaNei & gradGradDUcompYX.internalField()[nei]; // deltaNeiDotgradGradDUNei[tensor::YX] = deltaNei & gradGradDUcompYX.internalField()[nei];
// deltaOwnDotgradGradDUOwn[tensor::YY] = deltaOwn & gradGradDUcompYY.internalField()[own]; // deltaOwnDotgradGradDUOwn[tensor::YY] = deltaOwn & gradGradDUcompYY.internalField()[own];
// deltaNeiDotgradGradDUNei[tensor::YY] = deltaNei & gradGradDUcompYY.internalField()[nei]; // deltaNeiDotgradGradDUNei[tensor::YY] = deltaNei & gradGradDUcompYY.internalField()[nei];
// deltaOwnDotgradGradDUOwn[tensor::YZ] = deltaOwn & gradGradDUcompYZ.internalField()[own]; // deltaOwnDotgradGradDUOwn[tensor::YZ] = deltaOwn & gradGradDUcompYZ.internalField()[own];
// deltaNeiDotgradGradDUNei[tensor::YZ] = deltaNei & gradGradDUcompYZ.internalField()[nei]; // deltaNeiDotgradGradDUNei[tensor::YZ] = deltaNei & gradGradDUcompYZ.internalField()[nei];
// deltaOwnDotgradGradDUOwn[tensor::ZX] = deltaOwn & gradGradDUcompZX.internalField()[own]; // deltaOwnDotgradGradDUOwn[tensor::ZX] = deltaOwn & gradGradDUcompZX.internalField()[own];
// deltaNeiDotgradGradDUNei[tensor::ZX] = deltaNei & gradGradDUcompZX.internalField()[nei]; // deltaNeiDotgradGradDUNei[tensor::ZX] = deltaNei & gradGradDUcompZX.internalField()[nei];
// deltaOwnDotgradGradDUOwn[tensor::ZY] = deltaOwn & gradGradDUcompZY.internalField()[own]; // deltaOwnDotgradGradDUOwn[tensor::ZY] = deltaOwn & gradGradDUcompZY.internalField()[own];
// deltaNeiDotgradGradDUNei[tensor::ZY] = deltaNei & gradGradDUcompZY.internalField()[nei]; // deltaNeiDotgradGradDUNei[tensor::ZY] = deltaNei & gradGradDUcompZY.internalField()[nei];
// deltaOwnDotgradGradDUOwn[tensor::ZZ] = deltaOwn & gradGradDUcompZZ.internalField()[own]; // deltaOwnDotgradGradDUOwn[tensor::ZZ] = deltaOwn & gradGradDUcompZZ.internalField()[own];
// deltaNeiDotgradGradDUNei[tensor::ZZ] = deltaNei & gradGradDUcompZZ.internalField()[nei]; // deltaNeiDotgradGradDUNei[tensor::ZZ] = deltaNei & gradGradDUcompZZ.internalField()[nei];
scalar gradGradDUXXXOwn = gradGradDUXXX.internalField()[own]; scalar gradGradDUXXXOwn = gradGradDUXXX.internalField()[own];
scalar gradGradDUXXYOwn = gradGradDUXXY.internalField()[own]; scalar gradGradDUXXYOwn = gradGradDUXXY.internalField()[own];
scalar gradGradDUXXZOwn = gradGradDUXXZ.internalField()[own]; scalar gradGradDUXXZOwn = gradGradDUXXZ.internalField()[own];
scalar gradGradDUXYXOwn = gradGradDUXYX.internalField()[own]; scalar gradGradDUXYXOwn = gradGradDUXYX.internalField()[own];
scalar gradGradDUXYYOwn = gradGradDUXYY.internalField()[own]; scalar gradGradDUXYYOwn = gradGradDUXYY.internalField()[own];
scalar gradGradDUXYZOwn = gradGradDUXYZ.internalField()[own]; scalar gradGradDUXYZOwn = gradGradDUXYZ.internalField()[own];
scalar gradGradDUXZXOwn = gradGradDUXZX.internalField()[own]; scalar gradGradDUXZXOwn = gradGradDUXZX.internalField()[own];
scalar gradGradDUXZYOwn = gradGradDUXZY.internalField()[own]; scalar gradGradDUXZYOwn = gradGradDUXZY.internalField()[own];
scalar gradGradDUXZZOwn = gradGradDUXZZ.internalField()[own]; scalar gradGradDUXZZOwn = gradGradDUXZZ.internalField()[own];
scalar gradGradDUYXXOwn = gradGradDUYXX.internalField()[own]; scalar gradGradDUYXXOwn = gradGradDUYXX.internalField()[own];
scalar gradGradDUYXYOwn = gradGradDUYXY.internalField()[own]; scalar gradGradDUYXYOwn = gradGradDUYXY.internalField()[own];
scalar gradGradDUYXZOwn = gradGradDUYXZ.internalField()[own]; scalar gradGradDUYXZOwn = gradGradDUYXZ.internalField()[own];
scalar gradGradDUYYXOwn = gradGradDUYYX.internalField()[own]; scalar gradGradDUYYXOwn = gradGradDUYYX.internalField()[own];
scalar gradGradDUYYYOwn = gradGradDUYYY.internalField()[own]; scalar gradGradDUYYYOwn = gradGradDUYYY.internalField()[own];
scalar gradGradDUYYZOwn = gradGradDUYYZ.internalField()[own]; scalar gradGradDUYYZOwn = gradGradDUYYZ.internalField()[own];
scalar gradGradDUYZXOwn = gradGradDUYZX.internalField()[own]; scalar gradGradDUYZXOwn = gradGradDUYZX.internalField()[own];
scalar gradGradDUYZYOwn = gradGradDUYZY.internalField()[own]; scalar gradGradDUYZYOwn = gradGradDUYZY.internalField()[own];
scalar gradGradDUYZZOwn = gradGradDUYZZ.internalField()[own]; scalar gradGradDUYZZOwn = gradGradDUYZZ.internalField()[own];
scalar gradGradDUZXXOwn = gradGradDUZXX.internalField()[own]; scalar gradGradDUZXXOwn = gradGradDUZXX.internalField()[own];
scalar gradGradDUZXYOwn = gradGradDUZXY.internalField()[own]; scalar gradGradDUZXYOwn = gradGradDUZXY.internalField()[own];
scalar gradGradDUZXZOwn = gradGradDUZXZ.internalField()[own]; scalar gradGradDUZXZOwn = gradGradDUZXZ.internalField()[own];
scalar gradGradDUZYXOwn = gradGradDUZYX.internalField()[own]; scalar gradGradDUZYXOwn = gradGradDUZYX.internalField()[own];
scalar gradGradDUZYYOwn = gradGradDUZYY.internalField()[own]; scalar gradGradDUZYYOwn = gradGradDUZYY.internalField()[own];
scalar gradGradDUZYZOwn = gradGradDUZYZ.internalField()[own]; scalar gradGradDUZYZOwn = gradGradDUZYZ.internalField()[own];
scalar gradGradDUZZXOwn = gradGradDUZZX.internalField()[own]; scalar gradGradDUZZXOwn = gradGradDUZZX.internalField()[own];
scalar gradGradDUZZYOwn = gradGradDUZZY.internalField()[own]; scalar gradGradDUZZYOwn = gradGradDUZZY.internalField()[own];
scalar gradGradDUZZZOwn = gradGradDUZZZ.internalField()[own]; scalar gradGradDUZZZOwn = gradGradDUZZZ.internalField()[own];
// nei // nei
scalar gradGradDUXXXNei = gradGradDUXXX.internalField()[nei]; scalar gradGradDUXXXNei = gradGradDUXXX.internalField()[nei];
scalar gradGradDUXXYNei = gradGradDUXXY.internalField()[nei]; scalar gradGradDUXXYNei = gradGradDUXXY.internalField()[nei];
scalar gradGradDUXXZNei = gradGradDUXXZ.internalField()[nei]; scalar gradGradDUXXZNei = gradGradDUXXZ.internalField()[nei];
scalar gradGradDUXYXNei = gradGradDUXYX.internalField()[nei]; scalar gradGradDUXYXNei = gradGradDUXYX.internalField()[nei];
scalar gradGradDUXYYNei = gradGradDUXYY.internalField()[nei]; scalar gradGradDUXYYNei = gradGradDUXYY.internalField()[nei];
scalar gradGradDUXYZNei = gradGradDUXYZ.internalField()[nei]; scalar gradGradDUXYZNei = gradGradDUXYZ.internalField()[nei];
scalar gradGradDUXZXNei = gradGradDUXZX.internalField()[nei]; scalar gradGradDUXZXNei = gradGradDUXZX.internalField()[nei];
scalar gradGradDUXZYNei = gradGradDUXZY.internalField()[nei]; scalar gradGradDUXZYNei = gradGradDUXZY.internalField()[nei];
scalar gradGradDUXZZNei = gradGradDUXZZ.internalField()[nei]; scalar gradGradDUXZZNei = gradGradDUXZZ.internalField()[nei];
scalar gradGradDUYXXNei = gradGradDUYXX.internalField()[nei]; scalar gradGradDUYXXNei = gradGradDUYXX.internalField()[nei];
scalar gradGradDUYXYNei = gradGradDUYXY.internalField()[nei]; scalar gradGradDUYXYNei = gradGradDUYXY.internalField()[nei];
scalar gradGradDUYXZNei = gradGradDUYXZ.internalField()[nei]; scalar gradGradDUYXZNei = gradGradDUYXZ.internalField()[nei];
scalar gradGradDUYYXNei = gradGradDUYYX.internalField()[nei]; scalar gradGradDUYYXNei = gradGradDUYYX.internalField()[nei];
scalar gradGradDUYYYNei = gradGradDUYYY.internalField()[nei]; scalar gradGradDUYYYNei = gradGradDUYYY.internalField()[nei];
scalar gradGradDUYYZNei = gradGradDUYYZ.internalField()[nei]; scalar gradGradDUYYZNei = gradGradDUYYZ.internalField()[nei];
scalar gradGradDUYZXNei = gradGradDUYZX.internalField()[nei]; scalar gradGradDUYZXNei = gradGradDUYZX.internalField()[nei];
scalar gradGradDUYZYNei = gradGradDUYZY.internalField()[nei]; scalar gradGradDUYZYNei = gradGradDUYZY.internalField()[nei];
scalar gradGradDUYZZNei = gradGradDUYZZ.internalField()[nei]; scalar gradGradDUYZZNei = gradGradDUYZZ.internalField()[nei];
scalar gradGradDUZXXNei = gradGradDUZXX.internalField()[nei]; scalar gradGradDUZXXNei = gradGradDUZXX.internalField()[nei];
scalar gradGradDUZXYNei = gradGradDUZXY.internalField()[nei]; scalar gradGradDUZXYNei = gradGradDUZXY.internalField()[nei];
scalar gradGradDUZXZNei = gradGradDUZXZ.internalField()[nei]; scalar gradGradDUZXZNei = gradGradDUZXZ.internalField()[nei];
scalar gradGradDUZYXNei = gradGradDUZYX.internalField()[nei]; scalar gradGradDUZYXNei = gradGradDUZYX.internalField()[nei];
scalar gradGradDUZYYNei = gradGradDUZYY.internalField()[nei]; scalar gradGradDUZYYNei = gradGradDUZYY.internalField()[nei];
scalar gradGradDUZYZNei = gradGradDUZYZ.internalField()[nei]; scalar gradGradDUZYZNei = gradGradDUZYZ.internalField()[nei];
scalar gradGradDUZZXNei = gradGradDUZZX.internalField()[nei]; scalar gradGradDUZZXNei = gradGradDUZZX.internalField()[nei];
scalar gradGradDUZZYNei = gradGradDUZZY.internalField()[nei]; scalar gradGradDUZZYNei = gradGradDUZZY.internalField()[nei];
scalar gradGradDUZZZNei = gradGradDUZZZ.internalField()[nei]; scalar gradGradDUZZZNei = gradGradDUZZZ.internalField()[nei];
tensor deltaOwnDotgradGradDUOwn = tensor deltaOwnDotgradGradDUOwn = tensor
tensor(
deltaOwn.x()*gradGradDUXXXOwn + deltaOwn.y()*gradGradDUYXXOwn + deltaOwn.z()*gradGradDUZXXOwn,
deltaOwn.x()*gradGradDUXXYOwn + deltaOwn.y()*gradGradDUYXYOwn + deltaOwn.z()*gradGradDUZXYOwn,
deltaOwn.x()*gradGradDUXXZOwn + deltaOwn.y()*gradGradDUYXZOwn + deltaOwn.z()*gradGradDUZXZOwn,
deltaOwn.x()*gradGradDUXYXOwn + deltaOwn.y()*gradGradDUYYXOwn + deltaOwn.z()*gradGradDUZYXOwn,
deltaOwn.x()*gradGradDUXYYOwn + deltaOwn.y()*gradGradDUYYYOwn + deltaOwn.z()*gradGradDUZYYOwn,
deltaOwn.x()*gradGradDUXYZOwn + deltaOwn.y()*gradGradDUYYZOwn + deltaOwn.z()*gradGradDUZYZOwn,
deltaOwn.x()*gradGradDUXZXOwn + deltaOwn.y()*gradGradDUYZXOwn + deltaOwn.z()*gradGradDUZZXOwn,
deltaOwn.x()*gradGradDUXZYOwn + deltaOwn.y()*gradGradDUYZYOwn + deltaOwn.z()*gradGradDUZZYOwn,
deltaOwn.x()*gradGradDUXZZOwn + deltaOwn.y()*gradGradDUYZZOwn + deltaOwn.z()*gradGradDUZZZOwn
);
tensor deltaNeiDotgradGradDUNei =
tensor(
deltaNei.x()*gradGradDUXXXNei + deltaNei.y()*gradGradDUYXXNei + deltaNei.z()*gradGradDUZXXNei,
deltaNei.x()*gradGradDUXXYNei + deltaNei.y()*gradGradDUYXYNei + deltaNei.z()*gradGradDUZXYNei,
deltaNei.x()*gradGradDUXXZNei + deltaNei.y()*gradGradDUYXZNei + deltaNei.z()*gradGradDUZXZNei,
deltaNei.x()*gradGradDUXYXNei + deltaNei.y()*gradGradDUYYXNei + deltaNei.z()*gradGradDUZYXNei,
deltaNei.x()*gradGradDUXYYNei + deltaNei.y()*gradGradDUYYYNei + deltaNei.z()*gradGradDUZYYNei,
deltaNei.x()*gradGradDUXYZNei + deltaNei.y()*gradGradDUYYZNei + deltaNei.z()*gradGradDUZYZNei,
deltaNei.x()*gradGradDUXZXNei + deltaNei.y()*gradGradDUYZXNei + deltaNei.z()*gradGradDUZZXNei,
deltaNei.x()*gradGradDUXZYNei + deltaNei.y()*gradGradDUYZYNei + deltaNei.z()*gradGradDUZZYNei,
deltaNei.x()*gradGradDUXZZNei + deltaNei.y()*gradGradDUYZZNei + deltaNei.z()*gradGradDUZZZNei
);
// get average of extrapolated values
tensor extrapFaceGrad =
0.5*
( (
gradDUOwn + (deltaOwnDotgradGradDUOwn) deltaOwn.x()*gradGradDUXXXOwn + deltaOwn.y()*gradGradDUYXXOwn + deltaOwn.z()*gradGradDUZXXOwn,
+ deltaOwn.x()*gradGradDUXXYOwn + deltaOwn.y()*gradGradDUYXYOwn + deltaOwn.z()*gradGradDUZXYOwn,
gradDUNei + (deltaNeiDotgradGradDUNei) deltaOwn.x()*gradGradDUXXZOwn + deltaOwn.y()*gradGradDUYXZOwn + deltaOwn.z()*gradGradDUZXZOwn,
);
extrapGradDU.internalField()[facei] = extrapFaceGrad; deltaOwn.x()*gradGradDUXYXOwn + deltaOwn.y()*gradGradDUYYXOwn + deltaOwn.z()*gradGradDUZYXOwn,
deltaOwn.x()*gradGradDUXYYOwn + deltaOwn.y()*gradGradDUYYYOwn + deltaOwn.z()*gradGradDUZYYOwn,
deltaOwn.x()*gradGradDUXYZOwn + deltaOwn.y()*gradGradDUYYZOwn + deltaOwn.z()*gradGradDUZYZOwn,
deltaOwn.x()*gradGradDUXZXOwn + deltaOwn.y()*gradGradDUYZXOwn + deltaOwn.z()*gradGradDUZZXOwn,
deltaOwn.x()*gradGradDUXZYOwn + deltaOwn.y()*gradGradDUYZYOwn + deltaOwn.z()*gradGradDUZZYOwn,
deltaOwn.x()*gradGradDUXZZOwn + deltaOwn.y()*gradGradDUYZZOwn + deltaOwn.z()*gradGradDUZZZOwn
);
tensor deltaNeiDotgradGradDUNei = tensor
(
deltaNei.x()*gradGradDUXXXNei + deltaNei.y()*gradGradDUYXXNei + deltaNei.z()*gradGradDUZXXNei,
deltaNei.x()*gradGradDUXXYNei + deltaNei.y()*gradGradDUYXYNei + deltaNei.z()*gradGradDUZXYNei,
deltaNei.x()*gradGradDUXXZNei + deltaNei.y()*gradGradDUYXZNei + deltaNei.z()*gradGradDUZXZNei,
deltaNei.x()*gradGradDUXYXNei + deltaNei.y()*gradGradDUYYXNei + deltaNei.z()*gradGradDUZYXNei,
deltaNei.x()*gradGradDUXYYNei + deltaNei.y()*gradGradDUYYYNei + deltaNei.z()*gradGradDUZYYNei,
deltaNei.x()*gradGradDUXYZNei + deltaNei.y()*gradGradDUYYZNei + deltaNei.z()*gradGradDUZYZNei,
deltaNei.x()*gradGradDUXZXNei + deltaNei.y()*gradGradDUYZXNei + deltaNei.z()*gradGradDUZZXNei,
deltaNei.x()*gradGradDUXZYNei + deltaNei.y()*gradGradDUYZYNei + deltaNei.z()*gradGradDUZZYNei,
deltaNei.x()*gradGradDUXZZNei + deltaNei.y()*gradGradDUYZZNei + deltaNei.z()*gradGradDUZZZNei
);
// get average of extrapolated values
tensor extrapFaceGrad =
0.5*
(
gradDUOwn + (deltaOwnDotgradGradDUOwn)
+
gradDUNei + (deltaNeiDotgradGradDUNei)
);
extrapGradDU.internalField()[facei] = extrapFaceGrad;
} }
// correction is zero on boundary // correction is zero on boundary
forAll(extrapGradDU.boundaryField(), patchi) forAll(extrapGradDU.boundaryField(), patchi)
{ {
extrapGradDU.boundaryField()[patchi] = extrapGradDU.boundaryField()[patchi] =
averageGradDU.boundaryField()[patchi]; averageGradDU.boundaryField()[patchi];
} }
// calculate thirdOrderTerm // calculate thirdOrderTerm
volVectorField divThirdOrderTerm ( volVectorField divThirdOrderTerm
"thirdOrderTerm", (
fvc::div( "thirdOrderTerm",
(2*muf+lambdaf)*mesh.Sf() fvc::div
& (extrapGradDU - averageGradDU) (
) (2*muf+lambdaf)*mesh.Sf() & (extrapGradDU - averageGradDU)
); )
);
// if(runTime.outputTime()) // if(runTime.outputTime())
// { // {
// divThirdOrderTerm.write(); // divThirdOrderTerm.write();
// averageGradDU.write(); // averageGradDU.write();
// extrapGradDU.write(); // extrapGradDU.write();
// } // }

View file

@ -14,6 +14,7 @@
volTensorField gradDU = fvc::grad(DU); volTensorField gradDU = fvc::grad(DU);
Info<< "Creating field U\n" << endl;
volVectorField U volVectorField U
( (
IOobject IOobject
@ -24,23 +25,23 @@
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimLength, vector::zero) dimensionedVector("zero", dimLength, vector::zero)
); );
volTensorField gradU volTensorField gradU
( (
IOobject IOobject
( (
"grad(U)", "grad(U)",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedTensor("zero", dimless, tensor::zero) dimensionedTensor("zero", dimless, tensor::zero)
); );
//- Increment of Green finite strain tensor //- Increment of Green finite strain tensor
volSymmTensorField DEpsilon volSymmTensorField DEpsilon
@ -53,8 +54,8 @@
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedSymmTensor("zero", dimless, symmTensor::zero) dimensionedSymmTensor("zero", dimless, symmTensor::zero)
); );
volSymmTensorField epsilon volSymmTensorField epsilon
@ -67,8 +68,8 @@
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedSymmTensor("zero", dimless, symmTensor::zero) dimensionedSymmTensor("zero", dimless, symmTensor::zero)
); );
//- plastic strain //- plastic strain
@ -113,42 +114,41 @@
IOobject::READ_IF_PRESENT, IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE IOobject::AUTO_WRITE
), ),
mesh, mesh,
dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero) dimensionedSymmTensor("zero", dimForce/dimArea, symmTensor::zero)
); );
volVectorField divDSigmaExp volVectorField divDSigmaExp
( (
IOobject IOobject
( (
"divDSigmaExp", "divDSigmaExp",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimensionSet(1,-2,-2,0,0,0,0), vector::zero) dimensionedVector("zero", dimensionSet(1, -2, -2, 0, 0, 0, 0), vector::zero)
); );
volVectorField divDSigmaNonLinExp volVectorField divDSigmaNonLinExp
( (
IOobject IOobject
( (
"divDSigmaNonLinExp", "divDSigmaNonLinExp",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimensionSet(1,-2,-2,0,0,0,0), vector::zero) dimensionedVector("zero", dimensionSet(1,-2,-2,0,0,0,0), vector::zero)
); );
constitutiveModel rheology(sigma, DU); constitutiveModel rheology(sigma, DU);
volScalarField rho = rheology.rho(); volScalarField rho = rheology.rho();
volScalarField mu = rheology.mu(); volScalarField mu = rheology.mu();
volScalarField lambda = rheology.lambda(); volScalarField lambda = rheology.lambda();
surfaceScalarField muf = fvc::interpolate(mu, "mu"); surfaceScalarField muf = fvc::interpolate(mu, "mu");
@ -156,11 +156,11 @@
surfaceVectorField n = mesh.Sf()/mesh.magSf(); surfaceVectorField n = mesh.Sf()/mesh.magSf();
// plastic strain increment // plastic strain increment
const volSymmTensorField& DEpsilonP = rheology.DEpsilonP(); const volSymmTensorField& DEpsilonP = rheology.DEpsilonP();
// for aitken relaxation // for aitken relaxation
volVectorField aitkenDelta volVectorField aitkenDelta
( (
IOobject IOobject
( (
@ -171,22 +171,23 @@
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimLength, vector::zero) dimensionedVector("zero", dimLength, vector::zero)
); );
// aitken relaxation factor
scalar aitkenInitialRes = 1.0; // aitken relaxation factor
scalar aitkenTheta = 0.1; scalar aitkenInitialRes = 1.0;
scalar aitkenTheta = 0.1;
// volVectorField resid // volVectorField resid
// ( // (
// IOobject // IOobject
// ( // (
// "resid", // "resid",
// runTime.timeName(), // runTime.timeName(),
// mesh, // mesh,
// IOobject::NO_READ, // IOobject::NO_READ,
// IOobject::AUTO_WRITE // IOobject::AUTO_WRITE
// ), // ),
// mesh, // mesh,
// dimensionedVector("zero", dimless, vector::zero) // dimensionedVector("zero", dimless, vector::zero)
// ); // );

View file

@ -1,36 +1,36 @@
OFstream * forceFilePtr(NULL); OFstream* forceFilePtr(NULL);
OFstream * stressFilePtr(NULL); OFstream* stressFilePtr(NULL);
word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch")); word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch"));
label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName); label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName);
if(historyPatchID == -1) if(historyPatchID == -1)
{ {
Warning << "history patch " << historyPatchName Warning << "history patch " << historyPatchName
<< " not found. Force-displacement will not be written" << " not found. Force-displacement will not be written"
<< endl; << endl;
} }
else if(Pstream::master()) else if(Pstream::master())
{ {
fileName historyDir = "history"; fileName historyDir = "history";
mkDir(historyDir); mkDir(historyDir);
{ {
fileName forceFileName(historyDir/"forceDisp_"+historyPatchName+".dat"); fileName forceFileName(historyDir/"forceDisp_"+historyPatchName+".dat");
Info << "\nForce-displacement for patch " << historyPatchName Info << "\nForce-displacement for patch " << historyPatchName
<< " will be written to " << forceFileName << " will be written to " << forceFileName
<< endl; << endl;
forceFilePtr = new OFstream(forceFileName); forceFilePtr = new OFstream(forceFileName);
OFstream& forceDispFile = *forceFilePtr; OFstream& forceDispFile = *forceFilePtr;
forceDispFile << "#Disp(mm)\tForce(N)" << endl; forceDispFile << "#Disp(mm)\tForce(N)" << endl;
} }
{ {
fileName stressFileName(historyDir/"stressStrain_"+historyPatchName+".dat"); fileName stressFileName(historyDir/"stressStrain_"+historyPatchName+".dat");
Info << "\nStress(2nd Piola-Kirchoff)-strain(Green) for patch " Info << "\nStress(2nd Piola-Kirchoff)-strain(Green) for patch "
<< historyPatchName << historyPatchName
<< " will be written to " << stressFileName << " will be written to " << stressFileName
<< endl; << endl;
stressFilePtr = new OFstream(stressFileName); stressFilePtr = new OFstream(stressFileName);
OFstream& stressStrainFile = *stressFilePtr; OFstream& stressStrainFile = *stressFilePtr;
stressStrainFile << "#Strain(-)\tStress(Pa)" << endl; stressStrainFile << "#Strain(-)\tStress(Pa)" << endl;
} }
} }

View file

@ -54,158 +54,158 @@ int main(int argc, char *argv[])
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl; Info<< "\nStarting time loop\n" << endl;
while(runTime.loop()) while(runTime.loop())
{ {
Info<< "Time: " << runTime.timeName() << nl << endl; Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
int iCorr = 0; int iCorr = 0;
scalar initialResidual = 0; scalar initialResidual = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar relativeResidual = GREAT; scalar relativeResidual = GREAT;
lduMatrix::debug = 0; lduMatrix::debug = 0;
do do
{ {
DU.storePrevIter(); DU.storePrevIter();
# include "calculateDivDSigmaExp.H" # include "calculateDivDSigmaExp.H"
# include "calculateDivDSigmaNonLinExp.H" # include "calculateDivDSigmaNonLinExp.H"
// Incremental form of the // Incremental form of the
// linear momentum conservation // linear momentum conservation
// ensuring conservation of total momentum // ensuring conservation of total momentum
fvVectorMatrix DUEqn fvVectorMatrix DUEqn
( (
fvm::d2dt2(rho, DU) fvm::d2dt2(rho, DU)
== ==
fvm::laplacian(2*muf + lambdaf, DU, "laplacian(DDU,DU)") fvm::laplacian(2*muf + lambdaf, DU, "laplacian(DDU,DU)")
+ divDSigmaExp + divDSigmaExp
+ divDSigmaNonLinExp + divDSigmaNonLinExp
//- fvc::div(2*mu*DEpsilonP, "div(sigma)") //- fvc::div(2*mu*DEpsilonP, "div(sigma)")
- fvc::div - fvc::div
( (
2*muf*(mesh.Sf() & fvc::interpolate(DEpsilonP)) 2*muf*(mesh.Sf() & fvc::interpolate(DEpsilonP))
) )
); );
if (largeStrainOverRelax) if (largeStrainOverRelax)
{ {
// the terms (gradDU & gradU.T()) and (gradU & gradDU.T()) // the terms (gradDU & gradU.T()) and (gradU & gradDU.T())
// are linearly dependent of DU and represent initial // are linearly dependent of DU and represent initial
// displacement effect // displacement effect
// which can cause convergence difficulties when treated // which can cause convergence difficulties when treated
// explicitly // explicitly
// so we implicitly over-relax with gradU & gradDU here // so we implicitly over-relax with gradU & gradDU here
// which tends to help convergence // which tends to help convergence
// this should improve convergence when gradU is large // this should improve convergence when gradU is large
// but maybe not execution time // but maybe not execution time
DUEqn -= DUEqn -=
fvm::laplacian fvm::laplacian
( (
(2*mu + lambda)*gradU, DU, "laplacian(DDU,DU)" (2*mu + lambda)*gradU, DU, "laplacian(DDU,DU)"
) )
- fvc::div((2*mu + lambda)*(gradU & gradDU), "div(sigma)"); - fvc::div((2*mu + lambda)*(gradU & gradDU), "div(sigma)");
} }
if (nonLinearSemiImplicit) if (nonLinearSemiImplicit)
{ {
// experimental // experimental
// we can treat the nonlinear term (gradDU & gradDU.T()) in a // we can treat the nonlinear term (gradDU & gradDU.T()) in a
// semi-implicit over-relaxed manner // semi-implicit over-relaxed manner
// this should improve convergence when gradDU is large // this should improve convergence when gradDU is large
// but maybe not execution time // but maybe not execution time
DUEqn -= DUEqn -=
fvm::laplacian fvm::laplacian
( (
(2*mu + lambda)*gradDU, DU, "laplacian(DDU,DU)" (2*mu + lambda)*gradDU, DU, "laplacian(DDU,DU)"
) )
- fvc::div((2*mu + lambda)*(gradDU & gradDU), "div(sigma)"); - fvc::div((2*mu + lambda)*(gradDU & gradDU), "div(sigma)");
} }
solverPerf = DUEqn.solve(); solverPerf = DUEqn.solve();
if (iCorr == 0) if (iCorr == 0)
{ {
initialResidual = solverPerf.initialResidual(); initialResidual = solverPerf.initialResidual();
} }
if (aitkenRelax) if (aitkenRelax)
{ {
# include "aitkenRelaxation.H" # include "aitkenRelaxation.H"
} }
else else
{ {
DU.relax(); DU.relax();
} }
gradDU = fvc::grad(DU); gradDU = fvc::grad(DU);
// correct plasticty term // correct plasticty term
rheology.correct(); rheology.correct();
# include "calculateDEpsilonDSigma.H" # include "calculateDEpsilonDSigma.H"
# include "calculateRelativeResidual.H" # include "calculateRelativeResidual.H"
if (iCorr % infoFrequency == 0) if(iCorr % infoFrequency == 0)
{ {
Info<< "\tTime " << runTime.value() Info<< "\tTime " << runTime.value()
<< ", Corrector " << iCorr << ", Corrector " << iCorr
<< ", Solving for " << DU.name() << ", Solving for " << DU.name()
<< " using " << solverPerf.solverName() << " using " << solverPerf.solverName()
<< ", res = " << solverPerf.initialResidual() << ", res = " << solverPerf.initialResidual()
<< ", rel res = " << relativeResidual; << ", rel res = " << relativeResidual;
if (aitkenRelax) if(aitkenRelax)
{ {
Info << ", aitken = " << aitkenTheta; Info<< ", aitken = " << aitkenTheta;
} }
Info << ", iters = " << solverPerf.nIterations() << endl; Info<< ", iters = " << solverPerf.nIterations() << endl;
} }
} }
while while
( (
iCorr++ == 0 iCorr++ == 0
|| ||
( (
//solverPerf.initialResidual() > convergenceTolerance //solverPerf.initialResidual() > convergenceTolerance
relativeResidual > convergenceTolerance relativeResidual > convergenceTolerance
&& iCorr < nCorr && iCorr < nCorr
) )
); );
Info<< nl << "Time " << runTime.value() << ", Solving for " << DU.name() Info<< nl << "Time " << runTime.value() << ", Solving for " << DU.name()
<< ", Initial residual = " << initialResidual << ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual() << ", Final residual = " << solverPerf.initialResidual()
<< ", Relative residual = " << relativeResidual << ", Relative residual = " << relativeResidual
<< ", No outer iterations " << iCorr << ", No outer iterations " << iCorr
<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s"
<< endl; << endl;
// Update total quantities // Update total quantities
U += DU; U += DU;
gradU += gradDU; gradU += gradDU;
epsilon += DEpsilon; epsilon += DEpsilon;
epsilonP += rheology.DEpsilonP(); epsilonP += rheology.DEpsilonP();
sigma += DSigma; sigma += DSigma;
rheology.updateYieldStress(); rheology.updateYieldStress();
rho = rho/det(I+gradU); rho = rho/det(I+gradU);
# include "writeFields.H" # include "writeFields.H"
# include "writeHistory.H" # include "writeHistory.H"
Info<< "ExecutionTime = " Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< runTime.elapsedCpuTime() << " ClockTime = " << runTime.elapsedClockTime() << " s"
<< " s\n\n" << endl; << endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;
return(0); return(0);
} }

View file

@ -2,8 +2,8 @@
word divDSigmaNonLinExpMethod(mesh.solutionDict().subDict("solidMechanics").lookup("divSigmaNonLinExp")); word divDSigmaNonLinExpMethod(mesh.solutionDict().subDict("solidMechanics").lookup("divSigmaNonLinExp"));
Info << "divSigmaNonLinExp method " << divDSigmaNonLinExpMethod << endl; Info << "divSigmaNonLinExp method " << divDSigmaNonLinExpMethod << endl;
if(divDSigmaNonLinExpMethod != "standard" && divDSigmaNonLinExpMethod != "surface") if(divDSigmaNonLinExpMethod != "standard" && divDSigmaNonLinExpMethod != "surface")
{ {
FatalError << "divSigmaNonLinExp method " << divDSigmaNonLinExpMethod << " not found!" << nl FatalError << "divSigmaNonLinExp method " << divDSigmaNonLinExpMethod << " not found!" << nl
<< "valid methods are:\nstandard\nsurface" << "valid methods are:\nstandard\nsurface"
<< exit(FatalError); << exit(FatalError);
} }

View file

@ -1,45 +1,45 @@
//- write force displacement to file //- write force displacement to file
if(historyPatchID != -1) if(historyPatchID != -1)
{ {
Info << "Writing disp-force to file for patch " << historyPatchName Info << "Writing disp-force to file for patch " << historyPatchName
<< endl; << endl;
//- for small strain or moving mesh //- for small strain or moving mesh
//scalar force = gSum( //scalar force = gSum(
// direction & // direction &
// (mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID]) // (mesh.boundary()[historyPatchID].Sf() & sigma.boundaryField()[historyPatchID])
// ); //);
//- for large strain total lagrangian //- for large strain total lagrangian
tensorField F = I + gradU.boundaryField()[historyPatchID]; tensorField F = I + gradU.boundaryField()[historyPatchID];
vector force = gSum(mesh.Sf().boundaryField()[historyPatchID] & (sigma.boundaryField()[historyPatchID] & F)); vector force = gSum(mesh.Sf().boundaryField()[historyPatchID] & (sigma.boundaryField()[historyPatchID] & F));
vector disp = gAverage(U.boundaryField()[historyPatchID]); vector disp = gAverage(U.boundaryField()[historyPatchID]);
Info << "Writing strain-stress to file for patch " << historyPatchName Info << "Writing strain-stress to file for patch " << historyPatchName
<< endl; << endl;
// avaerage stress strain // average stress strain
symmTensor stress = gAverage(sigma.boundaryField()[historyPatchID]); symmTensor stress = gAverage(sigma.boundaryField()[historyPatchID]);
symmTensor strain = gAverage(epsilon.boundaryField()[historyPatchID]); symmTensor strain = gAverage(epsilon.boundaryField()[historyPatchID]);
// write to file // write to file
if(Pstream::master()) if(Pstream::master())
{ {
OFstream& forceDispFile = *forceFilePtr; OFstream& forceDispFile = *forceFilePtr;
label width = 20; label width = 20;
forceDispFile << disp.x() << " " << disp.y() << " " << disp.z(); forceDispFile << disp.x() << " " << disp.y() << " " << disp.z();
forceDispFile.width(width); forceDispFile.width(width);
forceDispFile << force.x() << " " << force.y() << " " << force.z() forceDispFile << force.x() << " " << force.y() << " " << force.z()
<< endl; << endl;
OFstream& stressStrainFile = *stressFilePtr; OFstream& stressStrainFile = *stressFilePtr;
stressStrainFile << strain.xx() << " " << strain.xy() << " " << strain.xz() << " " stressStrainFile << strain.xx() << " " << strain.xy() << " " << strain.xz() << " "
<< strain.yy() << " " << strain.yz() << " " << strain.zz(); << strain.yy() << " " << strain.yz() << " " << strain.zz();
stressStrainFile.width(width); stressStrainFile.width(width);
stressStrainFile << stress.xx() << " " << stress.xy() << " " << stress.xz() << " " stressStrainFile << stress.xx() << " " << stress.xy() << " " << stress.xz() << " "
<< stress.yy() << " " << stress.yz() << " " << stress.zz() << stress.yy() << " " << stress.yz() << " " << stress.zz()
<< endl; << endl;
} }
} }

View file

@ -1,8 +1,8 @@
// aitken acceleration // aitken acceleration
if(iCorr == 0) if(iCorr == 0)
{ {
aitkenInitialRes = gMax(mag(DU.internalField())); aitkenInitialRes = gMax(mag(DU.internalField()));
} }
aitkenDelta.storePrevIter(); aitkenDelta.storePrevIter();
@ -11,26 +11,24 @@ aitkenDelta = (DU - DU.prevIter()) / aitkenInitialRes;
// update relaxation factor // update relaxation factor
if(iCorr == 0) if(iCorr == 0)
{ {
aitkenTheta = 0.1; aitkenTheta = 0.1;
} }
else else
{ {
vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField(); vectorField b = aitkenDelta.internalField() - aitkenDelta.prevIter().internalField();
//scalar sumMagB = gSum(mag(b)); //scalar sumMagB = gSum(mag(b));
scalar sumMagB = gSum(magSqr(b)); scalar sumMagB = gSum(magSqr(b));
if(sumMagB < SMALL) if(sumMagB < SMALL)
{ {
//Warning << "Aitken under-relaxation: denominator less then SMALL" //Warning << "Aitken under-relaxation: denominator less then SMALL"
// << endl; // << endl;
sumMagB += SMALL; sumMagB += SMALL;
} }
aitkenTheta = -aitkenTheta* aitkenTheta = -aitkenTheta*
gSum(aitkenDelta.prevIter().internalField() & b) gSum(aitkenDelta.prevIter().internalField() & b)/sumMagB;
/ }
sumMagB;
}
// correction to the latest DU // correction to the latest DU
DU += aitkenTheta*aitkenDelta*aitkenInitialRes; DU += aitkenTheta*aitkenDelta*aitkenInitialRes;

View file

@ -1,47 +1,43 @@
if(divDSigmaExpMethod == "standard") if(divDSigmaExpMethod == "standard")
{ {
divDSigmaExp = fvc::div divDSigmaExp = fvc::div
( (
mu*gradDU.T() + lambda*(I*tr(gradDU)) - (mu + lambda)*gradDU, mu*gradDU.T() + lambda*(I*tr(gradDU)) - (mu + lambda)*gradDU,
"div(sigma)" "div(sigma)"
);
}
else if(divDSigmaExpMethod == "surface")
{
divDSigmaExp = fvc::div
(
muf*(mesh.Sf() & fvc::interpolate(gradDU.T()))
+ lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU)))
- (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU))
); );
} }
else if(divDSigmaExpMethod == "decompose") else if(divDSigmaExpMethod == "surface")
{ {
surfaceTensorField shearGradDU = divDSigmaExp = fvc::div
((I - n*n)&fvc::interpolate(gradDU)); (
muf*(mesh.Sf() & fvc::interpolate(gradDU.T()))
+ lambdaf*(mesh.Sf() & I*fvc::interpolate(tr(gradDU)))
- (muf + lambdaf)*(mesh.Sf() & fvc::interpolate(gradDU))
);
}
else if(divDSigmaExpMethod == "decompose")
{
surfaceTensorField shearGradDU = ((I - n*n) & fvc::interpolate(gradDU));
divDSigmaExp = fvc::div divDSigmaExp = fvc::div
( (
mesh.magSf() mesh.magSf()*
*( (
- (muf + lambdaf)*(fvc::snGrad(DU)&(I - n*n)) - (muf + lambdaf)*(fvc::snGrad(DU) & (I - n*n))
+ lambdaf*tr(shearGradDU&(I - n*n))*n + lambdaf*tr(shearGradDU&(I - n*n))*n
+ muf*(shearGradDU&n) + muf*(shearGradDU&n)
) )
); );
} }
else if(divDSigmaExpMethod == "laplacian") else if(divDSigmaExpMethod == "laplacian")
{ {
divDSigmaExp = divDSigmaExp =
- fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)") - fvc::laplacian(mu + lambda, DU, "laplacian(DDU,DU)")
+ fvc::div + fvc::div(mu*gradDU.T() + lambda*(I*tr(gradDU)), "div(sigma)");
( }
mu*gradDU.T() else
+ lambda*(I*tr(gradDU)), {
"div(sigma)" FatalErrorIn(args.executable())
); << "divDSigmaExp method " << divDSigmaExpMethod << " not found!"
} << abort(FatalError);
else }
{
FatalError << "divDSigmaExp method " << divDSigmaExpMethod << " not found!" << endl;
}

View file

@ -3,8 +3,7 @@
//----------------------------------------------------// //----------------------------------------------------//
if(divDSigmaLargeStrainExpMethod == "standard") if(divDSigmaLargeStrainExpMethod == "standard")
{ {
divDSigmaLargeStrainExp = divDSigmaLargeStrainExp = fvc::div
fvc::div
( (
mu*(gradDU & gradDU.T()) mu*(gradDU & gradDU.T())
+ 0.5*lambda*(gradDU && gradDU)*I //- equivalent to 0.5*lambda*(I*tr(gradDU & gradDU.T())) + 0.5*lambda*(gradDU && gradDU)*I //- equivalent to 0.5*lambda*(I*tr(gradDU & gradDU.T()))
@ -14,8 +13,7 @@ if(divDSigmaLargeStrainExpMethod == "standard")
} }
else if(divDSigmaLargeStrainExpMethod == "surface") else if(divDSigmaLargeStrainExpMethod == "surface")
{ {
divDSigmaLargeStrainExp = divDSigmaLargeStrainExp = fvc::div
fvc::div
( (
muf * (mesh.Sf() & fvc::interpolate(gradDU & gradDU.T())) muf * (mesh.Sf() & fvc::interpolate(gradDU & gradDU.T()))
+ 0.5*lambdaf * (mesh.Sf() & (fvc::interpolate(gradDU && gradDU)*I)) + 0.5*lambdaf * (mesh.Sf() & (fvc::interpolate(gradDU && gradDU)*I))
@ -25,9 +23,9 @@ else if(divDSigmaLargeStrainExpMethod == "surface")
} }
else else
{ {
FatalError FatalError
<< "divDSigmaLargeStrainMethod not found!" << "divDSigmaLargeStrainMethod not found!"
<< exit(FatalError); << exit(FatalError);
} }
//- relax //- relax

View file

@ -1,26 +1,26 @@
if(divDSigmaNonLinExpMethod == "standard") if(divDSigmaNonLinExpMethod == "standard")
{ {
divDSigmaNonLinExp = fvc::div divDSigmaNonLinExp = fvc::div
( (
( mu * (gradDU & gradDU.T()) ) ( mu * (gradDU & gradDU.T()) )
+ ( 0.5 * lambda * tr(gradDU & gradDU.T()) * I ) + ( 0.5 * lambda * tr(gradDU & gradDU.T()) * I )
+ ( (sigma + DSigma) & gradDU ), + ( (sigma + DSigma) & gradDU ),
"div(sigma)" "div(sigma)"
); );
} }
else if(divDSigmaNonLinExpMethod == "surface") else if(divDSigmaNonLinExpMethod == "surface")
{ {
divDSigmaNonLinExp = divDSigmaNonLinExp = fvc::div
fvc::div( (
mesh.magSf() mesh.magSf()*
*( (
( muf * (n & fvc::interpolate( gradDU & gradDU.T() )) ) ( muf * (n & fvc::interpolate( gradDU & gradDU.T() )) )
+ ( 0.5*lambdaf * (n * tr(fvc::interpolate( gradDU & gradDU.T() ))) ) + ( 0.5*lambdaf * (n * tr(fvc::interpolate( gradDU & gradDU.T() ))) )
+ (n & fvc::interpolate( (sigma + DSigma) & gradDU )) + (n & fvc::interpolate( (sigma + DSigma) & gradDU ))
) )
); );
} }
else else
{ {
FatalError << "divDSigmaExp method " << divDSigmaExpMethod << " not found!" << endl; FatalError << "divDSigmaExp method " << divDSigmaExpMethod << " not found!" << endl;
} }

View file

@ -15,59 +15,57 @@
FieldField<Field, vector> extraVecs(ptc.size()); FieldField<Field, vector> extraVecs(ptc.size());
{ {
const labelListList& pfaces = mesh.pointFaces(); const labelListList& pfaces = mesh.pointFaces();
const volVectorField& centres = mesh.C(); const volVectorField& centres = mesh.C();
const fvBoundaryMesh& bm = mesh.boundary(); const fvBoundaryMesh& bm = mesh.boundary();
forAll (ptc, pointI) forAll (ptc, pointI)
{ {
const label curPoint = ptc[pointI]; const label curPoint = ptc[pointI];
const labelList& curFaces = pfaces[curPoint]; const labelList& curFaces = pfaces[curPoint];
// extraVecs.hook(new vectorField(curFaces.size())); //- no hook function // extraVecs.hook(new vectorField(curFaces.size())); //- no hook function
extraVecs.set extraVecs.set
(
pointI,
new vectorField(curFaces.size())
);
vectorField& curExtraVectors = extraVecs[pointI];
label nFacesAroundPoint = 0;
const vector& pointLoc = mesh.points()[curPoint];
// Go through all the faces
forAll (curFaces, faceI)
{
if (!mesh.isInternalFace(curFaces[faceI]))
{
// This is a boundary face. If not in the empty patch
// or coupled calculate the extrapolation vector
label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
if
( (
!isA<emptyFvPatch>(bm[patchID]) pointI,
&& !bm[patchID].coupled() new vectorField(curFaces.size())
) );
vectorField& curExtraVectors = extraVecs[pointI];
label nFacesAroundPoint = 0;
const vector& pointLoc = mesh.points()[curPoint];
// Go through all the faces
forAll (curFaces, faceI)
{ {
// Found a face for extrapolation if (!mesh.isInternalFace(curFaces[faceI]))
curExtraVectors[nFacesAroundPoint] = {
pointLoc // This is a boundary face. If not in the empty patch
- centres.boundaryField()[patchID] // or coupled calculate the extrapolation vector
[bm[patchID].patch().whichFace(curFaces[faceI])]; label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
nFacesAroundPoint++; if
(
!isA<emptyFvPatch>(bm[patchID]) && !bm[patchID].coupled()
)
{
// Found a face for extrapolation
curExtraVectors[nFacesAroundPoint] =
pointLoc
- centres.boundaryField()[patchID]
[bm[patchID].patch().whichFace(curFaces[faceI])];
nFacesAroundPoint++;
}
}
} }
}
}
curExtraVectors.setSize(nFacesAroundPoint); curExtraVectors.setSize(nFacesAroundPoint);
} }
} }

View file

@ -8,114 +8,114 @@
FieldField<Field, scalar> w(ptc.size()); FieldField<Field, scalar> w(ptc.size());
{ {
const labelListList& pf = mesh.pointFaces(); const labelListList& pf = mesh.pointFaces();
const volVectorField& centres = mesh.C(); const volVectorField& centres = mesh.C();
const fvBoundaryMesh& bm = mesh.boundary(); const fvBoundaryMesh& bm = mesh.boundary();
pointScalarField volPointSumWeights pointScalarField volPointSumWeights
( (
IOobject IOobject
(
"volPointSumWeights",
mesh.polyMesh::instance(),
mesh
),
pMesh,
dimensionedScalar("zero", dimless, 0)
);
forAll (ptc, pointI)
{
const label curPoint = ptc[pointI];
const labelList& curFaces = pf[curPoint];
//w.hook(new scalarField(curFaces.size())); //philipc no hook function
w.set
(
pointI,
new scalarField(curFaces.size())
);
scalarField& curWeights = w[pointI];
label nFacesAroundPoint = 0;
const vector& pointLoc = mesh.points()[curPoint];
// Go through all the faces
forAll (curFaces, faceI)
{
if (!mesh.isInternalFace(curFaces[faceI]))
{
// This is a boundary face. If not in the empty patch
// or coupled calculate the extrapolation vector
label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
if
( (
!isA<emptyFvPatch>(bm[patchID]) "volPointSumWeights",
&& !( mesh.polyMesh::instance(),
bm[patchID].coupled() mesh
//&& Pstream::parRun() ),
//&& !mesh.parallelData().cyclicParallel() pMesh,
) dimensionedScalar("zero", dimless, 0)
)
{
curWeights[nFacesAroundPoint] =
1.0/mag
(
pointLoc
- centres.boundaryField()[patchID]
[
bm[patchID].patch().whichFace(curFaces[faceI])
]
);
nFacesAroundPoint++;
}
}
}
// Reset the sizes of the local weights
curWeights.setSize(nFacesAroundPoint);
// Collect the sum of weights for parallel correction
volPointSumWeights[curPoint] += sum(curWeights);
}
// Do parallel correction of weights
// Update coupled boundaries
// Work-around for cyclic parallels.
/*if (Pstream::parRun() && !mesh.parallelData().cyclicParallel())
{
forAll (volPointSumWeights.boundaryField(), patchI)
{
if (volPointSumWeights.boundaryField()[patchI].coupled())
{
volPointSumWeights.boundaryField()[patchI].initAddField();
}
}
forAll (volPointSumWeights.boundaryField(), patchI)
{
if (volPointSumWeights.boundaryField()[patchI].coupled())
{
volPointSumWeights.boundaryField()[patchI].addField
(
volPointSumWeights.internalField()
); );
forAll (ptc, pointI)
{
const label curPoint = ptc[pointI];
const labelList& curFaces = pf[curPoint];
//w.hook(new scalarField(curFaces.size())); //philipc no hook function
w.set
(
pointI,
new scalarField(curFaces.size())
);
scalarField& curWeights = w[pointI];
label nFacesAroundPoint = 0;
const vector& pointLoc = mesh.points()[curPoint];
// Go through all the faces
forAll (curFaces, faceI)
{
if (!mesh.isInternalFace(curFaces[faceI]))
{
// This is a boundary face. If not in the empty patch
// or coupled calculate the extrapolation vector
label patchID =
mesh.boundaryMesh().whichPatch(curFaces[faceI]);
if
(
!isA<emptyFvPatch>(bm[patchID])
&& !(
bm[patchID].coupled()
//&& Pstream::parRun()
//&& !mesh.parallelData().cyclicParallel()
)
)
{
curWeights[nFacesAroundPoint] =
1.0/mag
(
pointLoc
- centres.boundaryField()[patchID]
[
bm[patchID].patch().whichFace(curFaces[faceI])
]
);
nFacesAroundPoint++;
}
}
}
// Reset the sizes of the local weights
curWeights.setSize(nFacesAroundPoint);
// Collect the sum of weights for parallel correction
volPointSumWeights[curPoint] += sum(curWeights);
} }
}
// Do parallel correction of weights
// Update coupled boundaries
// Work-around for cyclic parallels.
/*if (Pstream::parRun() && !mesh.parallelData().cyclicParallel())
{
forAll (volPointSumWeights.boundaryField(), patchI)
{
if (volPointSumWeights.boundaryField()[patchI].coupled())
{
volPointSumWeights.boundaryField()[patchI].initAddField();
}
}
forAll (volPointSumWeights.boundaryField(), patchI)
{
if (volPointSumWeights.boundaryField()[patchI].coupled())
{
volPointSumWeights.boundaryField()[patchI].addField
(
volPointSumWeights.internalField()
);
}
}
}*/ }*/
// Re-scale the weights for the current point // Re-scale the weights for the current point
forAll (ptc, pointI) forAll (ptc, pointI)
{ {
w[pointI] /= volPointSumWeights[ptc[pointI]]; w[pointI] /= volPointSumWeights[ptc[pointI]];
} }
} }

View file

@ -107,36 +107,35 @@
//- explicit terms in the momentum equation //- explicit terms in the momentum equation
volVectorField divDSigmaExp volVectorField divDSigmaExp
( (
IOobject
(
"divDSigmaExp",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh,
dimensionedVector("zero", dimensionSet(1, -2, -2, 0, 0, 0, 0), vector::zero)
);
volVectorField divDSigmaNonLinExp
(
IOobject IOobject
( (
"divDSigmaNonLinExp", "divDSigmaExp",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh,
dimensionedVector("zero", dimensionSet(1, -2, -2, 0, 0, 0, 0), vector::zero)
);
volVectorField divDSigmaNonLinExp
(
IOobject
(
"divDSigmaNonLinExp",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh, mesh,
dimensionedVector("zero", dimensionSet(1,-2,-2,0,0,0,0), vector::zero) dimensionedVector("zero", dimensionSet(1,-2,-2,0,0,0,0), vector::zero)
); );
constitutiveModel rheology(sigma, DU); constitutiveModel rheology(sigma, DU);
volScalarField rho = rheology.rho(); volScalarField rho = rheology.rho();
volScalarField mu = rheology.mu(); volScalarField mu = rheology.mu();
volScalarField lambda = rheology.lambda(); volScalarField lambda = rheology.lambda();
surfaceScalarField muf = fvc::interpolate(rheology.mu()); surfaceScalarField muf = fvc::interpolate(rheology.mu());
@ -144,37 +143,38 @@
surfaceVectorField n = mesh.Sf()/mesh.magSf(); surfaceVectorField n = mesh.Sf()/mesh.magSf();
// plastic strain increment // plastic strain increment
const volSymmTensorField& DEpsilonP = rheology.DEpsilonP(); const volSymmTensorField& DEpsilonP = rheology.DEpsilonP();
// for aitken relaxation // for aitken relaxation
volVectorField aitkenDelta volVectorField aitkenDelta
( (
IOobject IOobject
( (
"aitkenDelta", "aitkenDelta",
runTime.timeName(), runTime.timeName(),
mesh, mesh,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE IOobject::NO_WRITE
), ),
mesh, mesh,
dimensionedVector("zero", dimLength, vector::zero) dimensionedVector("zero", dimLength, vector::zero)
); );
// aitken relaxation factor
scalar aitkenInitialRes = 1.0; // aitken relaxation factor
scalar aitkenTheta = 0.1; scalar aitkenInitialRes = 1.0;
scalar aitkenTheta = 0.1;
// volVectorField resid // volVectorField resid
// ( // (
// IOobject // IOobject
// ( // (
// "resid", // "resid",
// runTime.timeName(), // runTime.timeName(),
// mesh, // mesh,
// IOobject::NO_READ, // IOobject::NO_READ,
// IOobject::AUTO_WRITE // IOobject::AUTO_WRITE
// ), // ),
// mesh, // mesh,
// dimensionedVector("zero", dimless, vector::zero) // dimensionedVector("zero", dimless, vector::zero)
// ); // );

View file

@ -1,36 +1,36 @@
OFstream * forceFilePtr(NULL); OFstream* forceFilePtr(NULL);
OFstream * stressFilePtr(NULL); OFstream* stressFilePtr(NULL);
word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch")); word historyPatchName(mesh.solutionDict().subDict("solidMechanics").lookup("historyPatch"));
label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName); label historyPatchID = mesh.boundaryMesh().findPatchID(historyPatchName);
if(historyPatchID == -1) if(historyPatchID == -1)
{ {
Warning << "history patch " << historyPatchName Warning << "history patch " << historyPatchName
<< " not found. Force-displacement will not be written" << " not found. Force-displacement will not be written"
<< endl; << endl;
} }
else if(Pstream::master()) else if(Pstream::master())
{ {
fileName historyDir = "history"; fileName historyDir = "history";
mkDir(historyDir); mkDir(historyDir);
{ {
fileName forceFileName(historyDir/"forceDisp_"+historyPatchName+".dat"); fileName forceFileName(historyDir/"forceDisp_"+historyPatchName+".dat");
Info << "\nForce-displacement for patch " << historyPatchName Info << "\nForce-displacement for patch " << historyPatchName
<< " will be written to " << forceFileName << " will be written to " << forceFileName
<< endl; << endl;
forceFilePtr = new OFstream(forceFileName); forceFilePtr = new OFstream(forceFileName);
OFstream& forceDispFile = *forceFilePtr; OFstream& forceDispFile = *forceFilePtr;
forceDispFile << "#Disp(mm)\tForce(N)" << endl; forceDispFile << "#Disp(mm)\tForce(N)" << endl;
} }
{ {
fileName stressFileName(historyDir/"stressStrain_"+historyPatchName+".dat"); fileName stressFileName(historyDir/"stressStrain_"+historyPatchName+".dat");
Info << "\nCauchy Stress vs. Almansi Strain for patch " Info << "\nCauchy Stress vs. Almansi Strain for patch "
<< historyPatchName << historyPatchName
<< " will be written to " << stressFileName << " will be written to " << stressFileName
<< endl; << endl;
stressFilePtr = new OFstream(stressFileName); stressFilePtr = new OFstream(stressFileName);
OFstream& stressStrainFile = *stressFilePtr; OFstream& stressStrainFile = *stressFilePtr;
stressStrainFile << "#Strain(-)\tStress(Pa)" << endl; stressStrainFile << "#Strain(-)\tStress(Pa)" << endl;
} }
} }

View file

@ -4,26 +4,26 @@ solidInterface* solidInterfacePtr(NULL);
{ {
const dictionary& stressControl = const dictionary& stressControl =
mesh.solutionDict().subDict("solidMechanics"); mesh.solutionDict().subDict("solidMechanics");
solidInterfaceCorr = Switch(stressControl.lookup("solidInterface")); solidInterfaceCorr = Switch(stressControl.lookup("solidInterface"));
if(solidInterfaceCorr) if(solidInterfaceCorr)
{ {
Info << "Creating solid interface correction" << endl; Info << "Creating solid interface correction" << endl;
solidInterfacePtr = new solidInterface(mesh, rheology); solidInterfacePtr = new solidInterface(mesh, rheology);
solidInterfacePtr->modifyProperties(muf, lambdaf); solidInterfacePtr->modifyProperties(muf, lambdaf);
//- solidInterface needs muf and lambdaf to be used for divDSigmaExp //- solidInterface needs muf and lambdaf to be used for divDSigmaExp
if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose") if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose")
{ {
FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on" FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on"
<< exit(FatalError); << exit(FatalError);
} }
if(divDSigmaLargeStrainExpMethod == "surface") if(divDSigmaLargeStrainExpMethod == "surface")
{ {
FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on" FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on"
<< exit(FatalError); << exit(FatalError);
} }
} }
} }

View file

@ -4,26 +4,26 @@ solidInterfaceNonLin* solidInterfacePtr(NULL);
{ {
const dictionary& stressControl = const dictionary& stressControl =
mesh.solutionDict().subDict("solidMechanics"); mesh.solutionDict().subDict("solidMechanics");
solidInterfaceCorr = Switch(stressControl.lookup("solidInterface")); solidInterfaceCorr = Switch(stressControl.lookup("solidInterface"));
if(solidInterfaceCorr) if(solidInterfaceCorr)
{ {
Info << "Creating solid interface nonlinear correction" << endl; Info << "Creating solid interface nonlinear correction" << endl;
solidInterfacePtr = new solidInterfaceNonLin(mesh, rheology); solidInterfacePtr = new solidInterfaceNonLin(mesh, rheology);
solidInterfacePtr->modifyProperties(muf, lambdaf); solidInterfacePtr->modifyProperties(muf, lambdaf);
//- solidInterface needs muf and lambdaf to be used for divDSigmaExp //- solidInterface needs muf and lambdaf to be used for divDSigmaExp
if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose") if(divDSigmaExpMethod != "surface" && divDSigmaExpMethod != "decompose")
{ {
FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on" FatalError << "divDSigmaExp must be decompose or surface when solidInterface is on"
<< exit(FatalError); << exit(FatalError);
} }
if(divDSigmaLargeStrainExpMethod != "surface") if(divDSigmaLargeStrainExpMethod != "surface")
{ {
FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on" FatalError << "divDSigmaLargeStrainExp must be surface when solidInterface is on"
<< exit(FatalError); << exit(FatalError);
} }
} }
} }

View file

@ -69,139 +69,141 @@ int main(int argc, char *argv[])
# include "readMoveMeshMethod.H" # include "readMoveMeshMethod.H"
# include "findGlobalFaceZones.H" # include "findGlobalFaceZones.H"
//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info << "\nStarting time loop\n" << endl; Info<< "\nStarting time loop\n" << endl;
for (runTime++; !runTime.end(); runTime++) while(runTime.loop())
{ {
Info<< "Time = " << runTime.timeName() << nl << endl; Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSolidMechanicsControls.H" # include "readSolidMechanicsControls.H"
int iCorr = 0; int iCorr = 0;
lduMatrix::solverPerformance solverPerf; lduMatrix::solverPerformance solverPerf;
scalar initialResidual = 0; scalar initialResidual = 0;
scalar relativeResidual = 1.0; scalar relativeResidual = 1.0;
lduMatrix::debug = 0; lduMatrix::debug = 0;
do do
{ {
DU.storePrevIter(); DU.storePrevIter();
# include "calculateDivDSigmaExp.H" # include "calculateDivDSigmaExp.H"
# include "calculateDivDSigmaNonLinExp.H" # include "calculateDivDSigmaNonLinExp.H"
// Updated lagrangian large strain momentum equation // Updated lagrangian large strain momentum equation
fvVectorMatrix DUEqn fvVectorMatrix DUEqn
( (
fvm::d2dt2(rho,DU) fvm::d2dt2(rho,DU)
== ==
fvm::laplacian(2*muf + lambdaf, DU, "laplacian(DDU,DU)") fvm::laplacian(2*muf + lambdaf, DU, "laplacian(DDU,DU)")
+ divDSigmaExp + divDSigmaExp
+ divDSigmaNonLinExp + divDSigmaNonLinExp
//- fvc::div(2*mu*DEpsilonP, "div(sigma)") //- fvc::div(2*mu*DEpsilonP, "div(sigma)")
- fvc::div(2*muf*( mesh.Sf() & fvc::interpolate(DEpsilonP)) ) - fvc::div(2*muf*( mesh.Sf() & fvc::interpolate(DEpsilonP)) )
); );
if(nonLinearSemiImplicit) if(nonLinearSemiImplicit)
{ {
// experimental // experimental
// we can treat the nonlinear term (gradDU & gradDU.T()) in a // we can treat the nonlinear term (gradDU & gradDU.T()) in a
// semi-implicit over-relaxed manner // semi-implicit over-relaxed manner
// this should improve convergence when gradDU is large // this should improve convergence when gradDU is large
// but maybe not execution time // but maybe not execution time
DUEqn -= DUEqn -=
fvm::laplacian fvm::laplacian
( (
(2*mu + lambda)*gradDU, DU, "laplacian(DDU,DU)" (2*mu + lambda)*gradDU, DU, "laplacian(DDU,DU)"
) )
- fvc::div( (2*mu + lambda)*(gradDU&gradDU), "div(sigma)"); - fvc::div( (2*mu + lambda)*(gradDU&gradDU), "div(sigma)");
} }
solverPerf = DUEqn.solve(); solverPerf = DUEqn.solve();
if(iCorr == 0) if(iCorr == 0)
{ {
initialResidual = solverPerf.initialResidual(); initialResidual = solverPerf.initialResidual();
} }
if(aitkenRelax) if(aitkenRelax)
{ {
# include "aitkenRelaxation.H" # include "aitkenRelaxation.H"
} }
else else
{ {
DU.relax(); DU.relax();
} }
gradDU = fvc::grad(DU); gradDU = fvc::grad(DU);
// correct plasticty term // correct plasticty term
rheology.correct(); rheology.correct();
// correct elastic properties // correct elastic properties
// for nonlinear elastic materials // for nonlinear elastic materials
//mu = rheology.newMu(); //mu = rheology.newMu();
//lambda = rheology.newLambda(); //lambda = rheology.newLambda();
//muf = fvc::interpolate(mu); //muf = fvc::interpolate(mu);
//lambdaf = fvc::interpolate(lambda); //lambdaf = fvc::interpolate(lambda);
# include "calculateDEpsilonDSigma.H" # include "calculateDEpsilonDSigma.H"
# include "calculateRelativeResidual.H" # include "calculateRelativeResidual.H"
if(iCorr % infoFrequency == 0) if(iCorr % infoFrequency == 0)
{ {
Info<< "\tTime " << runTime.value() Info<< "\tTime " << runTime.value()
<< ", Corrector " << iCorr << ", Corrector " << iCorr
<< ", Solving for " << DU.name() << ", Solving for " << DU.name()
<< " using " << solverPerf.solverName() << " using " << solverPerf.solverName()
<< ", res = " << solverPerf.initialResidual() << ", res = " << solverPerf.initialResidual()
<< ", rel res = " << relativeResidual; << ", rel res = " << relativeResidual;
if(aitkenRelax) if(aitkenRelax)
{ {
Info<< ", aitken = " << aitkenTheta; Info<< ", aitken = " << aitkenTheta;
} }
Info<< ", iters = " << solverPerf.nIterations() << endl; Info<< ", iters = " << solverPerf.nIterations() << endl;
} }
} }
while while
( (
iCorr++ < 2 iCorr++ < 2
|| ||
(//solverPerf.initialResidual() > convergenceTolerance (
relativeResidual > convergenceTolerance //solverPerf.initialResidual() > convergenceTolerance
&& relativeResidual > convergenceTolerance
iCorr < nCorr) && iCorr < nCorr
); )
);
Info<< nl << "Time " << runTime.value() << ", Solving for " << DU.name() Info<< nl << "Time " << runTime.value() << ", Solving for " << DU.name()
<< ", Initial residual = " << initialResidual << ", Initial residual = " << initialResidual
<< ", Final residual = " << solverPerf.initialResidual() << ", Final residual = " << solverPerf.initialResidual()
<< ", Final rel residual = " << relativeResidual << ", Final rel residual = " << relativeResidual
<< ", No outer iterations " << iCorr << endl; << ", No outer iterations " << iCorr << endl;
rheology.updateYieldStress(); rheology.updateYieldStress();
U += DU; U += DU;
epsilon += DEpsilon; epsilon += DEpsilon;
epsilonP += DEpsilonP; epsilonP += DEpsilonP;
sigma += DSigma; sigma += DSigma;
# include "moveMesh.H" # include "moveMesh.H"
# include "rotateFields.H" # include "rotateFields.H"
# include "writeFields.H" # include "writeFields.H"
# include "writeHistory.H" # include "writeHistory.H"
Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s"
<< endl; << endl;
} }
Info<< "End\n" << endl; Info<< "End\n" << endl;
return(0); return(0);
} }
// ************************************************************************* // // ************************************************************************* //

View file

@ -8,26 +8,26 @@ const fvBoundaryMesh& bm = mesh.boundary();
forAll (bm, patchI) forAll (bm, patchI)
{ {
// If the patch is empty, skip it // If the patch is empty, skip it
// If the patch is coupled, and there are no cyclic parallels, skip it // If the patch is coupled, and there are no cyclic parallels, skip it
if if
( (
!isA<emptyFvPatch>(bm[patchI]) !isA<emptyFvPatch>(bm[patchI])
&& !( && !(
bm[patchI].coupled() bm[patchI].coupled()
//&& Pstream::parRun() //&& Pstream::parRun()
//&& !mesh.parallelData().cyclicParallel() //&& !mesh.parallelData().cyclicParallel()
) )
) )
{ {
const labelList& bp = bm[patchI].patch().boundaryPoints(); const labelList& bp = bm[patchI].patch().boundaryPoints();
const labelList& meshPoints = bm[patchI].patch().meshPoints(); const labelList& meshPoints = bm[patchI].patch().meshPoints();
forAll (bp, pointI) forAll (bp, pointI)
{ {
pointsCorrectionMap.insert(meshPoints[bp[pointI]]); pointsCorrectionMap.insert(meshPoints[bp[pointI]]);
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show more