/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | foam-extend: Open Source CFD
\\ / O peration | Version: 4.0
\\ / A nd | Web: http://www.foam-extend.org
\\/ M anipulation | For copyright notice see file Copyright
-------------------------------------------------------------------------------
License
This file is part of foam-extend.
foam-extend is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
foam-extend is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with foam-extend. If not, see .
Description
\*---------------------------------------------------------------------------*/
#include "contactPatchPair.H"
#include "contactProblem.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from components
Foam::contactPatchPair::contactPatchPair
(
const word& name,
const contactProblem& cp,
const word& masterPatchName,
const word& slavePatchName,
const dimensionedScalar& frictionCoeff,
const scalar contactTol,
const intersection::algorithm alg,
const intersection::direction dir
)
:
name_(name),
cp_(cp),
masterPatch_(masterPatchName, cp.mesh().boundaryMesh()),
slavePatch_(slavePatchName, cp.mesh().boundaryMesh()),
frictionCoeff_(frictionCoeff),
contactTol_(contactTol),
masterInterpolate_
(
cp.mesh().boundaryMesh()[masterPatch_.index()]
),
slaveInterpolate_
(
cp.mesh().boundaryMesh()[slavePatch_.index()]
),
masterToSlaveInterpolate_
(
cp.mesh().boundaryMesh()[masterPatch_.index()], // from patch
cp.mesh().boundaryMesh()[slavePatch_.index()], // to patch
alg,
dir
),
slaveToMasterInterpolate_
(
cp.mesh().boundaryMesh()[slavePatch_.index()], // from patch
cp.mesh().boundaryMesh()[masterPatch_.index()], // to patch
alg,
dir
)
{}
// Construct from dictionary
Foam::contactPatchPair::contactPatchPair
(
const word& name,
const contactProblem& cp,
const dictionary& dict
)
:
name_(name),
cp_(cp),
masterPatch_(dict.lookup("masterPatch"), cp.mesh().boundaryMesh()),
slavePatch_(dict.lookup("slavePatch"), cp.mesh().boundaryMesh()),
frictionCoeff_(dict.lookup("frictionCoeff")),
contactTol_(readScalar(dict.lookup("contactTol"))),
masterInterpolate_
(
cp.mesh().boundaryMesh()[masterPatch_.index()]
),
slaveInterpolate_
(
cp.mesh().boundaryMesh()[slavePatch_.index()]
),
masterToSlaveInterpolate_
(
cp.mesh().boundaryMesh()[masterPatch_.index()], // from patch
cp.mesh().boundaryMesh()[slavePatch_.index()], // to patch
intersection::algorithmNames_.read(dict.lookup("projectionAlgo")),
intersection::directionNames_.read(dict.lookup("projectionDir"))
),
slaveToMasterInterpolate_
(
cp.mesh().boundaryMesh()[slavePatch_.index()], // from patch
cp.mesh().boundaryMesh()[masterPatch_.index()], // to patch
intersection::algorithmNames_.read(dict.lookup("projectionAlgo")),
intersection::directionNames_.read(dict.lookup("projectionDir"))
)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp
Foam::contactPatchPair::masterTouchFraction() const
{
// Get reference to displacement field and mesh
const volVectorField& U = cp_.U();
const fvMesh& mesh = cp_.mesh();
// Interpolate slave displacement into master vertices
vectorField masterVertexU =
slaveToMasterInterpolate_.pointInterpolate
(
slaveInterpolate_.faceToPointInterpolate
(
U.boundaryField()[slavePatch_.index()]
)
);
const vectorField& projectionDir =
mesh.boundaryMesh()[masterPatch_.index()].pointNormals();
// Calculate master gap function
scalarField vertexMasterGap =
(
(
masterVertexU
- masterInterpolate_.faceToPointInterpolate
(
U.boundaryField()[masterPatch_.index()]
)
)
& projectionDir
) + slaveToMasterInterpolate_.pointDistanceToIntersection() - contactTol_;
// Calculate area in contact
const faceList& masterPatchLocalFaces =
mesh.boundaryMesh()[masterPatch_.index()].localFaces();
const pointField& masterPatchLocalPoints =
mesh.boundaryMesh()[masterPatch_.index()].localPoints();
tmp ttouchFrac
(
new scalarField(masterPatchLocalFaces.size(), 0)
);
scalarField& touchFrac = ttouchFrac();
forAll (masterPatchLocalFaces, faceI)
{
touchFrac[faceI] =
masterPatchLocalFaces[faceI].areaInContact
(
masterPatchLocalPoints,
vertexMasterGap
);
}
return ttouchFrac;
}
Foam::tmp
Foam::contactPatchPair::slaveTouchFraction() const
{
// Get reference to displacement field and mesh
const volVectorField& U = cp_.U();
const fvMesh& mesh = cp_.mesh();
// Interpolate master displacement into slave vertices
vectorField slaveVertexU =
masterToSlaveInterpolate_.pointInterpolate
(
masterInterpolate_.faceToPointInterpolate
(
U.boundaryField()[masterPatch_.index()]
)
);
const vectorField& projectionDir =
mesh.boundaryMesh()[slavePatch_.index()].pointNormals();
// Calculate slave gap function
scalarField vertexSlaveGap =
(
(
slaveVertexU
- slaveInterpolate_.faceToPointInterpolate
(
U.boundaryField()[slavePatch_.index()]
)
)
& projectionDir
) + masterToSlaveInterpolate_.pointDistanceToIntersection() - contactTol_;
// Calculate area in contact
const faceList& slavePatchLocalFaces =
mesh.boundaryMesh()[slavePatch_.index()].localFaces();
const pointField& slavePatchLocalPoints =
mesh.boundaryMesh()[slavePatch_.index()].localPoints();
tmp ttouchFrac
(
new scalarField(slavePatchLocalFaces.size(), 0)
);
scalarField& touchFrac = ttouchFrac();
forAll (slavePatchLocalFaces, faceI)
{
touchFrac[faceI] =
slavePatchLocalFaces[faceI].areaInContact
(
slavePatchLocalPoints,
vertexSlaveGap
);
}
return ttouchFrac;
}
void Foam::contactPatchPair::correct
(
const FieldField& curTraction,
FieldField& newTraction,
FieldField& refValue,
FieldField& valueFraction
)
{
// Get reference to displacement field and mesh
const volVectorField::GeometricBoundaryField& Upatches =
cp_.U().boundaryField();
const fvMesh& mesh = cp_.mesh();
const surfaceVectorField::GeometricBoundaryField& Apatches =
mesh.Sf().boundaryField();
const surfaceScalarField::GeometricBoundaryField& magApatches =
mesh.magSf().boundaryField();
// Get patch indices
const label masterIndex = masterPatch_.index();
const label slaveIndex = slavePatch_.index();
// Calculate patch normals
vectorField nMasterPatch = Apatches[masterIndex]/magApatches[masterIndex];
vectorField nSlavePatch = Apatches[slaveIndex]/magApatches[slaveIndex];
// Calculate slave pressure and tangential force
scalarField slavePressure = -( nSlavePatch & curTraction[slaveIndex]);
// Enforce gradient condition on the master patch
// Calculate relative tangential velocity for master patch
vectorField relUmaster =
slaveToMasterInterpolate_.faceInterpolate
(
Upatches[slaveIndex]
)
- Upatches[masterIndex];
relUmaster -= nMasterPatch*(nMasterPatch & relUmaster);
relUmaster /= mag(relUmaster) + VSMALL;
// Calculate tangential master traction
scalarField magMasterTangential =
Foam::mag((I - nMasterPatch*nMasterPatch) & curTraction[masterIndex]);
// Calculate master pressure
scalarField masterPressure =
max
(
slaveToMasterInterpolate_.faceInterpolate
(
slavePressure
),
scalar(0)
);
// Calculate master traction, using the positive part of
// slave pressure and tangential fricton
// Mind the signs: pressure = negative gradient (minus master normal)
// friction = positive pressure
newTraction[masterIndex] +=
masterTouchFraction()*
(
-nMasterPatch*masterPressure
+ relUmaster*
min
(
frictionCoeff_.value()*masterPressure,
magMasterTangential
)
);
// Enforce direction mixed condition on the slave patch
// Calculate slave fraction. Correct for negative pressure
// (if the pressure is negative, the contact is released)
//HJ, fiddle pos pressure!!!
scalarField slaveFrac = slaveTouchFraction();
// Calculate slave displacement
vectorField slaveVertexU =
masterToSlaveInterpolate_.pointInterpolate
(
masterInterpolate_.faceToPointInterpolate
(
Upatches[masterIndex]
)
);
const vectorField& projectionDir =
mesh.boundaryMesh()[slaveIndex].pointNormals();
// Calculate slave displacement
vectorField slaveDisp =
slaveInterpolate_.pointToFaceInterpolate
(
slaveVertexU
+ masterToSlaveInterpolate_.pointDistanceToIntersection()
*projectionDir
);
// Accumulate normal of slave displacement
refValue[slaveIndex] +=
nSlavePatch*
min
(
pos(slaveFrac)*
(
(nSlavePatch & Upatches[slaveIndex])
+ slaveFrac*contactTol_
),
(nSlavePatch & slaveDisp)
);
// Accumulate slave friction
// Calculate relative tangential velocity for slave patch
vectorField relUslave =
masterToSlaveInterpolate_.faceInterpolate
(
Upatches[masterIndex]
)
- Upatches[slaveIndex];
relUslave -= nSlavePatch*(nSlavePatch & relUslave);
relUslave /= mag(relUslave) + VSMALL;
// Take out normal component out of slave traction and find the
// magnitude of the tangential traction.
scalarField magSlaveTangential =
Foam::mag((I - nSlavePatch*nSlavePatch) & curTraction[slaveIndex]);
// Calculate slave traction
newTraction[slaveIndex] +=
slaveFrac*relUslave*
min
(
frictionCoeff_.value()*max(slavePressure, scalar(0)),
magSlaveTangential
);
// Accumulate slave touch fraction
valueFraction[slaveIndex] += slaveFrac;
/*
Info << "slavePressure: " << slavePressure << nl
<< "slaveTouchFrac: " << slaveTouchFraction() << nl
// << "slaveFrac: " << slaveFrac << nl
<< "refValueSlave: " << refValue[slaveIndex].component(vector::Y) << nl
// << "slaveTraction: " << newTraction[slaveIndex] << nl
<< "masterTouchFrac: " << masterTouchFraction() << nl
// << "interpolated slave pressure: "
// << slaveToMasterInterpolate_.faceInterpolate
// (
// slavePressure
// )
// << nl
// << "masterTraction: "
// << newTraction[masterIndex].component(vector::Y)
<< endl;
*/
}
void Foam::contactPatchPair::writeDict(Ostream& os) const
{
os << nl << name() << nl << token::BEGIN_BLOCK;
os << "masterPatch " << masterPatch_.name() << token::END_STATEMENT << nl
<< "slavePatch " << slavePatch_.name() << token::END_STATEMENT << nl
<< "frictionCoeff " << frictionCoeff_ << token::END_STATEMENT << nl
<< "contactTol " << contactTol_ << token::END_STATEMENT << nl
<< "projectionAlgo "
<< intersection::algorithmNames_
[masterToSlaveInterpolate_.projectionAlgo()]
<< token::END_STATEMENT << nl
<< "projectionDir "
<< intersection::directionNames_
[masterToSlaveInterpolate_.projectionDir()]
<< token::END_STATEMENT << nl
<< token::END_BLOCK << endl;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //