434 lines
12 KiB
C
434 lines
12 KiB
C
/*---------------------------------------------------------------------------*\
|
|
========= |
|
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
\\ / O peration |
|
|
\\ / A nd | Copyright (C) 2004-2007 Hrvoje Jasak
|
|
\\/ M anipulation |
|
|
-------------------------------------------------------------------------------
|
|
License
|
|
This file is part of OpenFOAM.
|
|
|
|
OpenFOAM 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 2 of the License, or (at your
|
|
option) any later version.
|
|
|
|
OpenFOAM 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 OpenFOAM; if not, write to the Free Software Foundation,
|
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
Description
|
|
A pair of surfaces in contact.
|
|
|
|
\*---------------------------------------------------------------------------*/
|
|
|
|
#include "contactPatchPair.H"
|
|
#include "contactProblem.H"
|
|
|
|
|
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
|
|
// Construct from dictionary
|
|
Foam::contactPatchPair::contactPatchPair
|
|
(
|
|
const word& name,
|
|
contactProblem& cp,
|
|
const dictionary& dict
|
|
)
|
|
:
|
|
contactActive_(dict.lookup("contactActive")),
|
|
name_(name),
|
|
cp_(cp),
|
|
alg_(intersection::algorithmNames_.read(dict.lookup("projectionAlgo"))),
|
|
dir_(intersection::directionNames_.read(dict.lookup("projectionDir"))),
|
|
masterPatch_(dict.lookup("masterPatch"), cp.mesh().boundaryMesh()),
|
|
slavePatch_(dict.lookup("slavePatch"), cp.mesh().boundaryMesh()),
|
|
contactGapTol_(readScalar(dict.lookup("contactGapTol"))),
|
|
penaltyScaleFactor_(readScalar(dict.lookup("penaltyScaleFactor"))),
|
|
returnScaleFactor_(readScalar(dict.lookup("returnScaleFactor"))),
|
|
contactIterNum_(0),
|
|
contactFilePtr_(NULL),
|
|
slaveFaceZoneName_(slavePatch_.name() + "FaceZone"),
|
|
masterFaceZoneName_(masterPatch_.name() + "FaceZone"),
|
|
slavePointZoneName_(slavePatch_.name() + "PointZone"),
|
|
totalSlavePointForce_(
|
|
cp_.mesh().boundaryMesh()[slavePatch_.index()].pointNormals().size(), vector::zero),
|
|
// IOobject
|
|
// (
|
|
// "totalSlavePointForce",
|
|
// cp_.mesh().time().timeName(),
|
|
// cp_.mesh(),
|
|
// IOobject::READ_IF_PRESENT,
|
|
// IOobject::AUTO_WRITE
|
|
// ),
|
|
// vectorField(cp_.mesh().boundaryMesh()[slavePatch_.index()].pointNormals().size(), vector::zero)
|
|
// ),
|
|
slavePointPenetration_(
|
|
cp_.mesh().boundaryMesh()[slavePatch_.index()].pointNormals().size(),
|
|
0.0
|
|
),
|
|
masterPointPenetration_(
|
|
cp_.mesh().boundaryMesh()[masterPatch_.index()].pointNormals().size(),
|
|
0.0
|
|
),
|
|
globalSlavePointPenetration_(
|
|
cp_.mesh().pointZones()[cp_.mesh().faceZones().findZoneID(slaveFaceZoneName_)].size(),
|
|
0.0
|
|
),
|
|
globalMasterPointPenetration_(
|
|
cp_.mesh().pointZones()[cp_.mesh().faceZones().findZoneID(masterFaceZoneName_)].size(),
|
|
0.0
|
|
),
|
|
oldTotalSlavePointForce_(
|
|
cp_.mesh().boundaryMesh()[slavePatch_.index()].pointNormals().size(),
|
|
vector::zero
|
|
),
|
|
oldMinSlavePointPenetration_(0.0),
|
|
penetrationLimit_(readScalar(dict.lookup("penetrationLimit"))),
|
|
rigidMaster_(dict.lookup("rigidMaster")),
|
|
interpolationMethod_(dict.lookup("interpolationMethod")),
|
|
faceZoneMasterToSlaveInterpolator_(
|
|
cp_.mesh().faceZones()[cp_.mesh().faceZones().findZoneID(masterFaceZoneName_)](), // from
|
|
cp_.mesh().faceZones()[cp_.mesh().faceZones().findZoneID(slaveFaceZoneName_)](), // to zone
|
|
alg_,
|
|
dir_
|
|
),
|
|
faceZoneSlaveToMasterInterpolatorPtr_(NULL),
|
|
faceZoneGgiInterpolatorPtr_(NULL),
|
|
slaveInterpolator_(cp_.mesh().boundaryMesh()[slavePatch_.index()])
|
|
{
|
|
Info << "\tConstructing contact patch pair"
|
|
<< "\n\t\tmaster patch:\t" << masterPatch_.name()
|
|
<< "\n\t\tslave patch:\t" << slavePatch_.name()
|
|
<< endl;
|
|
|
|
if(rigidMaster_)
|
|
Info << "\t\tThe master surface is considered rigid and is set as traction-free" << endl;
|
|
|
|
//- Check interpolation scheme for passing tractions from slave to master
|
|
if(interpolationMethod_ == "patchToPatch")
|
|
{
|
|
Info << "\t\tMethod for interpolation of traction from slave to master: patchToPatch" << endl;
|
|
label masterFaceZoneID = cp_.mesh().faceZones().findZoneID(masterFaceZoneName_);
|
|
label slaveFaceZoneID = cp_.mesh().faceZones().findZoneID(slaveFaceZoneName_);
|
|
faceZoneSlaveToMasterInterpolatorPtr_ =
|
|
new zoneToZoneInterpolation
|
|
(
|
|
cp_.mesh().faceZones()[slaveFaceZoneID](), // from zone
|
|
cp_.mesh().faceZones()[masterFaceZoneID](), // to zone
|
|
alg_,
|
|
dir_
|
|
);
|
|
}
|
|
else if(interpolationMethod_ == "ggi")
|
|
{
|
|
Info << "\t\tMethod for interpolation of traction from slave to master: ggi" << endl;
|
|
label masterFaceZoneID = cp_.mesh().faceZones().findZoneID(masterFaceZoneName_);
|
|
label slaveFaceZoneID = cp_.mesh().faceZones().findZoneID(slaveFaceZoneName_);
|
|
faceZoneGgiInterpolatorPtr_ =
|
|
new ggiZoneInterpolation
|
|
(
|
|
cp_.mesh().faceZones()[masterFaceZoneID](), // master zone
|
|
cp_.mesh().faceZones()[slaveFaceZoneID](), // slave zone
|
|
tensorField(0),
|
|
tensorField(0),
|
|
vectorField(0),
|
|
0.0,
|
|
0.0,
|
|
true,
|
|
ggiInterpolation::AABB
|
|
);
|
|
}
|
|
else
|
|
{
|
|
SeriousError << "\n\nTraction interpolation method '"
|
|
<< interpolationMethod_ << "' not found!\n"
|
|
<< "\nValid interpolation methods are:\n"
|
|
<< "ggi\n"
|
|
<< "patchToPatch"
|
|
<< endl
|
|
<< exit(FatalError);
|
|
}
|
|
|
|
//- only the master should create a contactInfo file
|
|
if(Pstream::master())
|
|
{
|
|
contactFilePtr_ = new OFstream(name_);
|
|
OFstream& contactFile = *contactFilePtr_;
|
|
int width = 20;
|
|
contactFile << "Time";
|
|
contactFile.width(width);
|
|
contactFile << "ContactIter";
|
|
contactFile.width(width);
|
|
contactFile << "PenaltyScale";
|
|
contactFile.width(width);
|
|
contactFile << "slaveContactVer";
|
|
contactFile.width(width);
|
|
contactFile << "penetration";
|
|
contactFile.width(width);
|
|
contactFile << "slaveVerReduce";
|
|
contactFile.width(width);
|
|
contactFile << "maxSlaveTrac" << endl;
|
|
}
|
|
Info << "\tContact patch pair constructed" << endl;
|
|
}
|
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
|
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
|
|
|
|
Foam::tmp<Foam::scalarField>
|
|
Foam::contactPatchPair::masterTouchFraction() const
|
|
{
|
|
//--DOES NOT WORK IN PARALLEL YET BUT IS ONLY FOR VISUALISATION--/
|
|
|
|
const fvMesh& mesh = cp_.mesh();
|
|
|
|
scalarField pDistToInter(cp_.mesh().boundaryMesh()[masterPatch_.index()].size(), 0.0);
|
|
// = slaveToMasterInterpolateDeformed.pointDistanceToIntersection();
|
|
|
|
scalarField vertexMasterGap = pDistToInter;
|
|
|
|
// Calculate area in contact
|
|
const faceList& masterPatchLocalFaces =
|
|
mesh.boundaryMesh()[masterPatch_.index()].localFaces();
|
|
|
|
const pointField& masterPatchLocalPoints =
|
|
mesh.boundaryMesh()[masterPatch_.index()].localPoints();
|
|
|
|
tmp<scalarField> ttouchFrac
|
|
(
|
|
new scalarField(masterPatchLocalFaces.size(), 0)
|
|
);
|
|
scalarField& touchFrac = ttouchFrac();
|
|
|
|
forAll (masterPatchLocalFaces, faceI)
|
|
{
|
|
touchFrac[faceI] =
|
|
masterPatchLocalFaces[faceI].areaInContact
|
|
(
|
|
masterPatchLocalPoints,
|
|
vertexMasterGap
|
|
);
|
|
}
|
|
|
|
return ttouchFrac;
|
|
}
|
|
|
|
|
|
|
|
|
|
Foam::tmp<Foam::scalarField>
|
|
Foam::contactPatchPair::slaveTouchFraction() const
|
|
{
|
|
//--DOES NOT WORK IN PARALLEL YET BUT IS ONLY FOR VISUALISATION--/
|
|
|
|
const fvMesh& mesh = cp_.mesh();
|
|
|
|
scalarField vertexSlaveGap = slavePointPenetration_;
|
|
// (cp_.mesh().boundaryMesh()[slavePatch_.index()].size(), 0.0);
|
|
|
|
// Calculate area in contact
|
|
const faceList& slavePatchLocalFaces =
|
|
mesh.boundaryMesh()[slavePatch_.index()].localFaces();
|
|
|
|
const pointField& slavePatchLocalPoints =
|
|
mesh.boundaryMesh()[slavePatch_.index()].localPoints();
|
|
|
|
tmp<scalarField> ttouchFrac
|
|
(
|
|
new scalarField(slavePatchLocalFaces.size(), 0)
|
|
);
|
|
scalarField& touchFrac = ttouchFrac();
|
|
|
|
forAll (slavePatchLocalFaces, faceI)
|
|
{
|
|
touchFrac[faceI] =
|
|
slavePatchLocalFaces[faceI].areaInContact
|
|
(
|
|
slavePatchLocalPoints,
|
|
vertexSlaveGap
|
|
);
|
|
}
|
|
|
|
return ttouchFrac;
|
|
}
|
|
|
|
|
|
|
|
|
|
Foam::tmp<Foam::scalarField>
|
|
Foam::contactPatchPair::masterGapPoints() const
|
|
{
|
|
scalarField globalMasterPointPenetration
|
|
(
|
|
cp_.mesh().boundaryMesh()[masterPatch_.index()].meshPoints().size(),
|
|
0.0
|
|
);
|
|
|
|
scalarField vertexMasterGap = masterPointPenetration_;
|
|
//globalMasterPointPenetration;
|
|
|
|
tmp<scalarField> tcontactGapPoints
|
|
(
|
|
new scalarField(vertexMasterGap.size(), 0)
|
|
);
|
|
scalarField& contactGapPoints = tcontactGapPoints();
|
|
|
|
forAll (vertexMasterGap, pointI)
|
|
{
|
|
contactGapPoints[pointI] = vertexMasterGap[pointI];
|
|
}
|
|
|
|
return tcontactGapPoints;
|
|
}
|
|
|
|
|
|
|
|
|
|
Foam::tmp<Foam::scalarField>
|
|
Foam::contactPatchPair::slaveGapPoints() const
|
|
{
|
|
const scalarField& slavePointPenetration = slavePointPenetration_;
|
|
|
|
tmp<scalarField> tcontactGapPoints
|
|
(
|
|
new scalarField(slavePointPenetration.size(), 0)
|
|
);
|
|
scalarField& contactGapPoints = tcontactGapPoints();
|
|
|
|
forAll (slavePointPenetration, pointI)
|
|
{
|
|
contactGapPoints[pointI] = slavePointPenetration[pointI];
|
|
}
|
|
|
|
return tcontactGapPoints;
|
|
}
|
|
|
|
|
|
|
|
|
|
Foam::tmp<Foam::vectorField>
|
|
Foam::contactPatchPair::masterPointForce() const
|
|
{
|
|
//- returns zero at the moment
|
|
vectorField masterPointForce
|
|
(
|
|
cp_.mesh().boundaryMesh()[masterPatch_.index()].meshPoints().size(),
|
|
vector::zero
|
|
);
|
|
|
|
tmp<vectorField> tcontactPointForce
|
|
(
|
|
new vectorField(masterPointForce.size(), vector::zero)
|
|
);
|
|
vectorField& contactPointForce = tcontactPointForce();
|
|
|
|
forAll (contactPointForce, pointI)
|
|
{
|
|
contactPointForce[pointI] = masterPointForce[pointI];
|
|
}
|
|
|
|
return tcontactPointForce;
|
|
}
|
|
|
|
|
|
|
|
|
|
Foam::tmp<Foam::vectorField>
|
|
Foam::contactPatchPair::slavePointForce() const
|
|
{
|
|
vectorField slavePointForce = totalSlavePointForce_;
|
|
|
|
tmp<vectorField> tcontactPointForce
|
|
(
|
|
new vectorField(slavePointForce.size(), vector::zero)
|
|
);
|
|
|
|
vectorField& contactPointForce = tcontactPointForce();
|
|
|
|
forAll (contactPointForce, pointI)
|
|
{
|
|
contactPointForce[pointI] = slavePointForce[pointI];
|
|
}
|
|
|
|
return tcontactPointForce;
|
|
}
|
|
|
|
|
|
|
|
|
|
Foam::tmp<Foam::scalarField>
|
|
Foam::contactPatchPair::masterContactPressure() const
|
|
{
|
|
const fvMesh& mesh = cp_.mesh();
|
|
|
|
vectorField n = mesh.boundary()[masterPatch_.index()].nf();
|
|
|
|
const volSymmTensorField& sigma =
|
|
mesh.objectRegistry::lookupObject<volSymmTensorField>("sigma");
|
|
|
|
scalarField masterPressure
|
|
= n & (n & sigma.boundaryField()[masterPatch_.index()]);
|
|
|
|
tmp<scalarField> tcontactPressure
|
|
(
|
|
new scalarField(masterPressure.size(), 0)
|
|
);
|
|
scalarField& contactPressure = tcontactPressure();
|
|
|
|
forAll (masterPressure, faceI)
|
|
{
|
|
contactPressure[faceI] = max(-1*masterPressure[faceI],0);
|
|
}
|
|
|
|
return tcontactPressure;
|
|
}
|
|
|
|
|
|
|
|
|
|
Foam::tmp<Foam::scalarField>
|
|
Foam::contactPatchPair::slaveContactPressure() const
|
|
{
|
|
const fvMesh& mesh = cp_.mesh();
|
|
|
|
vectorField n = mesh.boundary()[slavePatch_.index()].nf();
|
|
|
|
const volSymmTensorField& sigma =
|
|
mesh.objectRegistry::lookupObject<volSymmTensorField>("sigma");
|
|
|
|
scalarField slavePressure
|
|
= n & (n & sigma.boundaryField()[slavePatch_.index()]);
|
|
|
|
tmp<scalarField> tcontactPressure
|
|
(
|
|
new scalarField(slavePressure.size(), 0)
|
|
);
|
|
scalarField& contactPressure = tcontactPressure();
|
|
|
|
forAll (slavePressure, faceI)
|
|
{
|
|
contactPressure[faceI] = max(-1*slavePressure[faceI],0);
|
|
}
|
|
|
|
return tcontactPressure;
|
|
}
|
|
|
|
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
|
|
|
|
|
// ************************************************************************* //
|