Solid models update - boundary traction

This commit is contained in:
Hrvoje Jasak 2014-02-23 10:53:50 +00:00
parent 47c824e967
commit 3810b29f37
20 changed files with 1491 additions and 1249 deletions

View file

@ -116,10 +116,10 @@ solidCohesiveFvPatchVectorField::solidCohesiveFvPatchVectorField
nonLinear_(nonLinearGeometry::OFF),
orthotropic_(false)
{
Info << "Creating solidCohesive patch" << nl
Info<< "Creating solidCohesive patch" << nl
<< "\tOnly Dugdale law currently available!" << endl;
//- check if traction boundary is for non linear solver
// Check if traction boundary is for non linear solver
if (dict.found("nonLinear"))
{
nonLinear_ = nonLinearGeometry::nonLinearNames_.read
@ -415,12 +415,13 @@ tmp<scalarField> solidCohesiveFvPatchVectorField::crackingAndDamage() const
(
new scalarField(size(), 1.0)
);
scalarField& cad = tcrackingAndDamage();
forAll(tcrackingAndDamage(), facei)
forAll(cad, facei)
{
if (cracked_[facei])
{
tcrackingAndDamage()[facei] = 2.0;
cad[facei] = 2.0;
}
}
@ -434,10 +435,11 @@ tmp<scalarField> solidCohesiveFvPatchVectorField::GI() const
(
new scalarField(size(), 0.0)
);
scalarField& GI = tGI();
forAll(tGI(), facei)
forAll(GI, facei)
{
tGI()[facei] = currentGI_[facei];
GI[facei] = currentGI_[facei];
}
return tGI;
@ -450,15 +452,17 @@ tmp<scalarField> solidCohesiveFvPatchVectorField::GII() const
(
new scalarField(size(), 0.0)
);
scalarField& GII = tGII();
forAll(tGII(), facei)
forAll(GII, facei)
{
tGII()[facei] = currentGII_[facei];
GII[facei] = currentGII_[facei];
}
return tGII;
}
bool solidCohesiveFvPatchVectorField::cracking()
{
const fvMesh& mesh = patch().boundaryMesh().mesh();
@ -470,6 +474,7 @@ bool solidCohesiveFvPatchVectorField::cracking()
label sumDamaged = 0;
label sumCracked = 0;
forAll(globalCracked, facei)
{
if (globalCracked[facei] > 0.0)
@ -481,8 +486,8 @@ bool solidCohesiveFvPatchVectorField::cracking()
sumDamaged++;
}
}
Info << "\t\tThere are " << sumDamaged << " damaged faces" << endl;
Info << "\t\tThere are " << sumCracked << " cracked faces" << endl;
Info<< "\t\tThere are " << sumDamaged << " damaged faces" << nl
<< "\t\tThere are " << sumCracked << " cracked faces" << endl;
return false;
}
@ -534,10 +539,11 @@ void solidCohesiveFvPatchVectorField::autoMap
// the traction_ field after mapping and call updateCoeffs.
// For here, we will just set traction to zero.
if ( (patch().size()==1) && (nNewFaces == 1) )
if ( (patch().size() == 1) && (nNewFaces == 1) )
{
label i=0;
this->valueFraction()[i] = symmTensor::zero;
traction_[i] = vector::zero;
cracked_[i] = false;
curTractionN_[i] = 0.0;
@ -556,12 +562,13 @@ void solidCohesiveFvPatchVectorField::autoMap
currentGII_[i] = 0.0;
oldGII_[i] = 0.0;
}
else if ( (patch().size()==2) && (nNewFaces == 1) )
else if ( (patch().size() == 2) && (nNewFaces == 1) )
{
label i=1;
this->valueFraction()[i] = symmTensor::zero;
traction_[i] = vector::zero;
cracked_[i] = false;
curTractionN_[i] = 0.0;
oldTractionN_[i] = 0.0;
curTractionS_[i] = 0.0;
@ -586,6 +593,7 @@ void solidCohesiveFvPatchVectorField::autoMap
i=1;
this->valueFraction()[i] = symmTensor::zero;
traction_[i] = vector::zero;
cracked_[i] = false;
curTractionN_[i] = 0.0;
oldTractionN_[i] = 0.0;
@ -611,6 +619,7 @@ void solidCohesiveFvPatchVectorField::autoMap
{
this->valueFraction()[i] = symmTensor::zero;
traction_[i] = vector::zero;
cracked_[i] = false;
curTractionN_[i] = 0.0;
oldTractionN_[i] = 0.0;
@ -682,6 +691,7 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
(
"rheologyProperties"
);
label patchID = patch().index();
const scalarField sigmaMax =
rheology.cohLaw().sigmaMax()().boundaryField()[patchID];
@ -717,7 +727,10 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
max
(
unloadingDeltaEff_,
Foam::sqrt(max(deltaN_, 0.0)*max(deltaN_, 0.0) + deltaS_*deltaS_)
Foam::sqrt
(
max(deltaN_, 0.0)*max(deltaN_, 0.0) + deltaS_*deltaS_
)
);
curTimeIndex_ = this->db().time().timeIndex();
@ -760,20 +773,20 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
const regionSplit& regions = crackerMesh.regions();
labelField faceCellRegion(size(), -1);
forAll(faceCellRegion, faceI)
{
faceCellRegion[faceI] = regions[faceCells[faceI]];
}
labelField globalFaceCellRegion =
crackerMesh.globalCrackField(faceCellRegion);
// Patch displacement
vectorField UPatch = *this;
if (fieldName_ == "DU")
{
UPatch +=
patch().lookupPatchField<volVectorField, vector>("U");
UPatch += patch().lookupPatchField<volVectorField, vector>("U");
}
// Global displacement
@ -818,6 +831,7 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
deltaN_[i] =
relaxationFactor_*curDeltaN_[i]
+ (1.0 - relaxationFactor_)*deltaN_[i];
deltaS_[i] =
relaxationFactor_*curDeltaS_[i]
+ (1.0 - relaxationFactor_)*deltaS_[i];
@ -829,7 +843,7 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
// effective delta - only positive deltaN is considered
const scalar deltaEff =
::sqrt(max(deltaN_[i], 0.0)*max(deltaN_[i], 0.0)
Foam::sqrt(max(deltaN_[i], 0.0)*max(deltaN_[i], 0.0)
+ deltaS_[i]*deltaS_[i]);
// update energies
@ -844,19 +858,19 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
// trapezoidal rule
currentGI_[i] =
oldGI_[i]
+ ((0.5*(curTractionN_[i]+oldTractionN_[i]))
*(deltaN_[i]-oldDeltaN_[i]));
+ ((0.5*(curTractionN_[i]+oldTractionN_[i]))*
(deltaN_[i]-oldDeltaN_[i]));
}
else
{
// no modeI energy lost if in compression
currentGI_[i] = oldGI_[i];
}
// mode II - trapezoidal rule
currentGII_[i] =
oldGII_[i]
+ ((0.5*(curTractionS_[i]+oldTractionS_[i]))
*(deltaS_[i]-oldDeltaS_[i]));
currentGII_[i] = oldGII_[i]
+ ((0.5*(curTractionS_[i]+oldTractionS_[i]))*
(deltaS_[i]-oldDeltaS_[i]));
}
//scalar currentG = currentGI_[i] + currentGII_[i];
@ -885,7 +899,10 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
if ( ((currentGI_[i]/GIc[i]) + (currentGII_[i]/GIIc[i])) >= 1 )
{
//Pout << "GIc[i] is " << GIc[i] << ", curG is " << currentG << endl;
if (!cracked_[i]) Pout << "Face " << i << " is fully cracked" << endl;
if (!cracked_[i])
{
Pout << "Face " << i << " is fully cracked" << endl;
}
cracked_[i] = true;
@ -923,16 +940,20 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
curNormalTraction =
relaxationFactor_*curNormalTraction
+ (1-relaxationFactor_)*(n[i] & traction_[i]);
curTangentialTraction =
relaxationFactor_*curTangentialTraction
+ (1-relaxationFactor_)*( (I -sqr(n[i])) & traction_[i]);
traction_[i] = curNormalTraction*n[i] + curTangentialTraction;
}
// damging face with positive normal delta
else if ( deltaN_[i] > 0.0 )
{
if (cracked_[i]) Pout << "Face " << i << " is un-cracked" << endl;
if (cracked_[i])
{
Pout << "Face " << i << " is un-cracked" << endl;
}
cracked_[i] = false;
@ -977,16 +998,20 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
curNormalTraction =
relaxationFactor_*tN
+ (1-relaxationFactor_)*(n[i] & traction_[i]);
curTangentialTraction =
relaxationFactor_*(tS*sDir)
+ (1-relaxationFactor_)*( (I -sqr(n[i])) & traction_[i]);
traction_[i] = curNormalTraction*n[i] + curTangentialTraction;
}
// damaging faces with negative normal delta
else
{
if (cracked_[i]) Pout << "Face " << i << " is un-cracked" << endl;
if (cracked_[i])
{
Pout << "Face " << i << " is un-cracked" << endl;
}
cracked_[i] = false;
//Pout << "Contact and shearing face " << i << endl;
@ -1011,13 +1036,14 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
curNormalTraction =
relaxationFactor_*contactTN
+ (1-relaxationFactor_)*(n[i] & traction_[i]);
curTangentialTraction =
relaxationFactor_*(tS*sDir)
+ (1-relaxationFactor_)*( (I -sqr(n[i])) & traction_[i]);
traction_[i] = curNormalTraction*n[i] + curTangentialTraction;
}
}
else
{
// unloading
@ -1047,34 +1073,40 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
scalar scaleFactor = deltaEff/(unloadingDeltaEff_[i]);
traction_[i] =
relaxationFactor_*scaleFactor*traction_[i]
+ (1-relaxationFactor_)*traction_[i];
+ (1 - relaxationFactor_)*traction_[i];
}
}
bool incremental(fieldName_ == "DU");
this->refGrad() =
tractionBoundaryGradient()
this->refGrad() = tractionBoundaryGradient::snGrad
(
traction_,
scalarField(traction_.size(), 0.0),
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
nonLinear_,
incremental
);
directionMixedFvPatchVectorField::updateCoeffs();
}
void solidCohesiveFvPatchVectorField::calcPenaltyFactor()
{
void solidCohesiveFvPatchVectorField::calcPenaltyFactor()
{
// calculate penalty factor similar to standardPenalty contact model
// approx penaltyFactor from mechanical properties
// this can then be scaled using the penaltyScale
// to-do: write equivalent for orthotropic
if (orthotropic_)
{
FatalError << "solidCohesiveFvPatchVectorField::calcPenaltyFactor()"
FatalErrorIn
(
"void solidCohesiveFvPatchVectorField::calcPenaltyFactor()"
) << "solidCohesiveFvPatchVectorField::calcPenaltyFactor()"
<< " has yet to be written for orthotropic"
<< exit(FatalError);
}
@ -1085,6 +1117,7 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
const scalarField& mu =
mesh.objectRegistry::lookupObject<volScalarField>
("mu").boundaryField()[patchID];
const scalarField& lambda =
mesh.objectRegistry::lookupObject<volScalarField>
("lambda").boundaryField()[patchID];
@ -1097,9 +1130,12 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
// average contact patch cell volume
scalar cellVolume = 0.0;
const volScalarField::DimensionedInternalField & V = mesh.V();
{
const unallocLabelList& faceCells = mesh.boundary()[patchID].faceCells();
const unallocLabelList& faceCells =
mesh.boundary()[patchID].faceCells();
forAll(mesh.boundary()[patchID], facei)
{
cellVolume += V[faceCells[facei]];
@ -1111,7 +1147,7 @@ void solidCohesiveFvPatchVectorField::updateCoeffs()
// we approximate penalty factor for traction instead of force
penaltyFactorPtr_ =
new scalar(penaltyScale_*bulkModulus*faceArea/cellVolume);
}
}
// Write

View file

@ -81,8 +81,8 @@ class constitutiveModel
//- Plane stress
Switch planeStress_;
//- Run-time selectable solidInterface method for correct discretisation
// on bi-material interfaces
//- Run-time selectable solidInterface method for correct
// discretisation on bi-material interfaces
autoPtr<solidInterface> solidInterfacePtr_;
// we use IOReferencer to allow lookup of solidInterface object in
@ -141,6 +141,7 @@ public:
{
return plasticityStressReturnPtr_->plasticityActive();
}
return false;
}

View file

@ -36,51 +36,55 @@ Author
#include "constitutiveModel.H"
#include "thermalModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineTypeNameAndDebug(tractionBoundaryGradient, 0);
// * * * * * * * * * * * * * * Member functions * * * * * * * * * * * * * * //
tmp<vectorField> tractionBoundaryGradient::traction
Foam::tmp<Foam::vectorField> Foam::tractionBoundaryGradient::traction
(
const tensorField& gradField,
const word fieldName,
const word& workingFieldName,
const word& integralFieldName,
const fvPatch& patch,
Switch orthotropic,
word nonLinear
) const
const bool orthotropic,
const nonLinearGeometry::nonLinearType& nonLinear,
const bool incremental
)
{
// create tmp
// Create result
tmp<vectorField> ttraction
(
new vectorField(gradField.size(), vector::zero)
);
vectorField& traction = ttraction();
// Orthotropic material
if (orthotropic)
{
// for now, turn off orthotropic
FatalError
<< "tractionBoundaryGradient::traction is not written for"
<< " orthotropic yet" << nl
// For now, turn off orthotropic
FatalErrorIn
(
"tmp<vectorField> tractionBoundaryGradient::traction\n"
"(\n"
" const tensorField& gradField,\n"
" const word& workingFieldName,\n"
" const word& integralFieldName,\n"
" const fvPatch& patch,\n"
" const bool orthotropic,\n"
" const nonLinearGeometry::nonLinearType& nonLinear\n"
") const"
) << "tractionBoundaryGradient::traction is not written for"
<< " orthotropic materials yet" << nl
<< "you are probably trying to use solidContact boundaries "
<< "with orthotropic solver" << nl
<< "it should be straight-forward but I have not done it yet!"
<< "with the orthotropic solver" << nl
<< exit(FatalError);
}
else
{
// lookup material properties from the solver
const fvPatchField<scalar>& mu =
// Lookup material properties from the solver
const fvPatchScalarField& mu =
patch.lookupPatchField<volScalarField, scalar>("mu");
const fvPatchField<scalar>& lambda =
const fvPatchScalarField& lambda =
patch.lookupPatchField<volScalarField, scalar>("lambda");
// only for nonlinear elastic properties
@ -93,212 +97,297 @@ tmp<vectorField> tractionBoundaryGradient::traction
// lambda = plasticity.newLambda().boundaryField()[patch.index()];
// }
// required fields
// Get patch normal
vectorField n = patch.nf();
// Calculate traction
traction = 2*mu*(n & symm(gradField)) + lambda*tr(gradField)*n;
// calculate traction
traction = 2*mu*(n&symm(gradField)) + lambda*tr(gradField)*n;
//- if there is plasticity
// Plasticity effects
const constitutiveModel& rheology =
patch.boundaryMesh().mesh().objectRegistry::
lookupObject<constitutiveModel>("rheologyProperties");
if (rheology.plasticityActive())
{
traction -=
2*mu*(n & rheology.DEpsilonP().boundaryField()[patch.index()]);
}
//- if there are thermal effects
if (patch.boundaryMesh().mesh().objectRegistry::
foundObject<thermalModel>("thermalProperties"))
// Thermal effects
if
(
patch.boundaryMesh().mesh().objectRegistry::
foundObject<thermalModel>("thermalProperties")
)
{
const thermalModel& thermo =
patch.boundaryMesh().mesh().objectRegistry::
lookupObject<thermalModel>("thermalProperties");
const fvPatchField<scalar>& threeKalpha =
const fvPatchScalarField& threeKalpha =
patch.lookupPatchField<volScalarField, scalar>
("((threeK*rho)*alpha)");
if (fieldName == "DU")
// Incremental thermal contribution
if (incremental)
{
const fvPatchField<scalar>& DT =
const fvPatchScalarField& DT =
patch.lookupPatchField<volScalarField, scalar>("DT");
traction -= (n*threeKalpha*DT);
}
else
{
const fvPatchField<scalar>& T =
const fvPatchScalarField& T =
patch.lookupPatchField<volScalarField, scalar>("T");
const scalarField T0 = thermo.T0()().boundaryField()[patch.index()];
const scalarField T0 =
thermo.T0()().boundaryField()[patch.index()];
traction -= (n*threeKalpha*(T - T0));
}
}
// non linear terms
if (nonLinear == "updatedLagrangian" || nonLinear == "totalLagrangian")
// Non-linear terms
if
(
nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
|| nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
)
{
traction +=
(n & (mu*(gradField & gradField.T())))
+ 0.5*n*lambda*(gradField && gradField);
if (fieldName == "DU" && nonLinear == "totalLagrangian")
if
(
incremental
&& nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
)
{
// incremental total Lagrangian
const fvPatchField<tensor>& gradU =
patch.lookupPatchField<volTensorField, tensor>("grad(U)");
// Incremental total Lagrangian
const fvPatchTensorField& gradU =
patch.lookupPatchField<volTensorField, tensor>
(
"grad(" + integralFieldName + ")"
);
traction +=
(n & (mu*( (gradU & gradField.T()) + (gradField & gradU.T()))))
+ 0.5*n*lambda*tr((gradU & gradField.T()) + (gradField & gradU.T()));
(
n
& (
mu*
(
(gradU & gradField.T())
+ (gradField & gradU.T())
)
)
)
+ 0.5*n*lambda*tr
(
(gradU & gradField.T())
+ (gradField & gradU.T())
);
}
}
//- add old stress for incremental approaches
if (fieldName == "DU")
// Add old stress for incremental approaches
if (incremental)
{
// add on old traction
const fvPatchField<symmTensor>& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>("sigma");
const fvPatchSymmTensorField& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>
(
"sigma"
);
traction += (n & sigma);
}
//- visco-elastic
// Visco-elastic effects
if (rheology.viscoActive())
{
const fvPatchField<symmTensor>& DSigmaCorr =
patch.lookupPatchField<volSymmTensorField, symmTensor>("DSigmaCorr");
const fvPatchSymmTensorField& DSigmaCorr =
patch.lookupPatchField<volSymmTensorField, symmTensor>
(
"DSigmaCorr"
);
traction += (n & DSigmaCorr);
}
//- updated Lagrangian or total Lagrangian large strain
if (nonLinear == "updatedLagrangian" || nonLinear == "totalLagrangian")
// Updated Lagrangian or total Lagrangian large strain
if
(
nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
|| nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
)
{
tensorField F = I + gradField;
if (fieldName == "DU" && nonLinear == "totalLagrangian")
if
(
incremental
&& nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
)
{
const fvPatchField<tensor>& gradU =
patch.lookupPatchField<volTensorField, tensor>("grad(U)");
// Incremental total Lagrangian
const fvPatchTensorField& gradU =
patch.lookupPatchField<volTensorField, tensor>
(
"grad(" + integralFieldName + ")"
);
F += gradU;
}
tensorField Finv = inv(F);
scalarField J = det(F);
//- rotate second Piola Kirchhoff traction to be Cauchy traction
// Rotate second Piola Kirchhoff traction to be Cauchy traction
traction = (traction & F)/(mag(J * Finv & n));
}
}
return ttraction;
}
}
// * * * * * * * * * * * * * * * * Operators * * * * * * * * * * * * * * //
tmp<vectorField> tractionBoundaryGradient::operator()
(
Foam::tmp<Foam::vectorField> Foam::tractionBoundaryGradient::snGrad
(
const vectorField& traction,
const scalarField& pressure,
const word fieldName,
const word& workingFieldName,
const word& integralFieldName,
const fvPatch& patch,
Switch orthotropic,
word nonLinear
) const
{
// create tmp
const bool orthotropic,
const nonLinearGeometry::nonLinearType& nonLinear,
const bool incremental
)
{
// Create result
tmp<vectorField> tgradient(new vectorField(traction.size(), vector::zero));
vectorField& gradient = tgradient();
// lookup switches
// orthotropic solvers
// Orthotropic material
if (orthotropic)
{
// mechanical properties
// Get mechanical properties
const constitutiveModel& rheology =
patch.boundaryMesh().mesh().objectRegistry::
lookupObject<constitutiveModel>("rheologyProperties");
const diagTensorField K = rheology.K()().boundaryField()[patch.index()];
const diagTensorField K =
rheology.K()().boundaryField()[patch.index()];
const symmTensor4thOrderField C =
rheology.C()().boundaryField()[patch.index()];
// required fields
// Required fields
vectorField n = patch.nf();
const diagTensorField Kinv = inv(K);
const fvPatchField<tensor>& gradField =
patch.lookupPatchField<volTensorField, tensor>("grad(" + fieldName + ")");
const fvPatchTensorField& gradField =
patch.lookupPatchField<volTensorField, tensor>
(
"grad(" + workingFieldName + ")"
);
// calculate the traction to apply
// Calculate the traction to apply
vectorField Traction(n.size(), vector::zero);
tensorField sigmaExp(n.size(), tensor::zero);
//- total Lagrangian small strain
if (fieldName == "U" && nonLinear == "off")
// Total Lagrangian, small strain
if
(
!incremental
&& nonLinear == nonLinearGeometry::OFF
)
{
//- total traction
// Use total traction
Traction = (traction - n*pressure);
sigmaExp = (n*(n&(C && symm(gradField)))) - (K & gradField);
}
//- incremental total Lagrangian small strain
else if (fieldName == "DU" && nonLinear == "off")
// Incremental total Lagrangian small strain
else if
(
incremental
&& nonLinear == nonLinearGeometry::OFF
)
{
const fvPatchField<symmTensor>& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>("sigma");
const fvPatchSymmTensorField& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>
(
"sigma"
);
//- increment of traction
// Increment of traction
Traction = (traction - n*pressure) - (n & sigma);
sigmaExp = (n*(n&(C && symm(gradField)))) - (K & gradField);
}
//- updated Lagrangian large strain
else if (nonLinear == "updatedLagrangian")
// Updated Lagrangian large strain
else if
(
nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
)
{
const fvPatchField<symmTensor>& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>("sigma");
const fvPatchSymmTensorField& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>
(
"sigma"
);
tensorField F = I + gradField;
tensorField Finv = inv(F);
scalarField J = det(F);
vectorField nCurrent = Finv & n;
nCurrent /= mag(nCurrent);
nCurrent /= mag(nCurrent) + SMALL;
vectorField tractionCauchy = traction - nCurrent*pressure;
//- increment of 2nd Piola-Kirchhoff traction
Traction = (mag(J * Finv & n) * tractionCauchy & Finv) - (n & sigma);
// Increment of 2nd Piola-Kirchhoff traction
Traction = mag(J*(Finv & n))*(tractionCauchy & Finv) - (n & sigma);
sigmaExp = (n*(n&(C && symm(gradField)))) - (K & gradField);
sigmaExp = n*(n &(C && symm(gradField))) - (K & gradField);
}
else
{
FatalError
<< "solidTractionOrtho boundary condition not suitable for "
<< " field " << fieldName << " and " << nonLinear
FatalErrorIn
(
"tmp<vectorField> tractionBoundaryGradient::snGrad\n"
"(\n"
" const vectorField& traction,\n"
" const scalarField& pressure,\n"
" const word& workingFieldName,\n"
" const word& integralFieldName,\n"
" const fvPatch& patch,\n"
" const bool orthotropic,\n"
" const nonLinearGeometry::nonLinearType& nonLinear,\n"
" const bool incremental\n"
") const"
) << "solidTractionOrtho boundary condition not suitable for "
<< " field " << workingFieldName << " and "
<< nonLinearGeometry::nonLinearNames_[nonLinear]
<< abort(FatalError);
}
gradient =
n &
(
Kinv & ( n*(Traction) - sigmaExp )
);
gradient = n & (Kinv & ( n*(Traction) - sigmaExp ));
}
// standard isotropic solvers
else
{
// lookup material properties from the solver
const fvPatchField<scalar>& mu =
// Standard isotropic solvers
// Lookup material properties from the solver
const fvPatchScalarField& mu =
patch.lookupPatchField<volScalarField, scalar>("mu");
const fvPatchField<scalar>& lambda =
const fvPatchScalarField& lambda =
patch.lookupPatchField<volScalarField, scalar>("lambda");
// only for nonlinear elastic properties
@ -311,153 +400,215 @@ tmp<vectorField> tractionBoundaryGradient::traction
// lambda = plasticity.newLambda().boundaryField()[patch.index()];
// }
// required fields
vectorField n = patch.nf();
// gradient of the field
const fvPatchField<tensor>& gradField =
patch.lookupPatchField<volTensorField, tensor>("grad(" + fieldName + ")");
const fvPatchTensorField& gradField =
patch.lookupPatchField<volTensorField, tensor>
(
"grad(" + workingFieldName + ")"
);
//---------------------------//
//- calculate the actual traction to apply
//---------------------------//
vectorField Traction(n.size(),vector::zero);
vectorField Traction(n.size(), vector::zero);
//- total Lagrangian small strain
if (fieldName == "U" && nonLinear == "off")
// Total Lagrangian, small strain
if
(
!incremental
&& nonLinear == nonLinearGeometry::OFF
)
{
//- total traction
// Use total traction
Traction = (traction - n*pressure);
}
//- incremental total Lagrangian small strain
else if (fieldName == "DU" && nonLinear == "off")
// Incremental total Lagrangian small strain
else if
(
incremental
&& nonLinear == nonLinearGeometry::OFF
)
{
const fvPatchField<symmTensor>& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>("sigma");
const fvPatchSymmTensorField& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>
(
"sigma"
);
//- increment of traction
// Increment of traction
Traction = (traction - n*pressure) - (n & sigma);
}
//- updated Lagrangian or total Lagrangian large strain
else if (nonLinear == "updatedLagrangian" || nonLinear == "totalLagrangian")
else if
(
nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
|| nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
)
{
const fvPatchField<symmTensor>& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>("sigma");
const fvPatchSymmTensorField& sigma =
patch.lookupPatchField<volSymmTensorField, symmTensor>
(
"sigma"
);
tensorField F = I + gradField;
if (fieldName == "DU" && nonLinear == "totalLagrangian") // for incr TL
if
(
incremental
&& nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
)
{
const fvPatchField<tensor>& gradU =
patch.lookupPatchField<volTensorField, tensor>("grad(U)");
// Incremental total Lagrangian
const fvPatchTensorField& gradU =
patch.lookupPatchField<volTensorField, tensor>
(
"grad(" + integralFieldName + ")"
);
F += gradU;
}
tensorField Finv = hinv(F);
scalarField J = det(F);
vectorField nCurrent = Finv & n;
nCurrent /= mag(nCurrent);
nCurrent /= mag(nCurrent) + SMALL;
vectorField tractionCauchy = traction - nCurrent*pressure;
Traction = (mag(J * Finv & n) * tractionCauchy & Finv);
Traction = mag(J*(Finv & n))*(tractionCauchy & Finv);
if (fieldName == "DU")
if (incremental)
{
//- increment of 2nd Piola-Kirchhoff traction
// Increment of 2nd Piola-Kirchhoff traction
Traction -= (n & sigma);
}
}
else
{
FatalError
<< "Field " << fieldName << " and " << nonLinear
FatalErrorIn
(
"tmp<vectorField> tractionBoundaryGradient::snGrad\n"
"(\n"
" const vectorField& traction,\n"
" const scalarField& pressure,\n"
" const word& workingFieldName,\n"
" const word& integralFieldName,\n"
" const fvPatch& patch,\n"
" const bool orthotropic,\n"
" const nonLinearGeometry::nonLinearType& nonLinear,\n"
" const bool incremental\n"
") const"
) << " field " << workingFieldName << " and "
<< nonLinearGeometry::nonLinearNames_[nonLinear]
<< " nonLinear are not compatible!"
<< exit(FatalError);
<< abort(FatalError);
}
//- visco-elastic
const constitutiveModel& rheology =
patch.boundaryMesh().mesh().objectRegistry::
lookupObject<constitutiveModel>("rheologyProperties");
if (rheology.viscoActive())
{
//Info << "visco active" << endl;
const fvPatchField<symmTensor>& DSigmaCorr =
patch.lookupPatchField<volSymmTensorField, symmTensor>("DSigmaCorr");
const fvPatchSymmTensorField& DSigmaCorr =
patch.lookupPatchField<volSymmTensorField, symmTensor>
(
"DSigmaCorr"
);
Traction -= (n & DSigmaCorr);
}
//---------------------------//
//- calculate the normal gradient based on the traction
//---------------------------//
// Calculate the normal gradient based on the traction
gradient =
Traction
- (n & (mu*gradField.T() - (mu + lambda)*gradField))
- n*lambda*tr(gradField);
//- if there is plasticity
//- Plasticity contribution
if (rheology.plasticityActive())
{
//Info << "plasticity is active" << endl;
gradient +=
2*mu*(n & rheology.DEpsilonP().boundaryField()[patch.index()]);
}
//- if there are thermal effects
if (patch.boundaryMesh().mesh().objectRegistry::
foundObject<thermalModel>("thermalProperties"))
// Thermal effects
if
(
patch.boundaryMesh().mesh().objectRegistry::
foundObject<thermalModel>("thermalProperties")
)
{
const thermalModel& thermo =
patch.boundaryMesh().mesh().objectRegistry::
lookupObject<thermalModel>("thermalProperties");
const fvPatchField<scalar>& threeKalpha =
const fvPatchScalarField& threeKalpha =
patch.lookupPatchField<volScalarField, scalar>
("((threeK*rho)*alpha)");
(
"((threeK*rho)*alpha)"
);
if (fieldName == "DU")
if (!incremental)
{
const fvPatchField<scalar>& DT =
const fvPatchScalarField& DT =
patch.lookupPatchField<volScalarField, scalar>("DT");
gradient += (n*threeKalpha*DT);
gradient += n*threeKalpha*DT;
}
else
{
const fvPatchField<scalar>& T =
const fvPatchScalarField& T =
patch.lookupPatchField<volScalarField, scalar>("T");
const scalarField T0 = thermo.T0()().boundaryField()[patch.index()];
const scalarField T0 =
thermo.T0()().boundaryField()[patch.index()];
gradient += (n*threeKalpha*(T - T0));
gradient += n*threeKalpha*(T - T0);
}
}
//- higher order non-linear terms
if (nonLinear == "updatedLagrangian" || nonLinear == "totalLagrangian")
// Higher order non-linear terms
if
(
nonLinear == nonLinearGeometry::UPDATED_LAGRANGIAN
|| nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
)
{
// no extra relaxation
gradient -=
(n & (mu*(gradField & gradField.T())))
// + 0.5*n*lambda*(gradField && gradField);
+ 0.5*n*lambda*tr(gradField & gradField.T());
//- tensorial identity
//- tr(gradField & gradField.T())*I == (gradField && gradField)*I
if (fieldName == "DU" && nonLinear == "totalLagrangian")
if
(
incremental
&& nonLinear == nonLinearGeometry::TOTAL_LAGRANGIAN
)
{
// gradU is const in a time step
const fvPatchField<tensor>& gradU =
const fvPatchTensorField& gradU =
patch.lookupPatchField<volTensorField, tensor>("grad(U)");
gradient -=
(n &
(mu*( (gradField & gradU.T())
+ (gradU & gradField.T()) ))
(
n &
(
mu*
(
(gradField & gradU.T())
+ (gradU & gradField.T())
)
+ 0.5*n*lambda*tr( (gradField & gradU.T())
+ (gradU & gradField.T()) );
)
)
+ 0.5*n*lambda*tr
(
(gradField & gradU.T())
+ (gradU & gradField.T())
);
}
}
@ -466,8 +617,6 @@ tmp<vectorField> tractionBoundaryGradient::traction
return tgradient;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View file

@ -35,6 +35,7 @@ SourceFiles
Author
Philip Cardiff UCD
Clean-up and re-factoring Hrvoje Jasak
\*---------------------------------------------------------------------------*/
@ -47,6 +48,7 @@ Author
#include "volFields.H"
#include "tmp.H"
#include "rheologyLaw.H"
#include "nonLinearGeometry.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -59,49 +61,38 @@ namespace Foam
class tractionBoundaryGradient
{
public:
//- Runtime type information
TypeName("tractionBoundaryGradient");
// Constructors
tractionBoundaryGradient()
{}
// Destructor
virtual ~tractionBoundaryGradient()
{}
// Member functions
// Static member functions
//- Return the boundary Cauchy traction corresponding to
// the given gradient
tmp<vectorField> traction
static tmp<vectorField> traction
(
const tensorField& gradField,
const word fieldName,
const word& workingFieldName, // Working variable
const word& integralFieldName, // Integrated displacement
const fvPatch& patch,
Switch orthotropic,
word nonLinear
) const;
const bool orthotropic,
const nonLinearGeometry::nonLinearType& nonLinear,
const bool incremental
);
// Operators
tmp<vectorField> operator()
//- Return surface-normal gradient given traction and pressure
static tmp<vectorField> snGrad
(
const vectorField& traction,
const scalarField& pressure,
const word fieldName,
const word& workingFieldName, // Working variable
const word& integralFieldName, // Integrated displacement
const fvPatch& patch,
Switch orthotropic,
word nonLinear
) const;
const bool orthotropic,
const nonLinearGeometry::nonLinearType& nonLinear,
const bool incremental
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View file

@ -269,17 +269,23 @@ Foam::dirichletNeumannFriction::dirichletNeumannFriction
const fvPatch& slavePatch = mesh.boundary()[slavePatchIndex];
const fvPatchField<tensor>& gradField =
slavePatch.lookupPatchField<volTensorField, tensor>
("grad("+fieldName+")");
vectorField slaveShearTraction =
("grad(" + fieldName + ")");
bool incremental(fieldName == "DU");
vectorField slaveShearTraction
(
(I - sqr(slaveFaceNormals))
&
tractionBoundaryGradient().traction
& tractionBoundaryGradient::traction
(
gradField,
fieldName,
"U",
slavePatch,
orthotropic,
nonLinear
nonLinearGeometry::nonLinearNames_[nonLinear],
incremental
)
);

View file

@ -149,10 +149,10 @@ dirichletNeumann::dirichletNeumann
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void dirichletNeumann::correct
(
void dirichletNeumann::correct
(
const PrimitivePatch<face, List, pointField>& masterFaceZonePatch,
const PrimitivePatch<face, List, pointField>& slaveFaceZonePatch,
const intersection::algorithm alg,
@ -161,11 +161,13 @@ dirichletNeumann::dirichletNeumann
const Switch orthotropic,
const word nonLinear,
vectorField& slaveFaceNormals,
GGIInterpolation< PrimitivePatch< face, List, pointField >,
GGIInterpolation
<
PrimitivePatch< face, List, pointField >,
PrimitivePatch< face, List, pointField >
>* ggiInterpolatorPtr
)
{
)
{
if (!settleContact_ || (iCorr_ < settleIterationNumber_))
{
@ -209,8 +211,8 @@ dirichletNeumann::dirichletNeumann
// pointDistanceToIntersection() sometimes gives a seg fault when the
// momentum equation diverges
globalSlavePointPenetration
= masterToSlavePatchToPatchInterpolator.pointDistanceToIntersection();
globalSlavePointPenetration =
masterToSlavePatchToPatchInterpolator.pointDistanceToIntersection();
// get local point values from global values
forAll(slavePointPenetration, pointI)
@ -218,10 +220,7 @@ dirichletNeumann::dirichletNeumann
// the local point values seem to be kept at the start
// of the global field
slavePointPenetration[pointI] =
globalSlavePointPenetration
[
pointI
];
globalSlavePointPenetration[pointI];
//- when the master surface surrounds the slave (like the pelvis and
// femur head) then
@ -505,8 +504,9 @@ dirichletNeumann::dirichletNeumann
{
slaveDispPoints =
localSlaveInterpolator.faceToPointInterpolate<vector>(slaveDisp_);
slaveDisp_ =
localSlaveInterpolator.pointToFaceInterpolate<vector>(slaveDispPoints);
slaveDisp_ = localSlaveInterpolator.pointToFaceInterpolate<vector>
(slaveDispPoints);
// make sure no tangential component
slaveDisp_ = slaveFaceNormals*(slaveFaceNormals & slaveDisp_);
@ -533,14 +533,21 @@ dirichletNeumann::dirichletNeumann
const fvPatch& slavePatch = mesh.boundary()[slavePatchIndex];
const fvPatchField<tensor>& gradField =
slavePatch.lookupPatchField<volTensorField, tensor>
("grad("+fieldName+")");
slavePressure_ = tractionBoundaryGradient().traction
(
"grad(" + fieldName + ")"
);
bool incremental(fieldName == "DU");
slavePressure_ = tractionBoundaryGradient::traction
(
gradField,
fieldName,
"U",
slavePatch,
orthotropic,
nonLinear
nonLinearGeometry::nonLinearNames_[nonLinear],
incremental
);
// set traction to zero on faces not in contact
@ -555,16 +562,18 @@ dirichletNeumann::dirichletNeumann
forAll(touchFraction_, facei)
{
if (touchFraction_[facei] < SMALL
||
( (slaveFaceNormals[facei] & slavePressure_[facei])
> 1e-3*maxMagSlavePressure)
if
(
touchFraction_[facei] < SMALL
|| (
(slaveFaceNormals[facei] & slavePressure_[facei])
> 1e-3*maxMagSlavePressure
)
)
{
slavePressure_[facei] = vector::zero;
slaveValueFrac_[facei] = symmTensor::zero;
slaveDisp_[facei] =
slaveFaceNormals[facei]
slaveDisp_[facei] = slaveFaceNormals[facei]
*(slaveFaceNormals[facei]&oldSlaveDisp[facei]);
}
}
@ -581,9 +590,14 @@ dirichletNeumann::dirichletNeumann
{
forAll(slavePressure_, facei)
{
if ( (slaveFaceNormals[facei]&slavePressure_[facei]) < -pressureLimit_)
if
(
(slaveFaceNormals[facei] & slavePressure_[facei])
< -pressureLimit_
)
{
slavePressure_[facei] = -pressureLimit_*slaveFaceNormals[facei];
slavePressure_[facei] =
-pressureLimit_*slaveFaceNormals[facei];
}
}
}

View file

@ -206,15 +206,16 @@ void fixedDisplacementOrSolidTractionFvPatchVectorField::updateCoeffs()
this->valueFraction() = symmTensor::zero;
// set gradient to enfore specified traction
refGrad() = tractionBoundaryGradient()
refGrad() = tractionBoundaryGradient::snGrad
(
traction_,
pressure_,
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
);
}
else
{

View file

@ -144,6 +144,7 @@ fixedDisplacementZeroShearFvPatchVectorField
FatalError << "value entry not found for patch " << patch().name()
<< exit(FatalError);
}
this->refValue() = *this;
Field<vector> normalValue = transform(valueFraction(), refValue());
@ -223,15 +224,19 @@ void fixedDisplacementZeroShearFvPatchVectorField::updateCoeffs()
// this->valueFraction() = sqr(nCurrent);
// }
refGrad() = tractionBoundaryGradient()
bool incremental(fieldName_ == "DU");
refGrad() = tractionBoundaryGradient::snGrad
(
vectorField(patch().size(), vector::zero),
scalarField(patch().size(), 0.0),
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
nonLinear_,
incremental
);
directionMixedFvPatchVectorField::updateCoeffs();
}

View file

@ -201,14 +201,15 @@ void fixedDisplacementZeroShearOrSolidTractionFvPatchVectorField::rmap
}
void fixedDisplacementZeroShearOrSolidTractionFvPatchVectorField::updateCoeffs()
void
fixedDisplacementZeroShearOrSolidTractionFvPatchVectorField::updateCoeffs()
{
if (this->updated())
{
return;
}
if ( mag(timeSeries_(this->db().time().timeOutputValue())) < SMALL)
if (mag(timeSeries_(this->db().time().timeOutputValue())) < SMALL)
{
// traction boundary
@ -216,15 +217,16 @@ void fixedDisplacementZeroShearOrSolidTractionFvPatchVectorField::updateCoeffs()
this->valueFraction() = symmTensor::zero;
// set gradient to enfore specified traction
refGrad() = tractionBoundaryGradient()
refGrad() = tractionBoundaryGradient::snGrad
(
traction_,
pressure_,
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
);
}
else
{
@ -234,15 +236,16 @@ void fixedDisplacementZeroShearOrSolidTractionFvPatchVectorField::updateCoeffs()
this->valueFraction() = sqr(fixedNormal_);
// force zero shear stresses
refGrad() = tractionBoundaryGradient()
refGrad() = tractionBoundaryGradient::snGrad
(
vectorField(traction_.size(), vector::zero),
scalarField(traction_.size(), 0.0),
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
);
// set displacement
refValue() = displacement_;
@ -256,7 +259,7 @@ void fixedDisplacementZeroShearOrSolidTractionFvPatchVectorField::updateCoeffs()
void fixedDisplacementZeroShearOrSolidTractionFvPatchVectorField::write
(
Ostream& os
) const
) const
{
directionMixedFvPatchVectorField::write(os);
os.writeKeyword("nonLinear")

View file

@ -767,6 +767,8 @@ void solidContactFvPatchVectorField::updateCoeffs()
}
// set boundary conditions
bool incremental(fieldName_ == "DU");
if (!master_)
{
// set refValue, refGrad and valueFraction
@ -778,16 +780,18 @@ void solidContactFvPatchVectorField::updateCoeffs()
//refGrad - set traction
refGrad() =
tractionBoundaryGradient()
tractionBoundaryGradient::snGrad
(
frictionContactModelPtr_->slaveTraction()
+ normalContactModelPtr_->slavePressure(),
scalarField(patch().size(),0.0),
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
nonLinear_,
incremental
);
//valueFraction
valueFraction() =
@ -805,20 +809,21 @@ void solidContactFvPatchVectorField::updateCoeffs()
{
// set to master to traction free if it is rigid
refGrad() =
tractionBoundaryGradient()
tractionBoundaryGradient::snGrad
(
vectorField(patch().size(),vector::zero),
scalarField(patch().size(),0.0),
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
nonLinear_,
incremental
);
}
else
{
refGrad() =
tractionBoundaryGradient()
refGrad() = tractionBoundaryGradient::snGrad
(
interpolateSlaveToMaster
(
@ -826,11 +831,13 @@ void solidContactFvPatchVectorField::updateCoeffs()
-normalContactModelPtr_->slavePressure()
),
scalarField(patch().size(),0.0),
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
nonLinear_,
incremental
);
}
}
} // if correction freqeuncy
@ -840,21 +847,26 @@ void solidContactFvPatchVectorField::updateCoeffs()
else
{
// set refGrad to traction free for master and slave
bool incremental(fieldName_ == "DU");
refGrad() =
tractionBoundaryGradient()
tractionBoundaryGradient::snGrad
(
vectorField(patch().size(),vector::zero),
scalarField(patch().size(),0.0),
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
nonLinear_,
incremental
);
}
directionMixedFvPatchVectorField::updateCoeffs();
}
// Interpolate traction from slave to master
tmp<vectorField> solidContactFvPatchVectorField::interpolateSlaveToMaster
(
@ -1326,21 +1338,32 @@ tmp<scalarField> solidContactFvPatchVectorField::Qc() const
// average force
const fvPatchField<tensor>& gradField =
patch().lookupPatchField<volTensorField, tensor>("grad("+fieldName_+")");
patch().lookupPatchField<volTensorField, tensor>
(
"grad(" + fieldName_ + ")"
);
// current Cauchy traction for nonlinear
bool incremental(fieldName_ == "DU");
const vectorField curTrac =
tractionBoundaryGradient().traction
tractionBoundaryGradient::traction
(
gradField,
fieldName_,
"U",
patch(),
orthotropic_,
word(nonLinearGeometry::nonLinearNames_[nonLinear_])
nonLinear_,
incremental
);
vectorField Sf = patch().Sf();
if (nonLinear_ != nonLinearGeometry::OFF
&& nonLinear_ == nonLinearGeometry::TOTAL_LAGRANGIAN)
if
(
nonLinear_ != nonLinearGeometry::OFF
&& nonLinear_ == nonLinearGeometry::TOTAL_LAGRANGIAN
)
{
// current areas
const fvPatchField<tensor>& gradU =
@ -1352,7 +1375,7 @@ tmp<scalarField> solidContactFvPatchVectorField::Qc() const
}
const scalarField magSf = mag(Sf);
const vectorField curForce = magSf * curTrac;
const vectorField curForce = magSf*curTrac;
const fvPatchField<symmTensor>& oldSigma =
patch().lookupPatchField<volSymmTensorField, symmTensor>("sigma_0");

View file

@ -210,15 +210,19 @@ void solidTractionFvPatchVectorField::updateCoeffs()
return;
}
gradient() = tractionBoundaryGradient()
bool incremental(fieldName_ == "DU");
gradient() = tractionBoundaryGradient::snGrad
(
traction_,
pressure_,
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
nonLinear_,
incremental
);
fixedGradientFvPatchVectorField::updateCoeffs();
}
@ -243,14 +247,14 @@ void solidTractionFvPatchVectorField::evaluate(const Pstream::commsTypes)
//- non-orthogonal correction vectors
vectorField k = delta - n*(n&delta);
Field<vector>::operator=
vectorField::operator=
(
this->patchInternalField()
+ (k&gradField.patchInternalField())
+ gradient()/this->patch().deltaCoeffs()
);
fvPatchField<vector>::evaluate();
fvPatchVectorField::evaluate();
}
// Write

View file

@ -191,15 +191,19 @@ void solidTractionFreeFvPatchVectorField::updateCoeffs()
return;
}
gradient() = tractionBoundaryGradient()
bool incremental(fieldName_ == "DU");
gradient() = tractionBoundaryGradient::snGrad
(
vectorField(patch().size(), vector::zero),
scalarField(patch().size(), 0.0),
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
)();
nonLinear_,
incremental
);
fixedGradientFvPatchVectorField::updateCoeffs();
}
@ -226,7 +230,7 @@ void solidTractionFreeFvPatchVectorField::evaluate(const Pstream::commsTypes)
Field<vector>::operator=
(
this->patchInternalField()
+ (k&gradField.patchInternalField())
+ (k & gradField.patchInternalField())
+ gradient()/this->patch().deltaCoeffs()
);

View file

@ -66,7 +66,7 @@ class solidTractionFreeFvPatchVectorField
//- Name of the displacement field
const word fieldName_;
//- if it is a non linear solver
//- Is it a non linear solver
nonLinearGeometry::nonLinearType nonLinear_;
//- Is it an orthropic solver

View file

@ -233,14 +233,18 @@ void timeVaryingFixedDisplacementZeroShearFvPatchVectorField::updateCoeffs()
//vectorField n = patch().nf();
//this->valueFraction() = sqr(n);
refGrad() = tractionBoundaryGradient()
bool incremental(fieldName_ == "DU");
refGrad() = tractionBoundaryGradient::snGrad
(
vectorField(patch().size(), vector::zero),
scalarField(patch().size(), 0),
word(fieldName_),
fieldName_,
"U",
patch(),
orthotropic_,
nonLinearGeometry::nonLinearNames_[nonLinear_]
nonLinear_,
incremental
);
directionMixedFvPatchVectorField::updateCoeffs();

View file

@ -53,7 +53,7 @@ class nonLinearGeometry
{
public:
//- non-linear solver options
//- Non-linear solver options
enum nonLinearType
{
OFF,

View file

@ -27,19 +27,20 @@ boundaryField
}
right
{
type analyticalPlateHoleTraction;
// type analyticalPlateHoleTraction;
type solidTraction;
traction uniform (0 0 0);
pressure uniform 1e7;
}
down
{
type symmetryPlane;
}
up
{
type analyticalPlateHoleTraction;
// type analyticalPlateHoleTraction;
type solidTractionFree;
}
hole
{
type solidTractionFree;