mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: integration of lumpedPointMotion
- This provides a mechanism for moving mesh patches based on external
input (eg, from an external structures solver). The patch points are
influenced by the position and rotation of the lumped points.
BC: lumpedPointDisplacementPointPatchVectorField
Controlling mechanisms:
- externalCoupler
for coordinating the master/slave
- lumpedPointMovement
manages the patch-points motion, but also for extracting forces/moments
- lumpedPointState
represents the positions/rotations of the controlling points
Utils:
- lumpedPointZones
diagnostic for visualizing the correspondence between controlling
points and patch faces
- lumpedPointMovement
Test that the patch motion is as desired without invoking moveMesh.
With the -slave option, return items from a precalculated table
for the lumpedPointDisplacementPointPatchVectorField BC.
This commit is contained in:
3
applications/test/externalCoupler/Make/files
Normal file
3
applications/test/externalCoupler/Make/files
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Test-externalCoupler.C
|
||||||
|
|
||||||
|
EXE = $(FOAM_USER_APPBIN)/Test-externalCoupler
|
||||||
7
applications/test/externalCoupler/Make/options
Normal file
7
applications/test/externalCoupler/Make/options
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/lumpedPointMotion/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-llumpedPointMotion
|
||||||
97
applications/test/externalCoupler/Test-externalCoupler.C
Normal file
97
applications/test/externalCoupler/Test-externalCoupler.C
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Application
|
||||||
|
Test-externalCoupler
|
||||||
|
|
||||||
|
Description
|
||||||
|
Test of master/slave communication etc.
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "argList.H"
|
||||||
|
#include "externalCoupler.H"
|
||||||
|
|
||||||
|
using namespace Foam;
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
// Main program:
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argList::noParallel();
|
||||||
|
argList::addOption("max", "N", "max number of calls (default: 1000)");
|
||||||
|
argList::addBoolOption("slave", "run as slave");
|
||||||
|
|
||||||
|
#include "setRootCase.H"
|
||||||
|
|
||||||
|
const label maxCount = args.optionLookupOrDefault<label>("max", 1000);
|
||||||
|
|
||||||
|
externalCoupler coupler;
|
||||||
|
|
||||||
|
if (args.optionFound("slave"))
|
||||||
|
{
|
||||||
|
const word role = "slave";
|
||||||
|
Info<< "Running as " << role << " max=" << maxCount << endl;
|
||||||
|
|
||||||
|
for (label count = 0; count < maxCount; ++count)
|
||||||
|
{
|
||||||
|
// Wait for master, but stop if status=done was seen
|
||||||
|
|
||||||
|
Info<< role << ": waiting for master" << endl;
|
||||||
|
if (!coupler.waitForMaster())
|
||||||
|
{
|
||||||
|
Info<< role << ": stopping. status=done was detected" << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< role << ": switch to master" << endl;
|
||||||
|
coupler.useMaster();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const word role = "master";
|
||||||
|
Info<< "Running as " << role << " max=" << maxCount << endl;
|
||||||
|
|
||||||
|
for (label count = 0; count < maxCount; ++count)
|
||||||
|
{
|
||||||
|
// Wait for slave, but stop if status=done was seen
|
||||||
|
|
||||||
|
Info<< role << ": waiting for slave" << endl;
|
||||||
|
if (!coupler.waitForSlave())
|
||||||
|
{
|
||||||
|
Info<< role << ": stopping. status=done was detected" << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< role << ": switch to slave" << endl;
|
||||||
|
coupler.useSlave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
lumpedPointForces.C
|
||||||
|
|
||||||
|
EXE = $(FOAM_APPBIN)/lumpedPointForces
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/fileFormats/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
|
-I$(LIB_SRC)/lumpedPointMotion/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-lmeshTools \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-llumpedPointMotion
|
||||||
@ -0,0 +1,177 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Application
|
||||||
|
lumpedPointForces
|
||||||
|
|
||||||
|
Description
|
||||||
|
Extract force/moment information from existing calculations based
|
||||||
|
on the segmentation of the pressure integration zones.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "argList.H"
|
||||||
|
#include "Time.H"
|
||||||
|
#include "timeSelector.H"
|
||||||
|
#include "volFields.H"
|
||||||
|
#include "IOobjectList.H"
|
||||||
|
|
||||||
|
#include "lumpedPointTools.H"
|
||||||
|
#include "lumpedPointIOMovement.H"
|
||||||
|
|
||||||
|
using namespace Foam;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class GeoFieldType>
|
||||||
|
autoPtr<GeoFieldType> loadField
|
||||||
|
(
|
||||||
|
const volMesh::Mesh& mesh,
|
||||||
|
const IOobject* io
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (io && io->headerClassName() == GeoFieldType::typeName)
|
||||||
|
{
|
||||||
|
Info<< "Reading " << GeoFieldType::typeName
|
||||||
|
<< ' ' << io->name() << endl;
|
||||||
|
|
||||||
|
return autoPtr<GeoFieldType>
|
||||||
|
(
|
||||||
|
new GeoFieldType
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
io->name(),
|
||||||
|
io->instance(),
|
||||||
|
io->local(),
|
||||||
|
io->db(),
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE,
|
||||||
|
io->registerObject()
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return autoPtr<GeoFieldType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argList::addNote
|
||||||
|
(
|
||||||
|
"Extract force/moment information from existing calculations based "
|
||||||
|
"on the lumpedPoints pressure zones."
|
||||||
|
);
|
||||||
|
|
||||||
|
argList::addBoolOption
|
||||||
|
(
|
||||||
|
"vtk",
|
||||||
|
"create visualization files of the forces"
|
||||||
|
);
|
||||||
|
|
||||||
|
timeSelector::addOptions(true, false);
|
||||||
|
argList::noFunctionObjects(); // Never use function objects
|
||||||
|
|
||||||
|
#include "addRegionOption.H"
|
||||||
|
#include "setRootCase.H"
|
||||||
|
|
||||||
|
const bool withVTK = args.optionFound("vtk");
|
||||||
|
|
||||||
|
#include "createTime.H"
|
||||||
|
instantList timeDirs = timeSelector::select0(runTime, args);
|
||||||
|
|
||||||
|
#include "createNamedMesh.H"
|
||||||
|
|
||||||
|
autoPtr<lumpedPointIOMovement> movement = lumpedPointIOMovement::New
|
||||||
|
(
|
||||||
|
runTime
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!movement.valid())
|
||||||
|
{
|
||||||
|
Info<< "no valid movement given" << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const labelList patchLst = lumpedPointTools::lumpedPointPatchList(mesh);
|
||||||
|
if (patchLst.empty())
|
||||||
|
{
|
||||||
|
Info<< "no patch list found" << endl;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
movement().setMapping(mesh, patchLst, lumpedPointTools::points0Field(mesh));
|
||||||
|
|
||||||
|
List<vector> forces, moments;
|
||||||
|
forAll(timeDirs, timei)
|
||||||
|
{
|
||||||
|
runTime.setTime(timeDirs[timei], timei);
|
||||||
|
|
||||||
|
Info<< "Time = " << runTime.timeName() << endl;
|
||||||
|
|
||||||
|
if (mesh.readUpdate())
|
||||||
|
{
|
||||||
|
Info<< " Read new mesh" << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for list of objects for this time
|
||||||
|
IOobjectList objects(mesh, runTime.timeName());
|
||||||
|
|
||||||
|
// Pressure field
|
||||||
|
autoPtr<volScalarField> pField
|
||||||
|
= loadField<volScalarField>(mesh, objects.lookup("p"));
|
||||||
|
|
||||||
|
// The forces per zone
|
||||||
|
if (movement().forcesAndMoments(mesh, forces, moments))
|
||||||
|
{
|
||||||
|
Info<<"forces per zone: " << forces << endl;
|
||||||
|
Info<<"moments per zone: " << moments << endl;
|
||||||
|
|
||||||
|
if (withVTK && Pstream::master())
|
||||||
|
{
|
||||||
|
const word outputName =
|
||||||
|
Foam::name("forces_%06d.vtp", runTime.timeIndex());
|
||||||
|
|
||||||
|
Info<<" " << outputName << endl;
|
||||||
|
|
||||||
|
movement().writeForcesAndMomentsVTP
|
||||||
|
(
|
||||||
|
outputName,
|
||||||
|
forces,
|
||||||
|
moments
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< "End\n" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
lumpedPointMovement.C
|
||||||
|
|
||||||
|
EXE = $(FOAM_APPBIN)/lumpedPointMovement
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/fileFormats/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
|
-I$(LIB_SRC)/lumpedPointMotion/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-lmeshTools \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-llumpedPointMotion
|
||||||
@ -0,0 +1,263 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Application
|
||||||
|
lumpedPointMovement
|
||||||
|
|
||||||
|
Description
|
||||||
|
Thus utility can be used to produce VTK files to visualize the response
|
||||||
|
points/rotations and the corresponding movement of the building surfaces.
|
||||||
|
Uses the tabulated responses from the specified file.
|
||||||
|
Optionally, it can also be used to a dummy responder for the
|
||||||
|
externalCoupler logic, which makes it useful as a debugging facility
|
||||||
|
as well demonstrating how an external application could communicate
|
||||||
|
with the lumpedPointMovement point-patch boundary condition.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "argList.H"
|
||||||
|
#include "Time.H"
|
||||||
|
#include "timeSelector.H"
|
||||||
|
|
||||||
|
#include "OFstream.H"
|
||||||
|
|
||||||
|
#include "lumpedPointTools.H"
|
||||||
|
#include "lumpedPointIOMovement.H"
|
||||||
|
|
||||||
|
using namespace Foam;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argList::addNote
|
||||||
|
(
|
||||||
|
"Visualize lumpedPoint movements or provide a slave responder "
|
||||||
|
"for diagnostic purposes."
|
||||||
|
);
|
||||||
|
|
||||||
|
argList::noParallel();
|
||||||
|
argList::noFunctionObjects(); // Never use function objects
|
||||||
|
argList::addOption
|
||||||
|
(
|
||||||
|
"max",
|
||||||
|
"N",
|
||||||
|
"maximum number of outputs"
|
||||||
|
);
|
||||||
|
argList::addOption
|
||||||
|
(
|
||||||
|
"span",
|
||||||
|
"N",
|
||||||
|
"increment each input by factor N (default: 1)"
|
||||||
|
);
|
||||||
|
argList::addOption
|
||||||
|
(
|
||||||
|
"scale",
|
||||||
|
"factor",
|
||||||
|
"relaxation/scaling factor for movement (default: 1)"
|
||||||
|
);
|
||||||
|
argList::addBoolOption
|
||||||
|
(
|
||||||
|
"removeLock",
|
||||||
|
"remove lock-file on termination of slave"
|
||||||
|
);
|
||||||
|
argList::addBoolOption
|
||||||
|
(
|
||||||
|
"slave",
|
||||||
|
"invoke as a slave responder for testing"
|
||||||
|
);
|
||||||
|
argList::validArgs.insert("responseFile");
|
||||||
|
|
||||||
|
#include "setRootCase.H"
|
||||||
|
|
||||||
|
const label maxOut =
|
||||||
|
Foam::max(0, args.optionLookupOrDefault<label>("max", 0));
|
||||||
|
|
||||||
|
const label span =
|
||||||
|
Foam::max(1, args.optionLookupOrDefault<label>("span", 1));
|
||||||
|
|
||||||
|
const scalar relax = args.optionLookupOrDefault<scalar>("scale", 1);
|
||||||
|
|
||||||
|
const bool slave = args.optionFound("slave");
|
||||||
|
const bool removeLock = args.optionFound("removeLock");
|
||||||
|
|
||||||
|
#include "createTime.H"
|
||||||
|
|
||||||
|
autoPtr<lumpedPointIOMovement> movement = lumpedPointIOMovement::New
|
||||||
|
(
|
||||||
|
runTime
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!movement.valid())
|
||||||
|
{
|
||||||
|
Info<< "no valid movement given" << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<lumpedPointStateTuple> responseTable =
|
||||||
|
lumpedPointTools::lumpedPointStates(args[1]);
|
||||||
|
|
||||||
|
Info<< "Using response table with " << responseTable.size()
|
||||||
|
<< " entries" << endl;
|
||||||
|
|
||||||
|
Info << "Increment input by " << span << nl;
|
||||||
|
|
||||||
|
if (maxOut)
|
||||||
|
{
|
||||||
|
Info<< "Stopping after " << maxOut << " outputs" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slave)
|
||||||
|
{
|
||||||
|
Info<< "Running as slave responder" << endl;
|
||||||
|
|
||||||
|
externalCoupler& coupler = movement().coupler();
|
||||||
|
|
||||||
|
label count = 0;
|
||||||
|
for (label index = 0; index < responseTable.size(); index += span)
|
||||||
|
{
|
||||||
|
Info<< args.executable() << ": waiting for master" << endl;
|
||||||
|
|
||||||
|
// Wait for master, but stop if status=done was seen
|
||||||
|
if (!coupler.waitForMaster())
|
||||||
|
{
|
||||||
|
Info<< args.executable()
|
||||||
|
<< ": stopping status=done was detected" << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lumpedPointState state = responseTable[index].second();
|
||||||
|
state.relax(relax, movement().state0());
|
||||||
|
|
||||||
|
// Generate input for OpenFOAM
|
||||||
|
OFstream os(coupler.resolveFile(movement().inputName()));
|
||||||
|
if
|
||||||
|
(
|
||||||
|
movement().inputFormat()
|
||||||
|
== lumpedPointState::inputFormatType::PLAIN
|
||||||
|
)
|
||||||
|
{
|
||||||
|
state.writePlain(os);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os.writeEntry("time", responseTable[index].first());
|
||||||
|
state.writeDict(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< args.executable()
|
||||||
|
<< ": updated to state " << index
|
||||||
|
<< " - switch to master"
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
// Let OpenFOAM know that it can continue
|
||||||
|
coupler.useMaster();
|
||||||
|
|
||||||
|
if (maxOut && ++count >= maxOut)
|
||||||
|
{
|
||||||
|
Info<< args.executable()
|
||||||
|
<<": stopping after " << maxOut << " outputs" << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeLock)
|
||||||
|
{
|
||||||
|
Info<< args.executable() <<": removing lock file" << endl;
|
||||||
|
coupler.useSlave(); // This removes the lock-file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
runTime.setTime(instant(0, runTime.constant()), 0);
|
||||||
|
|
||||||
|
#include "createNamedPolyMesh.H"
|
||||||
|
|
||||||
|
const labelList patchLst = lumpedPointTools::lumpedPointPatchList(mesh);
|
||||||
|
if (patchLst.empty())
|
||||||
|
{
|
||||||
|
Info<< "no patch list found" << endl;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointIOField points0 = lumpedPointTools::points0Field(mesh);
|
||||||
|
movement().setBoundBox(mesh, patchLst, points0);
|
||||||
|
|
||||||
|
label index = 0;
|
||||||
|
|
||||||
|
// Initial geometry
|
||||||
|
movement().writeVTP("geom_init.vtp", mesh, patchLst, points0);
|
||||||
|
|
||||||
|
forAll(responseTable, i)
|
||||||
|
{
|
||||||
|
const bool output = ((i % span) == 0);
|
||||||
|
lumpedPointState state = responseTable[i].second();
|
||||||
|
state.relax(relax, movement().state0());
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
{
|
||||||
|
Info<<"output [" << i << "/"
|
||||||
|
<< responseTable.size() << "]" << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// State/response = what comes back from FEM
|
||||||
|
{
|
||||||
|
const word outputName = Foam::name("state_%06d.vtp", index);
|
||||||
|
Info<<" " << outputName << endl;
|
||||||
|
|
||||||
|
state.writeVTP(outputName, movement().axis());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const word outputName = Foam::name("geom_%06d.vtp", index);
|
||||||
|
Info<<" " << outputName << endl;
|
||||||
|
|
||||||
|
movement().writeVTP(outputName, state, mesh, patchLst, points0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
++index;
|
||||||
|
|
||||||
|
bool canOutput = !maxOut || (index <= maxOut);
|
||||||
|
if (!canOutput)
|
||||||
|
{
|
||||||
|
Info<<"stopping output after "
|
||||||
|
<< maxOut << " outputs" << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< args.executable() << ": End\n" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
lumpedPointZones.C
|
||||||
|
|
||||||
|
EXE = $(FOAM_APPBIN)/lumpedPointZones
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/fileFormats/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
|
-I$(LIB_SRC)/lumpedPointMotion/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-lmeshTools \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-llumpedPointMotion
|
||||||
@ -0,0 +1,107 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Application
|
||||||
|
lumpedPointZones
|
||||||
|
|
||||||
|
Description
|
||||||
|
Produces a VTK PolyData file \c lumpedPointZones.vtp in which the
|
||||||
|
segmentation of the pressure integration zones can be visualized
|
||||||
|
for diagnostic purposes. Does not use external coupling.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "argList.H"
|
||||||
|
#include "Time.H"
|
||||||
|
#include "timeSelector.H"
|
||||||
|
|
||||||
|
#include "lumpedPointTools.H"
|
||||||
|
#include "lumpedPointIOMovement.H"
|
||||||
|
|
||||||
|
using namespace Foam;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argList::addNote
|
||||||
|
(
|
||||||
|
"Create lumpedPointZones.vtp to verify the segmentation of "
|
||||||
|
"pressure integration zones used by lumpedPoint BC."
|
||||||
|
);
|
||||||
|
argList::noParallel(); // The VTP writer is not yet in parallel
|
||||||
|
|
||||||
|
argList::noFunctionObjects(); // Never use function objects
|
||||||
|
argList::addBoolOption
|
||||||
|
(
|
||||||
|
"verbose",
|
||||||
|
"increased verbosity"
|
||||||
|
);
|
||||||
|
|
||||||
|
#include "addRegionOption.H"
|
||||||
|
#include "setRootCase.H"
|
||||||
|
|
||||||
|
// const bool verbose = args.optionFound("verbose");
|
||||||
|
|
||||||
|
#include "createTime.H"
|
||||||
|
|
||||||
|
runTime.setTime(instant(0, runTime.constant()), 0);
|
||||||
|
|
||||||
|
#include "createNamedPolyMesh.H"
|
||||||
|
|
||||||
|
autoPtr<lumpedPointIOMovement> movement = lumpedPointIOMovement::New
|
||||||
|
(
|
||||||
|
runTime
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!movement.valid())
|
||||||
|
{
|
||||||
|
Info<< "no valid movement found" << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const labelList patchLst = lumpedPointTools::lumpedPointPatchList(mesh);
|
||||||
|
if (patchLst.empty())
|
||||||
|
{
|
||||||
|
Info<< "no patch list found" << endl;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointIOField points0 = lumpedPointTools::points0Field(mesh);
|
||||||
|
movement().setMapping(mesh, patchLst, points0);
|
||||||
|
|
||||||
|
// Initial geometry, but with zone colouring
|
||||||
|
movement().writeZonesVTP("lumpedPointZones.vtp", mesh, points0);
|
||||||
|
|
||||||
|
// Initial positions/rotations
|
||||||
|
movement().writeStateVTP("initialState.vtp");
|
||||||
|
|
||||||
|
Info<< nl
|
||||||
|
<< "wrote 'lumpedPointZones.vtp'" << nl
|
||||||
|
<< "wrote 'initialState.vtp'" << nl
|
||||||
|
<< "End\n" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -76,6 +76,7 @@ wmake $targetType regionCoupled
|
|||||||
|
|
||||||
functionObjects/Allwmake $targetType $*
|
functionObjects/Allwmake $targetType $*
|
||||||
|
|
||||||
|
wmake $targetType lumpedPointMotion
|
||||||
wmake $targetType sixDoFRigidBodyMotion
|
wmake $targetType sixDoFRigidBodyMotion
|
||||||
wmake $targetType rigidBodyDynamics
|
wmake $targetType rigidBodyDynamics
|
||||||
wmake $targetType rigidBodyMeshMotion
|
wmake $targetType rigidBodyMeshMotion
|
||||||
|
|||||||
13
src/lumpedPointMotion/Make/files
Normal file
13
src/lumpedPointMotion/Make/files
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
externalCoupler.C
|
||||||
|
|
||||||
|
lumpedPointMovement.C
|
||||||
|
lumpedPointMovementWriter.C
|
||||||
|
lumpedPointState.C
|
||||||
|
lumpedPointStateWriter.C
|
||||||
|
lumpedPointIOMovement.C
|
||||||
|
|
||||||
|
lumpedPointDisplacementPointPatchVectorField.C
|
||||||
|
|
||||||
|
lumpedPointTools.C
|
||||||
|
|
||||||
|
LIB = $(FOAM_LIBBIN)/liblumpedPointMotion
|
||||||
10
src/lumpedPointMotion/Make/options
Normal file
10
src/lumpedPointMotion/Make/options
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
||||||
|
-I$(LIB_SRC)/fileFormats/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude
|
||||||
|
|
||||||
|
LIB_LIBS = \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-ldynamicMesh \
|
||||||
|
-lmeshTools
|
||||||
309
src/lumpedPointMotion/externalCoupler.C
Normal file
309
src/lumpedPointMotion/externalCoupler.C
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2015-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "externalCoupler.H"
|
||||||
|
#include "Pstream.H"
|
||||||
|
#include "PstreamReduceOps.H"
|
||||||
|
#include "OSspecific.H"
|
||||||
|
#include "IFstream.H"
|
||||||
|
#include "OFstream.H"
|
||||||
|
#include "Switch.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(externalCoupler, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Foam::word Foam::externalCoupler::lockName = "OpenFOAM";
|
||||||
|
|
||||||
|
|
||||||
|
// file-scope
|
||||||
|
// check file (must exist) for "status=done" content
|
||||||
|
static bool checkIsDone(const std::string& lck)
|
||||||
|
{
|
||||||
|
std::string content;
|
||||||
|
std::ifstream is(lck.c_str());
|
||||||
|
is >> content;
|
||||||
|
|
||||||
|
return (content.find("done") != std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::fileName& Foam::externalCoupler::baseDir() const
|
||||||
|
{
|
||||||
|
return commsDir_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileName Foam::externalCoupler::lockFile() const
|
||||||
|
{
|
||||||
|
return resolveFile(lockName + ".lock");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::externalCoupler::externalCoupler()
|
||||||
|
:
|
||||||
|
runState_(NONE),
|
||||||
|
commsDir_("$FOAM_CASE/comms"),
|
||||||
|
waitInterval_(1u),
|
||||||
|
timeOut_(100u),
|
||||||
|
slaveFirst_(false),
|
||||||
|
log(false)
|
||||||
|
{
|
||||||
|
commsDir_.expand();
|
||||||
|
commsDir_.clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::externalCoupler::externalCoupler(const dictionary& dict)
|
||||||
|
:
|
||||||
|
externalCoupler()
|
||||||
|
{
|
||||||
|
readDict(dict);
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
mkDir(baseDir());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::externalCoupler::~externalCoupler()
|
||||||
|
{
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::externalCoupler::readDict(const dictionary& dict)
|
||||||
|
{
|
||||||
|
// Normally cannot change directory or initialization
|
||||||
|
// if things have already been initialized
|
||||||
|
dict.lookup("commsDir") >> commsDir_;
|
||||||
|
commsDir_.expand();
|
||||||
|
commsDir_.clean();
|
||||||
|
slaveFirst_ = dict.lookupOrDefault<bool>("initByExternal", false);
|
||||||
|
|
||||||
|
waitInterval_ = dict.lookupOrDefault("waitInterval", 1u);
|
||||||
|
if (!waitInterval_)
|
||||||
|
{
|
||||||
|
// Enforce non-zero sleep
|
||||||
|
waitInterval_ = 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeOut_ = dict.lookupOrDefault("timeOut", 100*waitInterval_);
|
||||||
|
|
||||||
|
log = dict.lookupOrDefault<bool>("log", false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::externalCoupler::initialized() const
|
||||||
|
{
|
||||||
|
return runState_ != NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::externalCoupler::slaveFirst() const
|
||||||
|
{
|
||||||
|
return slaveFirst_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::externalCoupler::useMaster(const bool wait) const
|
||||||
|
{
|
||||||
|
const bool wasInit = initialized();
|
||||||
|
runState_ = MASTER;
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
if (!wasInit)
|
||||||
|
{
|
||||||
|
// First time
|
||||||
|
Foam::mkDir(commsDir_);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileName lck(lockFile());
|
||||||
|
|
||||||
|
// Create lock file - only if it doesn't already exist
|
||||||
|
if (!Foam::isFile(lck))
|
||||||
|
{
|
||||||
|
Log << type() << ": creating lock file" << endl;
|
||||||
|
|
||||||
|
OFstream os(lck);
|
||||||
|
os << "status=openfoam\n";
|
||||||
|
os.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait)
|
||||||
|
{
|
||||||
|
waitForMaster();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::externalCoupler::useSlave(const bool wait) const
|
||||||
|
{
|
||||||
|
const bool wasInit = initialized();
|
||||||
|
runState_ = SLAVE;
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
if (!wasInit)
|
||||||
|
{
|
||||||
|
// First time
|
||||||
|
Foam::mkDir(commsDir_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log << type() << ": removing lock file" << endl;
|
||||||
|
|
||||||
|
Foam::rm(lockFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait)
|
||||||
|
{
|
||||||
|
waitForSlave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::externalCoupler::waitForMaster() const
|
||||||
|
{
|
||||||
|
if (!initialized())
|
||||||
|
{
|
||||||
|
useMaster(); // was not initialized
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDone = false;
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
const fileName lck(lockFile());
|
||||||
|
|
||||||
|
double prevTime = -1;
|
||||||
|
double modTime = 0;
|
||||||
|
|
||||||
|
// Wait until file disappears (modTime == 0)
|
||||||
|
// But also check for status=done content in the file
|
||||||
|
while ((modTime = highResLastModified(lck)) > 0)
|
||||||
|
{
|
||||||
|
if (prevTime < modTime)
|
||||||
|
{
|
||||||
|
prevTime = modTime;
|
||||||
|
isDone = checkIsDone(lck);
|
||||||
|
if (isDone)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sleep(waitInterval_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MPI barrier
|
||||||
|
Pstream::scatter(isDone);
|
||||||
|
|
||||||
|
return !isDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::externalCoupler::waitForSlave() const
|
||||||
|
{
|
||||||
|
if (!initialized())
|
||||||
|
{
|
||||||
|
useSlave(); // was not initialized
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDone = false;
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
const fileName lck(lockFile());
|
||||||
|
unsigned totalTime = 0;
|
||||||
|
|
||||||
|
Log << type() << ": waiting for lock file to appear " << lck << endl;
|
||||||
|
|
||||||
|
while (!Foam::isFile(lck))
|
||||||
|
{
|
||||||
|
sleep(waitInterval_);
|
||||||
|
|
||||||
|
if (timeOut_ && (totalTime += waitInterval_) > timeOut_)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Wait time exceeded timeout of " << timeOut_
|
||||||
|
<< " s" << abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log << type() << ": wait time = " << totalTime << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// But check for status=done content in the file
|
||||||
|
isDone = checkIsDone(lck);
|
||||||
|
|
||||||
|
Log << type() << ": found lock file " << lck << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MPI barrier
|
||||||
|
Pstream::scatter(isDone);
|
||||||
|
|
||||||
|
return !isDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::fileName Foam::externalCoupler::resolveFile
|
||||||
|
(
|
||||||
|
const word& file
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return fileName(baseDir()/file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::externalCoupler::shutdown() const
|
||||||
|
{
|
||||||
|
if (Pstream::master() && runState_ == MASTER && Foam::isDir(commsDir_))
|
||||||
|
{
|
||||||
|
const fileName lck(lockFile());
|
||||||
|
|
||||||
|
Log << type() << ": lock file status=done" << endl;
|
||||||
|
OFstream os(lck);
|
||||||
|
os << "status=done\n";
|
||||||
|
os.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
runState_ = DONE; // Avoid re-triggering in destructor
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
207
src/lumpedPointMotion/externalCoupler.H
Normal file
207
src/lumpedPointMotion/externalCoupler.H
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2015-2017 OpenCFD Ltd.
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify i
|
||||||
|
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.
|
||||||
|
|
||||||
|
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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::externalCoupler
|
||||||
|
|
||||||
|
Description
|
||||||
|
Encapsulates the logic for coordinating between OpenFOAM and an
|
||||||
|
external application.
|
||||||
|
|
||||||
|
This class provides a simple interface for explicit coupling with an
|
||||||
|
external application using plain text files located in the user-specified
|
||||||
|
communications directory.
|
||||||
|
These files are to be read/written on the master processor only.
|
||||||
|
|
||||||
|
The explicit coupling follows a master/slave model in which OpenFOAM
|
||||||
|
is the 'master' and the external application is the 'slave'.
|
||||||
|
The readiness to exchange information in either direction is handled
|
||||||
|
by a lock file (ie, OpenFOAM.lock).
|
||||||
|
If the lock file is present, the slave (external application) should wait
|
||||||
|
for the master (OpenFOAM) to complete.
|
||||||
|
|
||||||
|
When the master is finished its tasks and has prepared data for
|
||||||
|
the slave, the lock file is removed, instructing the external
|
||||||
|
source to take control of the program execution.
|
||||||
|
|
||||||
|
When the slave has completed its tasks, it will reinstate the lock file.
|
||||||
|
|
||||||
|
Example of the communication specification:
|
||||||
|
\verbatim
|
||||||
|
communication
|
||||||
|
{
|
||||||
|
commsDir "${FOAM_CASE}/comms";
|
||||||
|
waitInterval 1;
|
||||||
|
timeOut 100;
|
||||||
|
initByExternal no;
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
externalCoupler.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef externalCoupler_H
|
||||||
|
#define externalCoupler_H
|
||||||
|
|
||||||
|
#include "fileName.H"
|
||||||
|
#include "dictionary.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class externalCoupler Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class externalCoupler
|
||||||
|
{
|
||||||
|
//- The run state (ie, who is currently in charge)
|
||||||
|
enum runState
|
||||||
|
{
|
||||||
|
NONE, //!< Not initialized
|
||||||
|
MASTER, //!< The master (OpenFOAM) is in charge
|
||||||
|
SLAVE, //!< The slave (external program) is in charge
|
||||||
|
DONE //!< Finished
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- The current run (and initialization) state
|
||||||
|
mutable runState runState_;
|
||||||
|
|
||||||
|
//- Local path to communications directory
|
||||||
|
fileName commsDir_;
|
||||||
|
|
||||||
|
//- Interval time between checking for return data [s]
|
||||||
|
unsigned waitInterval_;
|
||||||
|
|
||||||
|
//- Timeout [s] while waiting for the external application
|
||||||
|
unsigned timeOut_;
|
||||||
|
|
||||||
|
//- Flag to indicate values are initialized by external application
|
||||||
|
bool slaveFirst_;
|
||||||
|
|
||||||
|
//- Local logging/verbosity flag
|
||||||
|
bool log;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Return the file path to the base communications directory
|
||||||
|
const fileName& baseDir() const;
|
||||||
|
|
||||||
|
//- Return the file path to the lock file
|
||||||
|
fileName lockFile() const;
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construc
|
||||||
|
externalCoupler(const externalCoupler&) = delete;
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignmen
|
||||||
|
void operator=(const externalCoupler&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("externalCoupler");
|
||||||
|
|
||||||
|
|
||||||
|
// Static data members
|
||||||
|
|
||||||
|
//- Name of the lock file
|
||||||
|
static word lockName;
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct null using standard defaults
|
||||||
|
externalCoupler();
|
||||||
|
|
||||||
|
//- Construct from dictionary
|
||||||
|
externalCoupler(const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~externalCoupler();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//- True if state has been initialized
|
||||||
|
bool initialized() const;
|
||||||
|
|
||||||
|
//- External application provides initial values
|
||||||
|
bool slaveFirst() const;
|
||||||
|
|
||||||
|
//- Create lock file to indicate that OpenFOAM is in charge
|
||||||
|
// Optionally wait for master as well.
|
||||||
|
void useMaster(const bool wait=false) const;
|
||||||
|
|
||||||
|
//- Wait for indication that OpenFOAM has supplied output.
|
||||||
|
// This is when the lock file disappears, or it exists but with
|
||||||
|
// "status=done" content.
|
||||||
|
// \return False if lock file contains "status=done"
|
||||||
|
bool waitForMaster() const;
|
||||||
|
|
||||||
|
//- Remove lock file to indicate that the external program is in charge
|
||||||
|
// Optionally wait for slave as well.
|
||||||
|
void useSlave(const bool wait=false) const;
|
||||||
|
|
||||||
|
//- Wait for indication that the external program has supplied input.
|
||||||
|
// This is when the lock file appears.
|
||||||
|
// \return False if lock file contains "status=done"
|
||||||
|
bool waitForSlave() const;
|
||||||
|
|
||||||
|
//- Return the file path in the communications directory
|
||||||
|
fileName resolveFile(const word& file) const;
|
||||||
|
|
||||||
|
//- Generate status=done in lock (only when run-state = master)
|
||||||
|
void shutdown() const;
|
||||||
|
|
||||||
|
//- Remove files written by OpenFOAM
|
||||||
|
void removeDirectory() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Edit
|
||||||
|
|
||||||
|
//- Read communication settings from dictionary
|
||||||
|
bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,285 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "lumpedPointDisplacementPointPatchVectorField.H"
|
||||||
|
#include "lumpedPointMovement.H"
|
||||||
|
#include "lumpedPointIOMovement.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "pointFields.H"
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
#include "volFields.H"
|
||||||
|
#include "Time.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "displacementMotionSolver.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
makePointPatchTypeField
|
||||||
|
(
|
||||||
|
pointPatchVectorField,
|
||||||
|
lumpedPointDisplacementPointPatchVectorField
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::labelList
|
||||||
|
Foam::lumpedPointDisplacementPointPatchVectorField::patchIds
|
||||||
|
(
|
||||||
|
const pointVectorField& pvf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const pointVectorField::Boundary& bf = pvf.boundaryField();
|
||||||
|
|
||||||
|
DynamicList<label> patchLst(bf.size());
|
||||||
|
forAll(bf, patchi)
|
||||||
|
{
|
||||||
|
// All patches of this type
|
||||||
|
if (isA<patchType>(bf[patchi]))
|
||||||
|
{
|
||||||
|
patchLst.append(patchi);
|
||||||
|
// or patchLst.append(bf[patchi].patch().index());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return patchLst.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::pointField&
|
||||||
|
Foam::lumpedPointDisplacementPointPatchVectorField::points0() const
|
||||||
|
{
|
||||||
|
const objectRegistry& obr = this->patch().boundaryMesh().mesh().db();
|
||||||
|
|
||||||
|
// Obtain starting locations from the motionSolver
|
||||||
|
return obr.lookupObject<displacementMotionSolver>
|
||||||
|
(
|
||||||
|
"dynamicMeshDict"
|
||||||
|
).points0();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::lumpedPointMovement&
|
||||||
|
Foam::lumpedPointDisplacementPointPatchVectorField::movement() const
|
||||||
|
{
|
||||||
|
const objectRegistry& obr = this->patch().boundaryMesh().mesh().db();
|
||||||
|
const lumpedPointIOMovement* ptr =
|
||||||
|
lumpedPointIOMovement::lookupInRegistry(obr);
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
return *ptr; // Already exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// create and register with this patch as the owner
|
||||||
|
autoPtr<lumpedPointIOMovement> obj = lumpedPointIOMovement::New
|
||||||
|
(
|
||||||
|
obr,
|
||||||
|
this->patch().index()
|
||||||
|
);
|
||||||
|
|
||||||
|
return objectRegistry::store(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::lumpedPointDisplacementPointPatchVectorField::
|
||||||
|
lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
const pointPatch& p,
|
||||||
|
const DimensionedField<vector, pointMesh>& iF
|
||||||
|
)
|
||||||
|
:
|
||||||
|
fixedValuePointPatchField<vector>(p, iF)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::lumpedPointDisplacementPointPatchVectorField::
|
||||||
|
lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
const pointPatch& p,
|
||||||
|
const DimensionedField<vector, pointMesh>& iF,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
fixedValuePointPatchField<vector>(p, iF, dict)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::lumpedPointDisplacementPointPatchVectorField::
|
||||||
|
lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
const lumpedPointDisplacementPointPatchVectorField& pf,
|
||||||
|
const pointPatch& p,
|
||||||
|
const DimensionedField<vector, pointMesh>& iF,
|
||||||
|
const pointPatchFieldMapper& mapper
|
||||||
|
)
|
||||||
|
:
|
||||||
|
fixedValuePointPatchField<vector>(pf, p, iF, mapper)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::lumpedPointDisplacementPointPatchVectorField::
|
||||||
|
lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
const lumpedPointDisplacementPointPatchVectorField& pf,
|
||||||
|
const DimensionedField<vector, pointMesh>& iF
|
||||||
|
)
|
||||||
|
:
|
||||||
|
fixedValuePointPatchField<vector>(pf, iF)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::lumpedPointDisplacementPointPatchVectorField::
|
||||||
|
~lumpedPointDisplacementPointPatchVectorField()
|
||||||
|
{
|
||||||
|
// de-register movement if in use and managed by this patch
|
||||||
|
const lumpedPointIOMovement* ptr = lumpedPointIOMovement::lookupInRegistry
|
||||||
|
(
|
||||||
|
this->patch().boundaryMesh().mesh().db()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ptr && ptr->ownerId() == this->patch().index())
|
||||||
|
{
|
||||||
|
movement().coupler().shutdown();
|
||||||
|
|
||||||
|
const_cast<lumpedPointIOMovement*>(ptr)->checkOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::lumpedPointDisplacementPointPatchVectorField::updateCoeffs()
|
||||||
|
{
|
||||||
|
if (this->updated())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool masterPatch = (movement().ownerId() == this->patch().index());
|
||||||
|
if (masterPatch)
|
||||||
|
{
|
||||||
|
if (lumpedPointIOMovement::debug)
|
||||||
|
{
|
||||||
|
Pout<<"masterPatch: " << this->patch().index() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const polyMesh& mesh = this->patch().boundaryMesh().mesh().mesh();
|
||||||
|
|
||||||
|
// need face 'zones' for calculating forces
|
||||||
|
// likely need bounding box for the movement
|
||||||
|
// -> do both now if required
|
||||||
|
if (!movement().hasMapping())
|
||||||
|
{
|
||||||
|
const_cast<lumpedPointMovement&>(movement()).setMapping
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
// All patches of this type
|
||||||
|
patchIds
|
||||||
|
(
|
||||||
|
static_cast<const pointVectorField&>
|
||||||
|
(
|
||||||
|
this->internalField()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
this->points0()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
movement().coupler().initialized()
|
||||||
|
|| !movement().coupler().slaveFirst()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Synchronized for all processes
|
||||||
|
List<vector> forces, moments;
|
||||||
|
movement().forcesAndMoments(mesh, forces, moments);
|
||||||
|
|
||||||
|
if (lumpedPointIOMovement::debug)
|
||||||
|
{
|
||||||
|
Pout<<"gatherForces: " << forces << " called from patch "
|
||||||
|
<< this->patch().index() << endl;
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
Pout<<"output forces to file: "
|
||||||
|
<< movement().locations() << " called from patch "
|
||||||
|
<< this->patch().index() << nl
|
||||||
|
<<"# " << forces.size() << " force entries" << nl
|
||||||
|
<<"# fx fy fz" << nl
|
||||||
|
<<"output forces to file: "
|
||||||
|
<< forces << " called from patch "
|
||||||
|
<< this->patch().index() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
movement().writeData(forces, moments);
|
||||||
|
|
||||||
|
// signal external source to execute
|
||||||
|
movement().coupler().useSlave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for slave to provide data - includes MPI barrier
|
||||||
|
movement().coupler().waitForSlave();
|
||||||
|
|
||||||
|
// Read data passed back from external source - includes MPI barrier
|
||||||
|
const_cast<lumpedPointMovement&>(movement()).readState();
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp<pointField> tdisp = movement().displacePoints
|
||||||
|
(
|
||||||
|
this->points0(),
|
||||||
|
this->patch().meshPoints()
|
||||||
|
);
|
||||||
|
|
||||||
|
this->operator==(tdisp);
|
||||||
|
|
||||||
|
fixedValuePointPatchField<vector>::updateCoeffs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointDisplacementPointPatchVectorField::write(Ostream& os)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
pointPatchField<vector>::write(os);
|
||||||
|
writeEntry("value", os);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,200 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::lumpedPointDisplacementPointPatchVectorField
|
||||||
|
|
||||||
|
Description
|
||||||
|
|
||||||
|
Interpolates pre-specified motion with motion specified as
|
||||||
|
pointVectorFields.
|
||||||
|
|
||||||
|
This is the point-patch responsible for managing the force
|
||||||
|
integration on a 'lumped-point' basis, waiting for the external
|
||||||
|
application, reading back the response from the external program
|
||||||
|
and updating the locations of the associated patch points
|
||||||
|
accordingly.
|
||||||
|
|
||||||
|
The internal patch type name is 'lumpedPointDisplacement'.
|
||||||
|
|
||||||
|
\heading Patch usage
|
||||||
|
|
||||||
|
Example:
|
||||||
|
\verbatim
|
||||||
|
walls
|
||||||
|
{
|
||||||
|
type lumpedPointDisplacement;
|
||||||
|
value uniform (0 0 0);
|
||||||
|
fieldName wantedDisplacement;
|
||||||
|
interpolationScheme linear;
|
||||||
|
}
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
This will scan the case for \a wantedDisplacement pointVectorFields
|
||||||
|
and interpolate those in time (using \c linear interpolation) to
|
||||||
|
obtain the current displacement.
|
||||||
|
The advantage of specifying displacement in this way is that it
|
||||||
|
automatically works through decomposePar.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
lumpedPointDisplacementPointPatchVectorField.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef lumpedPointDisplacementPointPatchVectorField_H
|
||||||
|
#define lumpedPointDisplacementPointPatchVectorField_H
|
||||||
|
|
||||||
|
#include "fixedValuePointPatchField.H"
|
||||||
|
#include "lumpedPointMovement.H"
|
||||||
|
#include "lumpedPointState.H"
|
||||||
|
#include "lumpedPointIOMovement.H"
|
||||||
|
#include "labelList.H"
|
||||||
|
#include "tmp.H"
|
||||||
|
#include "pointField.H"
|
||||||
|
#include "pointFieldsFwd.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
class interpolationWeights;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class lumpedPointDisplacementPointPatchVectorField Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class lumpedPointDisplacementPointPatchVectorField
|
||||||
|
:
|
||||||
|
public fixedValuePointPatchField<vector>
|
||||||
|
{
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- Convenience typedefs
|
||||||
|
typedef lumpedPointDisplacementPointPatchVectorField patchType;
|
||||||
|
typedef DimensionedField<vector, pointMesh> fieldType;
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
//- The starting locations (obtained from the motionSolver).
|
||||||
|
const pointField& points0() const;
|
||||||
|
|
||||||
|
//- The auto-vivifying singleton for movement.
|
||||||
|
const lumpedPointMovement& movement() const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("lumpedPointDisplacement");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from patch and internal field
|
||||||
|
lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
const pointPatch& p,
|
||||||
|
const DimensionedField<vector, pointMesh>& iF
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from patch, internal field and dictionary
|
||||||
|
lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
const pointPatch& p,
|
||||||
|
const DimensionedField<vector, pointMesh>& iF,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct by mapping given patchField<vector> onto a new patch
|
||||||
|
lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
const lumpedPointDisplacementPointPatchVectorField& pf,
|
||||||
|
const pointPatch& p,
|
||||||
|
const DimensionedField<vector, pointMesh>& iF,
|
||||||
|
const pointPatchFieldMapper& mapper
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct and return a clone
|
||||||
|
virtual autoPtr<pointPatchField<vector>> clone() const
|
||||||
|
{
|
||||||
|
return autoPtr<pointPatchField<vector>>
|
||||||
|
(
|
||||||
|
new lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
*this
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Construct as copy setting internal field reference
|
||||||
|
lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
const lumpedPointDisplacementPointPatchVectorField& pf,
|
||||||
|
const DimensionedField<vector, pointMesh>& iF
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct and return a clone setting internal field reference
|
||||||
|
virtual autoPtr<pointPatchField<vector>> clone
|
||||||
|
(
|
||||||
|
const DimensionedField<vector, pointMesh>& iF
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return autoPtr<pointPatchField<vector>>
|
||||||
|
(
|
||||||
|
new lumpedPointDisplacementPointPatchVectorField
|
||||||
|
(
|
||||||
|
*this,
|
||||||
|
iF
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~lumpedPointDisplacementPointPatchVectorField();
|
||||||
|
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
|
||||||
|
//- The ids for all patches of this type
|
||||||
|
static labelList patchIds(const pointVectorField& pvf);
|
||||||
|
|
||||||
|
//- Update the coefficients associated with the patch field
|
||||||
|
virtual void updateCoeffs();
|
||||||
|
|
||||||
|
//- Write
|
||||||
|
virtual void write(Ostream&) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
142
src/lumpedPointMotion/lumpedPointIOMovement.C
Normal file
142
src/lumpedPointMotion/lumpedPointIOMovement.C
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "lumpedPointIOMovement.H"
|
||||||
|
#include "Time.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(lumpedPointIOMovement, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::lumpedPointIOMovement*
|
||||||
|
Foam::lumpedPointIOMovement::lookupInRegistry(const objectRegistry& obr)
|
||||||
|
{
|
||||||
|
return obr.lookupObjectPtr<lumpedPointIOMovement>
|
||||||
|
(
|
||||||
|
lumpedPointMovement::dictionaryName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::autoPtr<Foam::lumpedPointIOMovement>
|
||||||
|
Foam::lumpedPointIOMovement::New
|
||||||
|
(
|
||||||
|
const objectRegistry& obr,
|
||||||
|
label ownerId
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return autoPtr<lumpedPointIOMovement>
|
||||||
|
(
|
||||||
|
new lumpedPointIOMovement
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
lumpedPointMovement::dictionaryName,
|
||||||
|
obr.time().caseSystem(),
|
||||||
|
obr,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
true // register object
|
||||||
|
),
|
||||||
|
ownerId // tag this patch as owner too
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::lumpedPointIOMovement::lumpedPointIOMovement
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
label ownerId
|
||||||
|
)
|
||||||
|
:
|
||||||
|
lumpedPointMovement(),
|
||||||
|
regIOobject(io)
|
||||||
|
{
|
||||||
|
bool ok =
|
||||||
|
(
|
||||||
|
readOpt() == IOobject::MUST_READ
|
||||||
|
|| readOpt() == IOobject::MUST_READ_IF_MODIFIED
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
ok = readData(readStream(typeName));
|
||||||
|
close();
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
this->ownerId(ownerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::lumpedPointIOMovement::~lumpedPointIOMovement()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointIOMovement::readData(Istream& is)
|
||||||
|
{
|
||||||
|
dictionary dict(is);
|
||||||
|
|
||||||
|
readDict(dict);
|
||||||
|
|
||||||
|
return is.check(FUNCTION_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointIOMovement::writeData(Ostream& os) const
|
||||||
|
{
|
||||||
|
os << *this;
|
||||||
|
return os.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::Ostream& Foam::operator<<(Ostream& os, const lumpedPointIOMovement& obj)
|
||||||
|
{
|
||||||
|
obj.writeDict(os);
|
||||||
|
|
||||||
|
os.check(FUNCTION_NAME);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
133
src/lumpedPointMotion/lumpedPointIOMovement.H
Normal file
133
src/lumpedPointMotion/lumpedPointIOMovement.H
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::lumpedPointIOMovement
|
||||||
|
|
||||||
|
Description
|
||||||
|
IO-registered version of lumpedPointMovement.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
lumpedPointMovement.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef lumpedPointIOMovement_H
|
||||||
|
#define lumpedPointIOMovement_H
|
||||||
|
|
||||||
|
#include "lumpedPointMovement.H"
|
||||||
|
#include "regIOobject.H"
|
||||||
|
#include "className.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
class lumpedPointIOMovement;
|
||||||
|
|
||||||
|
Ostream& operator<<(Ostream& os, const lumpedPointIOMovement& obj);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class lumpedPointIOMovement Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class lumpedPointIOMovement
|
||||||
|
:
|
||||||
|
public lumpedPointMovement,
|
||||||
|
public regIOobject
|
||||||
|
{
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
lumpedPointIOMovement(const lumpedPointIOMovement&) = delete;
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const lumpedPointIOMovement&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("lumpedPointMovement");
|
||||||
|
|
||||||
|
|
||||||
|
// Static Member Functions
|
||||||
|
|
||||||
|
//- Lookup pointer to object in the object-registry,
|
||||||
|
// return nullptr if found.
|
||||||
|
static const lumpedPointIOMovement* lookupInRegistry
|
||||||
|
(
|
||||||
|
const objectRegistry& obr
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Create a new object in the registry by reading system dictionary
|
||||||
|
static autoPtr<lumpedPointIOMovement> New
|
||||||
|
(
|
||||||
|
const objectRegistry& obr,
|
||||||
|
label ownerId = -1
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from IOobject, optionally with some owner information
|
||||||
|
explicit lumpedPointIOMovement
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
label ownerId = -1
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
~lumpedPointIOMovement();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- readData member function used by regIOobject
|
||||||
|
bool readData(Istream& is);
|
||||||
|
|
||||||
|
//- writeData member function required by regIOobject
|
||||||
|
bool writeData(Ostream& os) const;
|
||||||
|
|
||||||
|
|
||||||
|
// IOstream Operators
|
||||||
|
|
||||||
|
friend Ostream& operator<<
|
||||||
|
(
|
||||||
|
Ostream& os,
|
||||||
|
const lumpedPointIOMovement& obj
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
790
src/lumpedPointMotion/lumpedPointMovement.C
Normal file
790
src/lumpedPointMotion/lumpedPointMovement.C
Normal file
@ -0,0 +1,790 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "lumpedPointMovement.H"
|
||||||
|
#include "lumpedPointIOMovement.H"
|
||||||
|
#include "demandDrivenData.H"
|
||||||
|
#include "linearInterpolationWeights.H"
|
||||||
|
#include "IFstream.H"
|
||||||
|
#include "OFstream.H"
|
||||||
|
#include "volFields.H"
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
#include "PtrMap.H"
|
||||||
|
#include "faceZoneMesh.H"
|
||||||
|
#include "PstreamReduceOps.H"
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::Enum<Foam::lumpedPointMovement::outputFormatType>
|
||||||
|
Foam::lumpedPointMovement::formatNames
|
||||||
|
{
|
||||||
|
{ outputFormatType::PLAIN, "plain" },
|
||||||
|
{ outputFormatType::DICTIONARY, "dictionary" }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::word
|
||||||
|
Foam::lumpedPointMovement::dictionaryName("lumpedPointMovement");
|
||||||
|
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
//! \cond fileScope
|
||||||
|
//- Write list content with size, bracket, content, bracket one-per-line.
|
||||||
|
// This makes for consistent for parsing, regardless of the list length.
|
||||||
|
template <class T>
|
||||||
|
static void writeList(Ostream& os, const string& header, const UList<T>& lst)
|
||||||
|
{
|
||||||
|
// Header string
|
||||||
|
os << header.c_str() << nl;
|
||||||
|
|
||||||
|
// Write size and start delimiter
|
||||||
|
os << lst.size() << nl
|
||||||
|
<< token::BEGIN_LIST << nl;
|
||||||
|
|
||||||
|
// Write contents
|
||||||
|
forAll(lst, i)
|
||||||
|
{
|
||||||
|
os << lst[i] << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write end delimiter
|
||||||
|
os << token::END_LIST << token::END_STATEMENT << nl << nl;
|
||||||
|
}
|
||||||
|
//! \endcond
|
||||||
|
|
||||||
|
}
|
||||||
|
// namespace Foam
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::IOobject Foam::lumpedPointMovement::selectIO
|
||||||
|
(
|
||||||
|
const IOobject& io,
|
||||||
|
const fileName& f
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
f.size()
|
||||||
|
? IOobject // construct from filePath instead
|
||||||
|
(
|
||||||
|
f,
|
||||||
|
io.db(),
|
||||||
|
io.readOpt(),
|
||||||
|
io.writeOpt(),
|
||||||
|
io.registerObject(),
|
||||||
|
io.globalObject()
|
||||||
|
)
|
||||||
|
: io
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::calcThresholds() const
|
||||||
|
{
|
||||||
|
thresholdPtr_ = new scalarField(locations_);
|
||||||
|
|
||||||
|
scalarField& thresh = *thresholdPtr_;
|
||||||
|
|
||||||
|
for (label i=1; i < thresh.size(); ++i)
|
||||||
|
{
|
||||||
|
thresh[i-1] =
|
||||||
|
(
|
||||||
|
locations_[i-1]
|
||||||
|
+ (division_ * (locations_[i] - locations_[i-1]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::lumpedPointMovement::threshold(scalar pos) const
|
||||||
|
{
|
||||||
|
const scalarField& thresh = this->thresholds();
|
||||||
|
const label n = thresh.size();
|
||||||
|
|
||||||
|
// Clamp above and below
|
||||||
|
//
|
||||||
|
// ? may need special treatment to clamp values below the first threshold ?
|
||||||
|
// ? special treatment when 'axis' is negative ?
|
||||||
|
|
||||||
|
for (label i=0; i < n; ++i)
|
||||||
|
{
|
||||||
|
if (pos < thresh[i])
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// everything above goes into the last zone too
|
||||||
|
return n-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::lumpedPointMovement::lumpedPointMovement()
|
||||||
|
:
|
||||||
|
axis_(0,0,1),
|
||||||
|
locations_(),
|
||||||
|
division_(0),
|
||||||
|
relax_(1),
|
||||||
|
interpolationScheme_(linearInterpolationWeights::typeName),
|
||||||
|
ownerId_(-1),
|
||||||
|
boundBox_(),
|
||||||
|
centre_(),
|
||||||
|
autoCentre_(true),
|
||||||
|
forcesDict_(),
|
||||||
|
coupler_(),
|
||||||
|
inputName_("positions.in"),
|
||||||
|
outputName_("forces.out"),
|
||||||
|
inputFormat_(lumpedPointState::inputFormatType::DICTIONARY),
|
||||||
|
outputFormat_(outputFormatType::DICTIONARY),
|
||||||
|
state0_(),
|
||||||
|
state_(),
|
||||||
|
thresholdPtr_(0),
|
||||||
|
interpolatorPtr_()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::lumpedPointMovement::lumpedPointMovement
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
label ownerId
|
||||||
|
)
|
||||||
|
:
|
||||||
|
axis_(0,0,1),
|
||||||
|
locations_(),
|
||||||
|
division_(0),
|
||||||
|
relax_(1),
|
||||||
|
interpolationScheme_
|
||||||
|
(
|
||||||
|
dict.lookupOrDefault<word>
|
||||||
|
(
|
||||||
|
"interpolationScheme",
|
||||||
|
linearInterpolationWeights::typeName
|
||||||
|
)
|
||||||
|
),
|
||||||
|
ownerId_(ownerId),
|
||||||
|
boundBox_(),
|
||||||
|
centre_(),
|
||||||
|
autoCentre_(true),
|
||||||
|
forcesDict_(),
|
||||||
|
coupler_(),
|
||||||
|
state0_(),
|
||||||
|
state_(),
|
||||||
|
thresholdPtr_(0),
|
||||||
|
interpolatorPtr_()
|
||||||
|
{
|
||||||
|
readDict(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::lumpedPointMovement::~lumpedPointMovement()
|
||||||
|
{
|
||||||
|
deleteDemandDrivenData(thresholdPtr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::readDict(const dictionary& dict)
|
||||||
|
{
|
||||||
|
// assume the worst
|
||||||
|
deleteDemandDrivenData(thresholdPtr_);
|
||||||
|
|
||||||
|
dict.lookup("axis") >> axis_;
|
||||||
|
|
||||||
|
division_ = 0;
|
||||||
|
if (dict.readIfPresent("division", division_))
|
||||||
|
{
|
||||||
|
if (division_ < 0)
|
||||||
|
{
|
||||||
|
division_ = 0;
|
||||||
|
}
|
||||||
|
else if (division_ > 1)
|
||||||
|
{
|
||||||
|
division_ = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dict.readIfPresent("relax", relax_);
|
||||||
|
|
||||||
|
dict.lookup("locations") >> locations_;
|
||||||
|
|
||||||
|
if (dict.readIfPresent("interpolationScheme", interpolationScheme_))
|
||||||
|
{
|
||||||
|
interpolatorPtr_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
autoCentre_ = !dict.readIfPresent("centre", centre_);
|
||||||
|
|
||||||
|
// Initial state from initial locations, with zero rotation
|
||||||
|
tmp<vectorField> pts = locations_ * axis_;
|
||||||
|
state0_ = lumpedPointState(pts);
|
||||||
|
state_ = state0_;
|
||||||
|
|
||||||
|
forcesDict_.merge(dict.subOrEmptyDict("forces"));
|
||||||
|
|
||||||
|
const dictionary& commDict = dict.subDict("communication");
|
||||||
|
coupler_.readDict(commDict);
|
||||||
|
|
||||||
|
// TODO: calcFrequency_ = dict.lookupOrDefault("calcFrequency", 1);
|
||||||
|
|
||||||
|
commDict.lookup("inputName") >> inputName_;
|
||||||
|
commDict.lookup("outputName") >> outputName_;
|
||||||
|
|
||||||
|
inputFormat_ = lumpedPointState::formatNames.lookup
|
||||||
|
(
|
||||||
|
"inputFormat",
|
||||||
|
commDict
|
||||||
|
);
|
||||||
|
|
||||||
|
outputFormat_ = lumpedPointMovement::formatNames.lookup
|
||||||
|
(
|
||||||
|
"outputFormat",
|
||||||
|
commDict
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::setBoundBox
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const labelUList& patchIds,
|
||||||
|
const pointField& points0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
boundBox_ = boundBox::invertedBox;
|
||||||
|
|
||||||
|
const polyBoundaryMesh& patches = mesh.boundaryMesh();
|
||||||
|
for (const label patchId : patchIds)
|
||||||
|
{
|
||||||
|
boundBox_.add(points0, patches[patchId].meshPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
boundBox_.reduce();
|
||||||
|
|
||||||
|
if (autoCentre_)
|
||||||
|
{
|
||||||
|
centre_ = boundBox_.midpoint();
|
||||||
|
centre_ -= (centre_ & axis_) * axis_;
|
||||||
|
if (lumpedPointIOMovement::debug)
|
||||||
|
{
|
||||||
|
Pout<<"autoCentre on " << centre_ << " boundBox: " << boundBox_ << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// User-specified centre
|
||||||
|
if (lumpedPointIOMovement::debug)
|
||||||
|
{
|
||||||
|
Pout<<"centre on " << centre_ << " boundBox: " << boundBox_ << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::setMapping
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const labelUList& patchIds,
|
||||||
|
const pointField& points0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
setBoundBox(mesh, patchIds, points0);
|
||||||
|
|
||||||
|
faceZones_.clear();
|
||||||
|
|
||||||
|
// Local storage location (boundary faces only)
|
||||||
|
const label firstFace = mesh.nInternalFaces();
|
||||||
|
labelList faceToZoneID(mesh.nFaces() - firstFace, -1);
|
||||||
|
|
||||||
|
// Number of faces per zone
|
||||||
|
labelList nFaces(thresholds().size(), 0);
|
||||||
|
|
||||||
|
const polyBoundaryMesh& patches = mesh.boundaryMesh();
|
||||||
|
|
||||||
|
for (const label patchId : patchIds)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = patches[patchId];
|
||||||
|
|
||||||
|
// Classify faces into respective zones according to their centres
|
||||||
|
label meshFaceI = pp.start();
|
||||||
|
|
||||||
|
forAll(pp, i)
|
||||||
|
{
|
||||||
|
const face& f = mesh.faces()[meshFaceI];
|
||||||
|
label zoneId = this->threshold(f.centre(points0));
|
||||||
|
|
||||||
|
// localize storage location
|
||||||
|
faceToZoneID[meshFaceI - firstFace] = zoneId;
|
||||||
|
++nFaces[zoneId];
|
||||||
|
|
||||||
|
++meshFaceI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lumpedPointIOMovement::debug)
|
||||||
|
{
|
||||||
|
Pout<<"faces per zone:" << nFaces << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
faceZones_.setSize(nFaces.size());
|
||||||
|
|
||||||
|
label nZonedFaces = 0;
|
||||||
|
forAll(nFaces, zonei)
|
||||||
|
{
|
||||||
|
label n = nFaces[zonei];
|
||||||
|
labelList& addr = faceZones_[zonei];
|
||||||
|
addr.setSize(n);
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
forAll(faceToZoneID, faceI)
|
||||||
|
{
|
||||||
|
if (faceToZoneID[faceI] == zonei)
|
||||||
|
{
|
||||||
|
// from local storage to global mesh face
|
||||||
|
label meshFaceI = faceI + firstFace;
|
||||||
|
|
||||||
|
addr[n] = meshFaceI;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.setSize(n);
|
||||||
|
nZonedFaces += n;
|
||||||
|
|
||||||
|
if (lumpedPointIOMovement::debug)
|
||||||
|
{
|
||||||
|
Pout<< "Created faceZone[" << zonei << "] "
|
||||||
|
<< returnReduce(n, sumOp<label>()) << " faces, "
|
||||||
|
<< thresholds()[zonei] << " threshold" << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointMovement::forcesAndMoments
|
||||||
|
(
|
||||||
|
const polyMesh& pmesh,
|
||||||
|
List<vector>& forces,
|
||||||
|
List<vector>& moments
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
forces.setSize(faceZones_.size());
|
||||||
|
moments.setSize(faceZones_.size());
|
||||||
|
|
||||||
|
if (faceZones_.empty())
|
||||||
|
{
|
||||||
|
WarningInFunction
|
||||||
|
<< "Attempted to calculate forces without setMapping()"
|
||||||
|
<< nl << endl;
|
||||||
|
|
||||||
|
forces.setSize(thresholds().size(), Zero);
|
||||||
|
moments.setSize(thresholds().size(), Zero);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize with zero
|
||||||
|
forces = Zero;
|
||||||
|
moments = Zero;
|
||||||
|
|
||||||
|
// The mass centres
|
||||||
|
const pointField& lumpedCentres = state().points();
|
||||||
|
|
||||||
|
const polyBoundaryMesh& patches = pmesh.boundaryMesh();
|
||||||
|
|
||||||
|
const word pName = forcesDict_.lookupOrDefault<word>("p", "p");
|
||||||
|
|
||||||
|
scalar pRef = forcesDict_.lookupOrDefault<scalar>("pRef", 0.0);
|
||||||
|
scalar rhoRef = forcesDict_.lookupOrDefault<scalar>("rhoRef", 1.0);
|
||||||
|
|
||||||
|
|
||||||
|
// Calculated force per patch - cache
|
||||||
|
PtrMap<vectorField> forceOnPatches;
|
||||||
|
|
||||||
|
const volScalarField* pPtr = pmesh.lookupObjectPtr<volScalarField>(pName);
|
||||||
|
|
||||||
|
// fvMesh and has pressure field
|
||||||
|
if (isA<fvMesh>(pmesh) && pPtr)
|
||||||
|
{
|
||||||
|
const fvMesh& mesh = dynamicCast<const fvMesh>(pmesh);
|
||||||
|
const volScalarField& p = *pPtr;
|
||||||
|
|
||||||
|
// face centres (on patches)
|
||||||
|
const surfaceVectorField::Boundary& patchCf =
|
||||||
|
mesh.Cf().boundaryField();
|
||||||
|
|
||||||
|
// face areas (on patches)
|
||||||
|
const surfaceVectorField::Boundary& patchSf =
|
||||||
|
mesh.Sf().boundaryField();
|
||||||
|
|
||||||
|
// Pressure (on patches)
|
||||||
|
const volScalarField::Boundary& patchPress =
|
||||||
|
p.boundaryField();
|
||||||
|
|
||||||
|
// rhoRef if the pressure field is dynamic, i.e. p/rho otherwise 1
|
||||||
|
rhoRef = (p.dimensions() == dimPressure ? 1.0 : rhoRef);
|
||||||
|
|
||||||
|
// Scale pRef by density for incompressible simulations
|
||||||
|
pRef /= rhoRef;
|
||||||
|
|
||||||
|
forAll(faceZones_, zonei)
|
||||||
|
{
|
||||||
|
const labelList& zn = faceZones_[zonei];
|
||||||
|
|
||||||
|
forAll(zn, localFaceI)
|
||||||
|
{
|
||||||
|
const label meshFaceI = zn[localFaceI];
|
||||||
|
|
||||||
|
// locate which patch this face is on,
|
||||||
|
// and its offset within the patch
|
||||||
|
const label patchI = patches.whichPatch(meshFaceI);
|
||||||
|
if (patchI == -1)
|
||||||
|
{
|
||||||
|
// Should not happen - could also warn
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const label patchFaceI = meshFaceI - patches[patchI].start();
|
||||||
|
|
||||||
|
if (!forceOnPatches.found(patchI))
|
||||||
|
{
|
||||||
|
// Patch faces are +ve outwards,
|
||||||
|
// so the forces (exerted by fluid on solid)
|
||||||
|
// already have the correct sign
|
||||||
|
forceOnPatches.set
|
||||||
|
(
|
||||||
|
patchI,
|
||||||
|
(
|
||||||
|
rhoRef
|
||||||
|
* patchSf[patchI] * (patchPress[patchI] - pRef)
|
||||||
|
).ptr()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vectorField& forceOnPatch = *forceOnPatches[patchI];
|
||||||
|
|
||||||
|
// Force from the patch-face into sum
|
||||||
|
forces[zonei] += forceOnPatch[patchFaceI];
|
||||||
|
|
||||||
|
// effective torque arm:
|
||||||
|
// - translated into the lumped-points coordinate system
|
||||||
|
// prior to determining the distance
|
||||||
|
const vector lever =
|
||||||
|
(
|
||||||
|
patchCf[patchI][patchFaceI] - centre_
|
||||||
|
- lumpedCentres[zonei]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Moment from the patch-face into sum
|
||||||
|
moments[zonei] += lever ^ forceOnPatch[patchFaceI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info<<"no pressure" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pstream::listCombineGather(forces, plusEqOp<vector>());
|
||||||
|
Pstream::listCombineScatter(forces);
|
||||||
|
|
||||||
|
Pstream::listCombineGather(moments, plusEqOp<vector>());
|
||||||
|
Pstream::listCombineScatter(moments);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// \cond fileScope
|
||||||
|
template<class T>
|
||||||
|
static inline T interpolatedValue
|
||||||
|
(
|
||||||
|
const Foam::UList<T> input,
|
||||||
|
const Foam::labelUList& indices,
|
||||||
|
const Foam::scalarField& weights
|
||||||
|
)
|
||||||
|
{
|
||||||
|
T result = weights[0] * input[indices[0]];
|
||||||
|
for (Foam::label i=1; i < indices.size(); ++i)
|
||||||
|
{
|
||||||
|
result += weights[i] * input[indices[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// \endcond
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::pointField>
|
||||||
|
Foam::lumpedPointMovement::displacePoints
|
||||||
|
(
|
||||||
|
const pointField& points0,
|
||||||
|
const labelList& pointLabels
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return displacePoints(state(), points0, pointLabels);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::pointField>
|
||||||
|
Foam::lumpedPointMovement::displacePoints
|
||||||
|
(
|
||||||
|
const lumpedPointState& state,
|
||||||
|
const pointField& points0,
|
||||||
|
const labelList& pointLabels
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// storage for the interpolation indices/weights
|
||||||
|
labelList indices;
|
||||||
|
scalarField weights;
|
||||||
|
const interpolationWeights& interp = interpolator();
|
||||||
|
|
||||||
|
// The mass centres
|
||||||
|
const pointField& lumpedCentres = state.points();
|
||||||
|
|
||||||
|
// local-to-global transformation tensor
|
||||||
|
const tensorField& localToGlobal = state.rotations();
|
||||||
|
|
||||||
|
// could also verify the sizes (state vs original)
|
||||||
|
|
||||||
|
tmp<pointField> tdisp(new pointField(pointLabels.size()));
|
||||||
|
pointField& disp = tdisp.ref();
|
||||||
|
|
||||||
|
forAll(pointLabels, ptI)
|
||||||
|
{
|
||||||
|
const point& p0 = points0[pointLabels[ptI]];
|
||||||
|
|
||||||
|
// Interpolation factor based on the axis component
|
||||||
|
// of the original point (location)
|
||||||
|
scalar where = p0 & axis_;
|
||||||
|
|
||||||
|
interp.valueWeights(where, indices, weights);
|
||||||
|
|
||||||
|
vector origin = interpolatedValue(lumpedCentres, indices, weights);
|
||||||
|
tensor rotTensor = interpolatedValue(localToGlobal, indices, weights);
|
||||||
|
|
||||||
|
if (indices.size() == 1)
|
||||||
|
{
|
||||||
|
// out-of-bounds, use corresponding end-point
|
||||||
|
where = locations_[indices[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// local point:
|
||||||
|
// - translated into the lumped-points coordinate system
|
||||||
|
// - relative to the interpolation (where) location
|
||||||
|
const vector local = (p0 - (where * axis_)) - centre_;
|
||||||
|
|
||||||
|
// local-to-global rotation and translation
|
||||||
|
// - translate back out of the lumped-points coordinate system
|
||||||
|
//
|
||||||
|
// -> subtract p0 to return displacements
|
||||||
|
disp[ptI] = (rotTensor & local) + origin + centre_ - p0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tdisp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::writeDict(Ostream& os) const
|
||||||
|
{
|
||||||
|
os.writeEntry("axis", axis_);
|
||||||
|
os.writeEntry("locations", locations_);
|
||||||
|
os.writeEntry("division", division_);
|
||||||
|
// os.writeEntry("interpolationScheme", interpolationScheme_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointMovement::readState()
|
||||||
|
{
|
||||||
|
lumpedPointState prev = state_;
|
||||||
|
|
||||||
|
bool status = state_.readData
|
||||||
|
(
|
||||||
|
inputFormat_,
|
||||||
|
coupler().resolveFile(inputName_)
|
||||||
|
);
|
||||||
|
|
||||||
|
state_.relax(relax_, prev);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointMovement::writeData
|
||||||
|
(
|
||||||
|
const UList<vector>& forces
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
if (!Pstream::master())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileName output(coupler().resolveFile(outputName_));
|
||||||
|
OFstream os(output); // ASCII
|
||||||
|
|
||||||
|
if (outputFormat_ == outputFormatType::PLAIN)
|
||||||
|
{
|
||||||
|
os <<"# output from OpenFOAM" << nl
|
||||||
|
<<"# N, points, forces" << nl
|
||||||
|
<< this->size() << nl;
|
||||||
|
|
||||||
|
const char* zeroVector = "0 0 0";
|
||||||
|
|
||||||
|
forAll(locations_, i)
|
||||||
|
{
|
||||||
|
const vector pos = locations_[i] * axis_;
|
||||||
|
|
||||||
|
os << pos.x() << ' '
|
||||||
|
<< pos.y() << ' '
|
||||||
|
<< pos.z() << ' ';
|
||||||
|
|
||||||
|
if (i < forces.size())
|
||||||
|
{
|
||||||
|
os << forces[i].x() << ' '
|
||||||
|
<< forces[i].y() << ' '
|
||||||
|
<< forces[i].z();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << zeroVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
os << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Make it easier for external programs to parse
|
||||||
|
// - exclude the usual OpenFOAM 'FoamFile' header
|
||||||
|
// - ensure lists have consistent format
|
||||||
|
|
||||||
|
os <<"// output from OpenFOAM" << nl << nl;
|
||||||
|
|
||||||
|
writeList(os, "points", (locations_*axis_)());
|
||||||
|
writeList(os, "forces", forces);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointMovement::writeData
|
||||||
|
(
|
||||||
|
const UList<vector>& forces,
|
||||||
|
const UList<vector>& moments
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
if (!Pstream::master())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileName output(coupler().resolveFile(outputName_));
|
||||||
|
OFstream os(output); // ASCII
|
||||||
|
|
||||||
|
if (outputFormat_ == outputFormatType::PLAIN)
|
||||||
|
{
|
||||||
|
os <<"# output from OpenFOAM" << nl
|
||||||
|
<<"# N, points, forces, moments" << nl
|
||||||
|
<< this->size() << nl;
|
||||||
|
|
||||||
|
const char* zeroVector = "0 0 0";
|
||||||
|
|
||||||
|
forAll(locations_, i)
|
||||||
|
{
|
||||||
|
const vector pos = locations_[i] * axis_;
|
||||||
|
|
||||||
|
os << pos.x() << ' '
|
||||||
|
<< pos.y() << ' '
|
||||||
|
<< pos.z() << ' ';
|
||||||
|
|
||||||
|
if (i < forces.size())
|
||||||
|
{
|
||||||
|
os << forces[i].x() << ' '
|
||||||
|
<< forces[i].y() << ' '
|
||||||
|
<< forces[i].z() << ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << zeroVector << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < moments.size())
|
||||||
|
{
|
||||||
|
os << moments[i].x() << ' '
|
||||||
|
<< moments[i].y() << ' '
|
||||||
|
<< moments[i].z();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << zeroVector;
|
||||||
|
}
|
||||||
|
os << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Make it easier for external programs to parse
|
||||||
|
// - exclude the usual OpenFOAM 'FoamFile' header
|
||||||
|
// - ensure lists have consistent format
|
||||||
|
|
||||||
|
os <<"// output from OpenFOAM" << nl << nl;
|
||||||
|
|
||||||
|
writeList(os, "points", (locations_*axis_)());
|
||||||
|
writeList(os, "forces", forces);
|
||||||
|
writeList(os, "moments", moments);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::interpolationWeights&
|
||||||
|
Foam::lumpedPointMovement::interpolator() const
|
||||||
|
{
|
||||||
|
if (!interpolatorPtr_.valid())
|
||||||
|
{
|
||||||
|
interpolatorPtr_ = interpolationWeights::New
|
||||||
|
(
|
||||||
|
interpolationScheme_,
|
||||||
|
locations_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return interpolatorPtr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
399
src/lumpedPointMotion/lumpedPointMovement.H
Normal file
399
src/lumpedPointMotion/lumpedPointMovement.H
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::lumpedPointMovement
|
||||||
|
|
||||||
|
Description
|
||||||
|
The movement 'driver' that describes initial point locations, the
|
||||||
|
segmentation for pressure integration, the current state of the
|
||||||
|
points/rotations, and forwarding to the communication
|
||||||
|
coordinator. The 'lumpedPointIOMovement' class is simply a
|
||||||
|
registered version of the same.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
lumpedPointMovement.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef lumpedPointMovement_H
|
||||||
|
#define lumpedPointMovement_H
|
||||||
|
|
||||||
|
#include "dictionary.H"
|
||||||
|
#include "scalarList.H"
|
||||||
|
#include "scalarField.H"
|
||||||
|
#include "pointField.H"
|
||||||
|
#include "vectorField.H"
|
||||||
|
#include "tensorField.H"
|
||||||
|
#include "vector.H"
|
||||||
|
#include "interpolationWeights.H"
|
||||||
|
#include "IOobject.H"
|
||||||
|
#include "tmp.H"
|
||||||
|
#include "faceZoneMeshFwd.H"
|
||||||
|
#include "externalCoupler.H"
|
||||||
|
#include "lumpedPointState.H"
|
||||||
|
#include "boundBox.H"
|
||||||
|
#include "Enum.H"
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
// Forward declarations
|
||||||
|
class polyMesh;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class lumpedPointMovement Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class lumpedPointMovement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Output format types
|
||||||
|
enum class outputFormatType
|
||||||
|
{
|
||||||
|
PLAIN,
|
||||||
|
DICTIONARY
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static data
|
||||||
|
|
||||||
|
//- Names for the output format types
|
||||||
|
static const Enum<outputFormatType> formatNames;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- Reference axis for the locations
|
||||||
|
vector axis_;
|
||||||
|
|
||||||
|
//- The locations of the lumped points within the reference axis
|
||||||
|
// The interpolator needs scalarField, not scalarList.
|
||||||
|
scalarField locations_;
|
||||||
|
|
||||||
|
//- The division when calculating pressure forces (0-1)
|
||||||
|
scalar division_;
|
||||||
|
|
||||||
|
//- The relaxation factor when moving points (default: 1)
|
||||||
|
scalar relax_;
|
||||||
|
|
||||||
|
//- The interpolation type (linear|spline)
|
||||||
|
word interpolationScheme_;
|
||||||
|
|
||||||
|
//- Optional owner information
|
||||||
|
label ownerId_;
|
||||||
|
|
||||||
|
//- The bounding box (if set)
|
||||||
|
boundBox boundBox_;
|
||||||
|
|
||||||
|
//- The offset of patch points to compared to the locations
|
||||||
|
point centre_;
|
||||||
|
|
||||||
|
//- Calculate centre based on the bounding box
|
||||||
|
bool autoCentre_;
|
||||||
|
|
||||||
|
//- Dictionary of controls for force calculation
|
||||||
|
dictionary forcesDict_;
|
||||||
|
|
||||||
|
//- Communication control
|
||||||
|
externalCoupler coupler_;
|
||||||
|
|
||||||
|
//- File io
|
||||||
|
word inputName_;
|
||||||
|
word outputName_;
|
||||||
|
lumpedPointState::inputFormatType inputFormat_;
|
||||||
|
outputFormatType outputFormat_;
|
||||||
|
|
||||||
|
|
||||||
|
// Demand-driven private data
|
||||||
|
|
||||||
|
//- The initial state (positions, rotations)
|
||||||
|
lumpedPointState state0_;
|
||||||
|
|
||||||
|
//- The current state (positions, rotations)
|
||||||
|
// Eg, as response from external application
|
||||||
|
lumpedPointState state_;
|
||||||
|
|
||||||
|
//- Threshold locations for pressure forces
|
||||||
|
mutable scalarField* thresholdPtr_;
|
||||||
|
|
||||||
|
//- User-specified interpolator
|
||||||
|
mutable autoPtr<interpolationWeights> interpolatorPtr_;
|
||||||
|
|
||||||
|
//- Pressure zones (only used from the master patch)
|
||||||
|
mutable List<labelList> faceZones_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Calculate threshold locations
|
||||||
|
void calcThresholds() const;
|
||||||
|
|
||||||
|
//- Classify the position to be located in one of the threshold zones
|
||||||
|
label threshold(scalar pos) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy constructor
|
||||||
|
lumpedPointMovement(const lumpedPointMovement&) = delete;
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const lumpedPointMovement&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Static data members
|
||||||
|
|
||||||
|
//- The standard dictionary name
|
||||||
|
static const word dictionaryName;
|
||||||
|
|
||||||
|
//- Helper: return IOobject with optionally absolute path provided
|
||||||
|
static IOobject selectIO(const IOobject&, const fileName&);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct null
|
||||||
|
lumpedPointMovement();
|
||||||
|
|
||||||
|
//- Construct from dictionary, optionally with some owner information
|
||||||
|
lumpedPointMovement(const dictionary& dict, label ownerId=-1);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~lumpedPointMovement();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Update settings from dictionary
|
||||||
|
void readDict(const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
|
//- If no number of lumped points (locations) were specified
|
||||||
|
inline bool empty() const;
|
||||||
|
|
||||||
|
//- The number of lumped points (number of locations)
|
||||||
|
inline label size() const;
|
||||||
|
|
||||||
|
//- The normalized reference axis
|
||||||
|
inline const vector& axis() const;
|
||||||
|
|
||||||
|
//- Read access to the locations
|
||||||
|
inline const scalarField& locations() const;
|
||||||
|
|
||||||
|
//- The division (0-1) when calculating pressure forces
|
||||||
|
inline scalar division() const;
|
||||||
|
|
||||||
|
//- An owner Id, if needed for bookkeeping purposes
|
||||||
|
inline label ownerId() const;
|
||||||
|
|
||||||
|
//- Change the owner id, if needed for bookkeeping purposes
|
||||||
|
inline void ownerId(label id);
|
||||||
|
|
||||||
|
|
||||||
|
//- Threshold locations for pressure forces
|
||||||
|
inline const scalarField& thresholds() const;
|
||||||
|
|
||||||
|
//- Classify the position to be located in one of the threshold zones
|
||||||
|
inline label threshold(const point& position) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Communication control
|
||||||
|
inline const externalCoupler& coupler() const;
|
||||||
|
|
||||||
|
//- Communication control
|
||||||
|
inline externalCoupler& coupler();
|
||||||
|
|
||||||
|
//- The initial state (positions/rotations)
|
||||||
|
inline const lumpedPointState& state0() const;
|
||||||
|
|
||||||
|
//- The current state (positions/rotations)
|
||||||
|
inline const lumpedPointState& state() const;
|
||||||
|
|
||||||
|
//- The relaxation factor when changing states
|
||||||
|
inline scalar relax() const;
|
||||||
|
|
||||||
|
//- The relaxation factor when changing states
|
||||||
|
inline scalar& relax();
|
||||||
|
|
||||||
|
//- The input (state) file name
|
||||||
|
inline const word& inputName() const;
|
||||||
|
|
||||||
|
//- The output (forces) file name
|
||||||
|
inline const word& outputName() const;
|
||||||
|
|
||||||
|
//- The input (state) file format
|
||||||
|
inline lumpedPointState::inputFormatType inputFormat() const;
|
||||||
|
|
||||||
|
//- The output (forces) file format
|
||||||
|
inline lumpedPointMovement::outputFormatType outputFormat() const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Define the bounding-box required to enclose the specified patches.
|
||||||
|
// Calculates the centre as required.
|
||||||
|
//
|
||||||
|
// \param mesh The volume mesh reference
|
||||||
|
// \param patchIds The patch ids to be included in the bounding box.
|
||||||
|
// \param points0 The initial mesh points, prior to movement
|
||||||
|
void setBoundBox
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const labelUList& patchIds,
|
||||||
|
const pointField& points0
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Define the pressure-zones mapping for faces in the specified
|
||||||
|
// patches.
|
||||||
|
// The face centres are compared to the threshold positions,
|
||||||
|
// which are determined by locations along the defined axis.
|
||||||
|
//
|
||||||
|
// \param mesh The volume mesh reference
|
||||||
|
// \param patchIds The patch ids to be included in the mapping
|
||||||
|
// \param points0 The initial mesh points, prior to movement
|
||||||
|
void setMapping
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const labelUList& patchIds,
|
||||||
|
const pointField& points0
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- True if the pressure-zones mapping has already been performed
|
||||||
|
inline bool hasMapping() const;
|
||||||
|
|
||||||
|
//- Return the pressure-zones mapping with the associated
|
||||||
|
// patch face ids.
|
||||||
|
inline const List<labelList>& zones() const;
|
||||||
|
|
||||||
|
|
||||||
|
//- The forces and moments acting on each pressure-zone.
|
||||||
|
// The zones must be previously defined via setMapping.
|
||||||
|
bool forcesAndMoments
|
||||||
|
(
|
||||||
|
const polyMesh& pmesh,
|
||||||
|
List<vector>& forces,
|
||||||
|
List<vector>& moments
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Displace points according to the current state
|
||||||
|
tmp<pointField> displacePoints
|
||||||
|
(
|
||||||
|
const pointField& points0,
|
||||||
|
const labelList& pointLabels
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Displace points according to specified state
|
||||||
|
tmp<pointField> displacePoints
|
||||||
|
(
|
||||||
|
const lumpedPointState& state,
|
||||||
|
const pointField& points0,
|
||||||
|
const labelList& pointLabels
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Interpolation weights
|
||||||
|
const interpolationWeights& interpolator() const;
|
||||||
|
|
||||||
|
//- Write axis, locations, division as a dictionary
|
||||||
|
void writeDict(Ostream& os) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Write points, forces
|
||||||
|
bool writeData
|
||||||
|
(
|
||||||
|
const UList<vector>& forces
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Write points, forces, moments
|
||||||
|
bool writeData
|
||||||
|
(
|
||||||
|
const UList<vector>& forces,
|
||||||
|
const UList<vector>& moments
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Read state from file, applying relaxation as requested
|
||||||
|
bool readState();
|
||||||
|
|
||||||
|
//- Write state as VTK PolyData format.
|
||||||
|
void writeStateVTP(const fileName& file) const;
|
||||||
|
|
||||||
|
//- Write forces on points as VTK PolyData format.
|
||||||
|
void writeForcesAndMomentsVTP
|
||||||
|
(
|
||||||
|
const fileName& file,
|
||||||
|
const UList<vector>& forces,
|
||||||
|
const UList<vector>& moments
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Write pressure-zones geometry, write as VTK PolyData format.
|
||||||
|
void writeZonesVTP
|
||||||
|
(
|
||||||
|
const fileName& file,
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const pointField& points0
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Write displaced geometry according to the current state,
|
||||||
|
// write as VTK PolyData format.
|
||||||
|
void writeVTP
|
||||||
|
(
|
||||||
|
const fileName& file,
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const labelUList& patchIds,
|
||||||
|
const pointField& points0
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Write displaced geometry according to the specified state,
|
||||||
|
// write as VTK PolyData format.
|
||||||
|
void writeVTP
|
||||||
|
(
|
||||||
|
const fileName& file,
|
||||||
|
const lumpedPointState& state,
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const labelUList& patchLst,
|
||||||
|
const pointField& points0
|
||||||
|
) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#include "lumpedPointMovementI.H"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
162
src/lumpedPointMotion/lumpedPointMovementI.H
Normal file
162
src/lumpedPointMotion/lumpedPointMovementI.H
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::lumpedPointMovement::empty() const
|
||||||
|
{
|
||||||
|
return locations_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::label Foam::lumpedPointMovement::size() const
|
||||||
|
{
|
||||||
|
return locations_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::vector& Foam::lumpedPointMovement::axis() const
|
||||||
|
{
|
||||||
|
return axis_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::scalarField& Foam::lumpedPointMovement::locations() const
|
||||||
|
{
|
||||||
|
return locations_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::scalar Foam::lumpedPointMovement::division() const
|
||||||
|
{
|
||||||
|
return division_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::label Foam::lumpedPointMovement::ownerId() const
|
||||||
|
{
|
||||||
|
return ownerId_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Foam::lumpedPointMovement::ownerId(label id)
|
||||||
|
{
|
||||||
|
ownerId_ = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::scalarField& Foam::lumpedPointMovement::thresholds() const
|
||||||
|
{
|
||||||
|
if (!thresholdPtr_)
|
||||||
|
{
|
||||||
|
calcThresholds();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *thresholdPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::label
|
||||||
|
Foam::lumpedPointMovement::threshold(const point& position) const
|
||||||
|
{
|
||||||
|
return threshold(position & axis_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::externalCoupler& Foam::lumpedPointMovement::coupler() const
|
||||||
|
{
|
||||||
|
return coupler_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::externalCoupler& Foam::lumpedPointMovement::coupler()
|
||||||
|
{
|
||||||
|
return coupler_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//- The initial state (positions/rotations)
|
||||||
|
inline const Foam::lumpedPointState& Foam::lumpedPointMovement::state0() const
|
||||||
|
{
|
||||||
|
return state0_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::lumpedPointState& Foam::lumpedPointMovement::state() const
|
||||||
|
{
|
||||||
|
return state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::scalar Foam::lumpedPointMovement::relax() const
|
||||||
|
{
|
||||||
|
return relax_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::scalar& Foam::lumpedPointMovement::relax()
|
||||||
|
{
|
||||||
|
return relax_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::word& Foam::lumpedPointMovement::inputName() const
|
||||||
|
{
|
||||||
|
return inputName_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::word& Foam::lumpedPointMovement::outputName() const
|
||||||
|
{
|
||||||
|
return outputName_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::lumpedPointState::inputFormatType
|
||||||
|
Foam::lumpedPointMovement::inputFormat() const
|
||||||
|
{
|
||||||
|
return inputFormat_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::lumpedPointMovement::outputFormatType
|
||||||
|
Foam::lumpedPointMovement::outputFormat() const
|
||||||
|
{
|
||||||
|
return outputFormat_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::lumpedPointMovement::hasMapping() const
|
||||||
|
{
|
||||||
|
return !faceZones_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::List<Foam::labelList>&
|
||||||
|
Foam::lumpedPointMovement::zones() const
|
||||||
|
{
|
||||||
|
return faceZones_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
447
src/lumpedPointMotion/lumpedPointMovementWriter.C
Normal file
447
src/lumpedPointMotion/lumpedPointMovementWriter.C
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "lumpedPointMovement.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "OFstream.H"
|
||||||
|
#include "uindirectPrimitivePatch.H"
|
||||||
|
|
||||||
|
#include "foamVtkOutput.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::writeStateVTP(const fileName& file) const
|
||||||
|
{
|
||||||
|
state().writeVTP(file, axis());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::writeForcesAndMomentsVTP
|
||||||
|
(
|
||||||
|
const fileName& file,
|
||||||
|
const UList<vector>& forces,
|
||||||
|
const UList<vector>& moments
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
OFstream fos(file);
|
||||||
|
std::ostream& os = fos.stdStream();
|
||||||
|
|
||||||
|
autoPtr<vtk::formatter> format = vtk::newFormatter
|
||||||
|
(
|
||||||
|
os,
|
||||||
|
vtk::formatType::INLINE_ASCII
|
||||||
|
);
|
||||||
|
|
||||||
|
format().xmlHeader()
|
||||||
|
.beginVTKFile(vtk::fileTag::POLY_DATA, "0.1");
|
||||||
|
|
||||||
|
//
|
||||||
|
// The 'spine' of lumped mass points
|
||||||
|
//
|
||||||
|
const label nPoints = state().points().size();
|
||||||
|
|
||||||
|
{
|
||||||
|
format()
|
||||||
|
.openTag(vtk::fileTag::PIECE)
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, nPoints)
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_VERTS, nPoints)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
// 'points'
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (nPoints*3* sizeof(float));
|
||||||
|
|
||||||
|
format()
|
||||||
|
.tag(vtk::fileTag::POINTS)
|
||||||
|
.openDataArray<float, 3>(vtk::dataArrayAttr::POINTS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
vtk::writeList(format(), state().points());
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format()
|
||||||
|
.endDataArray()
|
||||||
|
.endTag(vtk::fileTag::POINTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Verts>
|
||||||
|
format().tag(vtk::fileTag::VERTS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'connectivity'
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (nPoints*sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
for (label i=0; i<nPoints; ++i)
|
||||||
|
{
|
||||||
|
format().write(i);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'offsets' (connectivity offsets)
|
||||||
|
// = linear mapping onto points (with 1 offset)
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (nPoints*sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::OFFSETS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
for (label i=0; i<nPoints; ++i)
|
||||||
|
{
|
||||||
|
format().write(i+1);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::VERTS);
|
||||||
|
// </Verts>
|
||||||
|
}
|
||||||
|
|
||||||
|
format().tag(vtk::fileTag::POINT_DATA);
|
||||||
|
|
||||||
|
// forces
|
||||||
|
if (forces.size() == nPoints)
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (nPoints * 3 * sizeof(float));
|
||||||
|
|
||||||
|
format().openDataArray<float, 3>("forces")
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
vtk::writeList(format(), forces);
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// moments
|
||||||
|
if (moments.size() == nPoints)
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (nPoints * 3 * sizeof(float));
|
||||||
|
|
||||||
|
format().openDataArray<float, 3>("moments")
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
vtk::writeList(format(), moments);
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::POINT_DATA);
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::PIECE);
|
||||||
|
format().endTag(vtk::fileTag::POLY_DATA);
|
||||||
|
format().endVTKFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::writeZonesVTP
|
||||||
|
(
|
||||||
|
const fileName& file,
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const pointField& points0
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
OFstream fos(file);
|
||||||
|
std::ostream& os = fos.stdStream();
|
||||||
|
|
||||||
|
autoPtr<vtk::formatter> format = vtk::newFormatter
|
||||||
|
(
|
||||||
|
os,
|
||||||
|
vtk::formatType::INLINE_ASCII
|
||||||
|
);
|
||||||
|
|
||||||
|
format().xmlHeader()
|
||||||
|
.beginVTKFile(vtk::fileTag::POLY_DATA, "0.1");
|
||||||
|
|
||||||
|
forAll(faceZones_, zoneI)
|
||||||
|
{
|
||||||
|
uindirectPrimitivePatch pp
|
||||||
|
(
|
||||||
|
UIndirectList<face>(mesh.faces(), faceZones_[zoneI]),
|
||||||
|
points0
|
||||||
|
);
|
||||||
|
|
||||||
|
format()
|
||||||
|
.openTag(vtk::fileTag::PIECE)
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, pp.nPoints())
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_POLYS, pp.size())
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
// 'points'
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (pp.nPoints()*3* sizeof(float));
|
||||||
|
|
||||||
|
format()
|
||||||
|
.tag(vtk::fileTag::POINTS)
|
||||||
|
.openDataArray<float, 3>(vtk::dataArrayAttr::POINTS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
vtk::writeList(format(), pp.localPoints());
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format()
|
||||||
|
.endDataArray()
|
||||||
|
.endTag(vtk::fileTag::POINTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Polys>
|
||||||
|
format().tag(vtk::fileTag::POLYS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'connectivity'
|
||||||
|
//
|
||||||
|
{
|
||||||
|
uint64_t payLoad = 0;
|
||||||
|
forAll(pp, facei)
|
||||||
|
{
|
||||||
|
const face& f = pp[facei];
|
||||||
|
payLoad += f.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad * sizeof(label));
|
||||||
|
|
||||||
|
for (const face& f : pp.localFaces())
|
||||||
|
{
|
||||||
|
vtk::writeList(format(), f);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'offsets' (connectivity offsets)
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (pp.size() * sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::OFFSETS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
|
||||||
|
label off = 0;
|
||||||
|
forAll(pp, facei)
|
||||||
|
{
|
||||||
|
const face& f = pp[facei];
|
||||||
|
off += f.size();
|
||||||
|
|
||||||
|
format().write(off);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::POLYS);
|
||||||
|
|
||||||
|
|
||||||
|
format().tag(vtk::fileTag::CELL_DATA);
|
||||||
|
|
||||||
|
// zone Id
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (pp.size() * sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>("zoneId")
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
|
||||||
|
forAll(pp, facei)
|
||||||
|
{
|
||||||
|
format().write(zoneI);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::CELL_DATA);
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::PIECE);
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::POLY_DATA);
|
||||||
|
format().endVTKFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::writeVTP
|
||||||
|
(
|
||||||
|
const fileName& file,
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const labelUList& patchIds,
|
||||||
|
const pointField& points0
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
writeVTP(file, state(), mesh, patchIds, points0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointMovement::writeVTP
|
||||||
|
(
|
||||||
|
const fileName& file,
|
||||||
|
const lumpedPointState& state,
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const labelUList& patchIds,
|
||||||
|
const pointField& points0
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const polyBoundaryMesh& boundaryMesh = mesh.boundaryMesh();
|
||||||
|
|
||||||
|
OFstream fos(file);
|
||||||
|
std::ostream& os = fos.stdStream();
|
||||||
|
|
||||||
|
autoPtr<vtk::formatter> format = vtk::newFormatter
|
||||||
|
(
|
||||||
|
os,
|
||||||
|
vtk::formatType::INLINE_ASCII
|
||||||
|
);
|
||||||
|
|
||||||
|
format().xmlHeader()
|
||||||
|
.beginVTKFile(vtk::fileTag::POLY_DATA, "0.1");
|
||||||
|
|
||||||
|
for (const label patchId : patchIds)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = boundaryMesh[patchId];
|
||||||
|
|
||||||
|
format()
|
||||||
|
.openTag(vtk::fileTag::PIECE)
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, pp.nPoints())
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_POLYS, pp.size())
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
// 'points'
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (pp.nPoints()*3* sizeof(float));
|
||||||
|
|
||||||
|
format()
|
||||||
|
.tag(vtk::fileTag::POINTS)
|
||||||
|
.openDataArray<float, 3>(vtk::dataArrayAttr::POINTS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
// Could be more efficient, but not often needed
|
||||||
|
tmp<pointField> tpts = displacePoints
|
||||||
|
(
|
||||||
|
state,
|
||||||
|
points0,
|
||||||
|
pp.meshPoints()
|
||||||
|
) + pointField(points0, pp.meshPoints());
|
||||||
|
|
||||||
|
const pointField& pts = tpts();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
vtk::writeList(format(), pts);
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format()
|
||||||
|
.endDataArray()
|
||||||
|
.endTag(vtk::fileTag::POINTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Polys>
|
||||||
|
format().tag(vtk::fileTag::POLYS);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'connectivity'
|
||||||
|
//
|
||||||
|
{
|
||||||
|
uint64_t payLoad = 0;
|
||||||
|
for (const face& f : pp)
|
||||||
|
{
|
||||||
|
payLoad += f.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad * sizeof(label));
|
||||||
|
|
||||||
|
for (const face& f : pp.localFaces())
|
||||||
|
{
|
||||||
|
vtk::writeList(format(), f);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'offsets' (connectivity offsets)
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (pp.size() * sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::OFFSETS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
|
||||||
|
label off = 0;
|
||||||
|
forAll(pp, facei)
|
||||||
|
{
|
||||||
|
const face& f = pp[facei];
|
||||||
|
off += f.size();
|
||||||
|
|
||||||
|
format().write(off);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::POLYS);
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::PIECE);
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::POLY_DATA);
|
||||||
|
format().endVTKFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
362
src/lumpedPointMotion/lumpedPointState.C
Normal file
362
src/lumpedPointMotion/lumpedPointState.C
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "lumpedPointState.H"
|
||||||
|
#include "demandDrivenData.H"
|
||||||
|
#include "EulerCoordinateRotation.H"
|
||||||
|
#include "unitConversion.H"
|
||||||
|
|
||||||
|
#include "ISstream.H"
|
||||||
|
#include "IFstream.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::Enum<Foam::lumpedPointState::inputFormatType>
|
||||||
|
Foam::lumpedPointState::formatNames
|
||||||
|
{
|
||||||
|
{ inputFormatType::PLAIN, "plain" },
|
||||||
|
{ inputFormatType::DICTIONARY, "dictionary" }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
//! \cond fileScope
|
||||||
|
static Foam::string getLineNoComment(Foam::ISstream& is)
|
||||||
|
{
|
||||||
|
Foam::string line;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
is.getLine(line);
|
||||||
|
}
|
||||||
|
while ((line.empty() || line[0] == '#') && is.good());
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
//! \endcond
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::lumpedPointState::calcRotations() const
|
||||||
|
{
|
||||||
|
rotationPtr_ = new tensorField(angles_.size());
|
||||||
|
forAll(angles_, itemi)
|
||||||
|
{
|
||||||
|
rotationPtr_->operator[](itemi) = EulerCoordinateRotation
|
||||||
|
(
|
||||||
|
angles_[itemi],
|
||||||
|
degrees_ // true=degrees, false=radians
|
||||||
|
).R();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointState::readDict(const dictionary& dict)
|
||||||
|
{
|
||||||
|
dict.lookup("points") >> points_;
|
||||||
|
dict.lookup("angles") >> angles_;
|
||||||
|
degrees_ = dict.lookupOrDefault("degrees", false);
|
||||||
|
deleteDemandDrivenData(rotationPtr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::lumpedPointState::lumpedPointState()
|
||||||
|
:
|
||||||
|
points_(0),
|
||||||
|
angles_(0),
|
||||||
|
degrees_(false),
|
||||||
|
rotationPtr_(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::lumpedPointState::lumpedPointState(const lumpedPointState& rhs)
|
||||||
|
:
|
||||||
|
points_(rhs.points_),
|
||||||
|
angles_(rhs.angles_),
|
||||||
|
degrees_(rhs.degrees_),
|
||||||
|
rotationPtr_(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::lumpedPointState::lumpedPointState
|
||||||
|
(
|
||||||
|
const pointField& pts
|
||||||
|
)
|
||||||
|
:
|
||||||
|
points_(pts),
|
||||||
|
angles_(points_.size(), Zero),
|
||||||
|
degrees_(false),
|
||||||
|
rotationPtr_(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::lumpedPointState::lumpedPointState
|
||||||
|
(
|
||||||
|
tmp<pointField>& pts
|
||||||
|
)
|
||||||
|
:
|
||||||
|
points_(pts),
|
||||||
|
angles_(points_.size(), Zero),
|
||||||
|
degrees_(false),
|
||||||
|
rotationPtr_(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::lumpedPointState::lumpedPointState
|
||||||
|
(
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
points_(0),
|
||||||
|
angles_(0),
|
||||||
|
degrees_(false),
|
||||||
|
rotationPtr_(nullptr)
|
||||||
|
{
|
||||||
|
readDict(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::lumpedPointState::~lumpedPointState()
|
||||||
|
{
|
||||||
|
deleteDemandDrivenData(rotationPtr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::lumpedPointState::operator=(const lumpedPointState& rhs)
|
||||||
|
{
|
||||||
|
points_ = rhs.points_;
|
||||||
|
angles_ = rhs.angles_;
|
||||||
|
degrees_ = rhs.degrees_;
|
||||||
|
|
||||||
|
deleteDemandDrivenData(rotationPtr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointState::relax
|
||||||
|
(
|
||||||
|
const scalar alpha,
|
||||||
|
const lumpedPointState& prev
|
||||||
|
)
|
||||||
|
{
|
||||||
|
points_ = prev.points_ + alpha*(points_ - prev.points_);
|
||||||
|
|
||||||
|
scalar convert = 1.0;
|
||||||
|
if (degrees_ != prev.degrees_)
|
||||||
|
{
|
||||||
|
if (prev.degrees_)
|
||||||
|
{
|
||||||
|
// Was degrees, now radians
|
||||||
|
convert = degToRad(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Was radians, now degrees
|
||||||
|
convert = radToDeg(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
angles_ = convert*prev.angles_ + alpha*(angles_ - convert*prev.angles_);
|
||||||
|
|
||||||
|
deleteDemandDrivenData(rotationPtr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointState::readPlain(Istream& is)
|
||||||
|
{
|
||||||
|
// Assume generic input stream so we can do line-based input
|
||||||
|
ISstream& iss = dynamic_cast<ISstream&>(is);
|
||||||
|
|
||||||
|
string line = getLineNoComment(iss);
|
||||||
|
|
||||||
|
label count;
|
||||||
|
{
|
||||||
|
IStringStream isstr(line);
|
||||||
|
isstr >> count;
|
||||||
|
}
|
||||||
|
|
||||||
|
points_.setSize(count);
|
||||||
|
angles_.setSize(count);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
forAll(points_, i)
|
||||||
|
{
|
||||||
|
iss.getLine(line);
|
||||||
|
IStringStream isstr(line);
|
||||||
|
|
||||||
|
isstr
|
||||||
|
>> points_[count].x() >> points_[count].y() >> points_[count].z()
|
||||||
|
>> angles_[count].x() >> angles_[count].y() >> angles_[count].z();
|
||||||
|
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
points_.setSize(count);
|
||||||
|
angles_.setSize(count);
|
||||||
|
|
||||||
|
degrees_ = false;
|
||||||
|
deleteDemandDrivenData(rotationPtr_);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointState::readData(Istream& is)
|
||||||
|
{
|
||||||
|
dictionary dict(is);
|
||||||
|
readDict(dict);
|
||||||
|
|
||||||
|
return points_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointState::writeData(Ostream& os) const
|
||||||
|
{
|
||||||
|
writeDict(os);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointState::writeDict(Ostream& os) const
|
||||||
|
{
|
||||||
|
os.writeEntry("points", points_);
|
||||||
|
os.writeEntry("angles", angles_);
|
||||||
|
if (degrees_)
|
||||||
|
{
|
||||||
|
os.writeKeyword("degrees") << "true;" << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::lumpedPointState::writePlain(Ostream& os) const
|
||||||
|
{
|
||||||
|
os <<"# input for OpenFOAM\n"
|
||||||
|
<<"# N, points, angles\n"
|
||||||
|
<< points_.size() << "\n";
|
||||||
|
|
||||||
|
forAll(points_, i)
|
||||||
|
{
|
||||||
|
const vector& pt = points_[i];
|
||||||
|
|
||||||
|
os << pt.x() << ' '
|
||||||
|
<< pt.y() << ' '
|
||||||
|
<< pt.z() << ' ';
|
||||||
|
|
||||||
|
if (i < angles_.size())
|
||||||
|
{
|
||||||
|
os << angles_[i].x() << ' '
|
||||||
|
<< angles_[i].y() << ' '
|
||||||
|
<< angles_[i].z() << '\n';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << "0 0 0\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::lumpedPointState::readData
|
||||||
|
(
|
||||||
|
const inputFormatType& fmt,
|
||||||
|
const fileName& file
|
||||||
|
)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
IFstream is(file);
|
||||||
|
|
||||||
|
if (fmt == inputFormatType::PLAIN)
|
||||||
|
{
|
||||||
|
ok = this->readPlain(is);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok = this->readData(is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Pstream::parRun())
|
||||||
|
{
|
||||||
|
// Scatter master data using communication scheme
|
||||||
|
|
||||||
|
const List<Pstream::commsStruct>& comms =
|
||||||
|
(
|
||||||
|
(Pstream::nProcs() < Pstream::nProcsSimpleSum)
|
||||||
|
? Pstream::linearCommunication()
|
||||||
|
: Pstream::treeCommunication()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get my communication order
|
||||||
|
const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
|
||||||
|
|
||||||
|
// Receive from up
|
||||||
|
if (myComm.above() != -1)
|
||||||
|
{
|
||||||
|
IPstream fromAbove
|
||||||
|
(
|
||||||
|
UPstream::commsTypes::scheduled,
|
||||||
|
myComm.above(),
|
||||||
|
0,
|
||||||
|
Pstream::msgType(),
|
||||||
|
Pstream::worldComm
|
||||||
|
);
|
||||||
|
|
||||||
|
fromAbove >> points_ >> angles_ >> degrees_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send to downstairs neighbours
|
||||||
|
forAllReverse(myComm.below(), belowI)
|
||||||
|
{
|
||||||
|
OPstream toBelow
|
||||||
|
(
|
||||||
|
UPstream::commsTypes::scheduled,
|
||||||
|
myComm.below()[belowI],
|
||||||
|
0,
|
||||||
|
Pstream::msgType(),
|
||||||
|
Pstream::worldComm
|
||||||
|
);
|
||||||
|
|
||||||
|
toBelow << points_ << angles_ << degrees_;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteDemandDrivenData(rotationPtr_);
|
||||||
|
|
||||||
|
// MPI barrier
|
||||||
|
Pstream::scatter(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
194
src/lumpedPointMotion/lumpedPointState.H
Normal file
194
src/lumpedPointMotion/lumpedPointState.H
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::lumpedPointState
|
||||||
|
|
||||||
|
Description
|
||||||
|
The 'state' of lumped points corresponds to positions and rotations.
|
||||||
|
|
||||||
|
Encapsulates the response from the external application.
|
||||||
|
Entry place for applying relaxation and sub-stepping etc.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
lumpedPointState.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef lumpedPointState_H
|
||||||
|
#define lumpedPointState_H
|
||||||
|
|
||||||
|
#include "dictionary.H"
|
||||||
|
#include "scalarList.H"
|
||||||
|
#include "pointField.H"
|
||||||
|
#include "scalarField.H"
|
||||||
|
#include "vectorField.H"
|
||||||
|
#include "tensorField.H"
|
||||||
|
#include "Enum.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
class Istream;
|
||||||
|
class Ostream;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class lumpedPointState Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//- Bundling of position/rotation
|
||||||
|
class lumpedPointState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Input format types
|
||||||
|
enum class inputFormatType
|
||||||
|
{
|
||||||
|
PLAIN,
|
||||||
|
DICTIONARY
|
||||||
|
};
|
||||||
|
|
||||||
|
// Static data
|
||||||
|
|
||||||
|
//- Names for the input format types
|
||||||
|
static const Enum<inputFormatType> formatNames;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- Positions of lumped points
|
||||||
|
pointField points_;
|
||||||
|
|
||||||
|
//- Orientation of lumped points (as Euler angles)
|
||||||
|
vectorField angles_;
|
||||||
|
|
||||||
|
//- Euler angles in degrees instead radians
|
||||||
|
bool degrees_;
|
||||||
|
|
||||||
|
//- Tensor rotation of lumped points
|
||||||
|
mutable tensorField* rotationPtr_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
void calcRotations() const;
|
||||||
|
|
||||||
|
void readDict(const dictionary& dict);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct null
|
||||||
|
lumpedPointState();
|
||||||
|
|
||||||
|
//- Copy constructor
|
||||||
|
lumpedPointState(const lumpedPointState& rhs);
|
||||||
|
|
||||||
|
//- Construct from points with zero-rotation
|
||||||
|
lumpedPointState(const pointField& pts);
|
||||||
|
|
||||||
|
//- Construct from points with zero-rotation
|
||||||
|
lumpedPointState(tmp<pointField>& pts);
|
||||||
|
|
||||||
|
//- Construct from dictionary
|
||||||
|
lumpedPointState(const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~lumpedPointState();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Has positions and consistent number of rotations?
|
||||||
|
inline bool valid() const;
|
||||||
|
|
||||||
|
//- If no points were specified
|
||||||
|
inline bool empty() const;
|
||||||
|
|
||||||
|
//- The number of points
|
||||||
|
inline label size() const;
|
||||||
|
|
||||||
|
//- The points corresponding to mass centres
|
||||||
|
inline const pointField& points() const;
|
||||||
|
|
||||||
|
//- The orientation of the points (mass centres)
|
||||||
|
inline const vectorField& angles() const;
|
||||||
|
|
||||||
|
//- The local-to-global transformation for each point
|
||||||
|
inline const tensorField& rotations() const;
|
||||||
|
|
||||||
|
//- Relax the state
|
||||||
|
// alpha = 1 : no relaxation
|
||||||
|
// alpha < 1 : relaxation
|
||||||
|
// alpha = 0 : do nothing
|
||||||
|
void relax(const scalar alpha, const lumpedPointState& prev);
|
||||||
|
|
||||||
|
|
||||||
|
//- Read input as dictionary content
|
||||||
|
bool readData(Istream& is);
|
||||||
|
|
||||||
|
//- Output as dictionary content
|
||||||
|
bool writeData(Ostream& os) const;
|
||||||
|
|
||||||
|
//- Output as dictionary content
|
||||||
|
void writeDict(Ostream& os) const;
|
||||||
|
|
||||||
|
//- Read input as plain content
|
||||||
|
bool readPlain(Istream& is);
|
||||||
|
|
||||||
|
//- Output as plain content
|
||||||
|
void writePlain(Ostream& os) const;
|
||||||
|
|
||||||
|
//- Read input from file (master process only) using specified format
|
||||||
|
bool readData(const inputFormatType& fmt, const fileName& file);
|
||||||
|
|
||||||
|
//- Output as VTK file for debugging/visualization
|
||||||
|
// The points are joined as lines, the rotation is visualized
|
||||||
|
// by planes, write as VTK PolyData format.
|
||||||
|
void writeVTP(const fileName& outputFile, const vector& axis) const;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Operators
|
||||||
|
|
||||||
|
//- Assignment operator
|
||||||
|
void operator=(const lumpedPointState& rhs);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#include "lumpedPointStateI.H"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
67
src/lumpedPointMotion/lumpedPointStateI.H
Normal file
67
src/lumpedPointMotion/lumpedPointStateI.H
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
inline bool Foam::lumpedPointState::valid() const
|
||||||
|
{
|
||||||
|
return points_.size() && points_.size() == angles_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::lumpedPointState::empty() const
|
||||||
|
{
|
||||||
|
return points_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::label Foam::lumpedPointState::size() const
|
||||||
|
{
|
||||||
|
return points_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::pointField& Foam::lumpedPointState::points() const
|
||||||
|
{
|
||||||
|
return points_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::vectorField& Foam::lumpedPointState::angles() const
|
||||||
|
{
|
||||||
|
return angles_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::tensorField& Foam::lumpedPointState::rotations() const
|
||||||
|
{
|
||||||
|
if (!rotationPtr_)
|
||||||
|
{
|
||||||
|
calcRotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *rotationPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
326
src/lumpedPointMotion/lumpedPointStateWriter.C
Normal file
326
src/lumpedPointMotion/lumpedPointStateWriter.C
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "lumpedPointState.H"
|
||||||
|
#include "OFstream.H"
|
||||||
|
#include "axesRotation.H"
|
||||||
|
|
||||||
|
#include "foamVtkOutput.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// file-local
|
||||||
|
const static Foam::FixedList<Foam::point, 4> standardCorners
|
||||||
|
{
|
||||||
|
{-0.1, -0.1, 0},
|
||||||
|
{+0.1, -0.1, 0},
|
||||||
|
{+0.1, +0.1, 0},
|
||||||
|
{-0.1, +0.1, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::lumpedPointState::writeVTP
|
||||||
|
(
|
||||||
|
const fileName& outputFile,
|
||||||
|
const vector& axis
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// local-to-global transformation tensors
|
||||||
|
const tensorField& localToGlobal = rotations();
|
||||||
|
|
||||||
|
OFstream fos(outputFile);
|
||||||
|
std::ostream& os = fos.stdStream();
|
||||||
|
|
||||||
|
autoPtr<vtk::formatter> format = vtk::newFormatter
|
||||||
|
(
|
||||||
|
os,
|
||||||
|
vtk::formatType::INLINE_ASCII
|
||||||
|
);
|
||||||
|
|
||||||
|
format().xmlHeader()
|
||||||
|
.beginVTKFile(vtk::fileTag::POLY_DATA, "0.1");
|
||||||
|
|
||||||
|
//
|
||||||
|
// The 'spine' of lumped mass points
|
||||||
|
//
|
||||||
|
{
|
||||||
|
format()
|
||||||
|
.openTag(vtk::fileTag::PIECE)
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, points_.size())
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_VERTS, points_.size())
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_LINES, 1)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
// 'points'
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (points_.size()*3* sizeof(float));
|
||||||
|
|
||||||
|
format()
|
||||||
|
.tag(vtk::fileTag::POINTS)
|
||||||
|
.openDataArray<float, 3>(vtk::dataArrayAttr::POINTS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
vtk::writeList(format(), points_);
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format()
|
||||||
|
.endDataArray()
|
||||||
|
.endTag(vtk::fileTag::POINTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Verts>
|
||||||
|
format().tag(vtk::fileTag::VERTS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'connectivity'
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (points_.size()*sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
forAll(points_, i)
|
||||||
|
{
|
||||||
|
format().write(i);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'offsets' (connectivity offsets)
|
||||||
|
// = linear mapping onto points (with 1 offset)
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (points_.size()*sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::OFFSETS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
forAll(points_, i)
|
||||||
|
{
|
||||||
|
format().write(i+1);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::VERTS);
|
||||||
|
// </Verts>
|
||||||
|
|
||||||
|
|
||||||
|
// <Lines>
|
||||||
|
format().tag(vtk::fileTag::LINES);
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'connectivity'
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (points_.size()*sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
forAll(points_, i)
|
||||||
|
{
|
||||||
|
format().write(i);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'offsets' (connectivity offsets)
|
||||||
|
// = single line
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (1*sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::OFFSETS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
format().write(points_.size());
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::LINES);
|
||||||
|
format().endTag(vtk::fileTag::PIECE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard corners in local axis
|
||||||
|
const axesRotation cornerTransform(axis);
|
||||||
|
|
||||||
|
FixedList<point, 4> corners;
|
||||||
|
forAll(standardCorners, corni)
|
||||||
|
{
|
||||||
|
corners[corni] = cornerTransform.transform(standardCorners[corni]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Planes to visualize location/rotation
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const label nPoints = 4*points_.size(); // 4 points per quad
|
||||||
|
const label nPolys = points_.size();
|
||||||
|
|
||||||
|
format()
|
||||||
|
.openTag(vtk::fileTag::PIECE)
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_POINTS, nPoints)
|
||||||
|
.xmlAttr(vtk::fileAttr::NUMBER_OF_POLYS, nPolys)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
// 'points'
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (nPoints*3*sizeof(float));
|
||||||
|
|
||||||
|
format()
|
||||||
|
.tag(vtk::fileTag::POINTS)
|
||||||
|
.openDataArray<float, 3>(vtk::dataArrayAttr::POINTS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
|
||||||
|
forAll(points_, posI)
|
||||||
|
{
|
||||||
|
const point& origin = points_[posI];
|
||||||
|
const tensor& rotTensor =
|
||||||
|
(
|
||||||
|
posI < localToGlobal.size()
|
||||||
|
? localToGlobal[posI]
|
||||||
|
: pTraits<tensor>::I
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
for (const point& cornerPt : corners)
|
||||||
|
{
|
||||||
|
// Local-to-global rotation and translation
|
||||||
|
const point pt = (rotTensor & cornerPt) + origin;
|
||||||
|
|
||||||
|
vtk::write(format(), pt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format()
|
||||||
|
.endDataArray()
|
||||||
|
.endTag(vtk::fileTag::POINTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <Polys>
|
||||||
|
format().tag(vtk::fileTag::POLYS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'connectivity' - 4 points (ie, quad)
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (4*nPolys*sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::CONNECTIVITY)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
for (label i=0; i < 4*nPolys; ++i)
|
||||||
|
{
|
||||||
|
format().write(i);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'offsets' (connectivity offsets)
|
||||||
|
// = single quad
|
||||||
|
//
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (nPolys*sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>(vtk::dataArrayAttr::OFFSETS)
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
for (label i=0; i < nPolys; ++i)
|
||||||
|
{
|
||||||
|
const label off = 4 * (i+1);
|
||||||
|
format().write(off);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::POLYS);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
format().tag(vtk::fileTag::CELL_DATA);
|
||||||
|
|
||||||
|
// zone Id
|
||||||
|
{
|
||||||
|
const uint64_t payLoad = (points_.size()*sizeof(label));
|
||||||
|
|
||||||
|
format().openDataArray<label>("zoneId")
|
||||||
|
.closeTag();
|
||||||
|
|
||||||
|
format().writeSize(payLoad);
|
||||||
|
for (label i=0; i < nPolys; ++i)
|
||||||
|
{
|
||||||
|
format().write(i);
|
||||||
|
}
|
||||||
|
format().flush();
|
||||||
|
|
||||||
|
format().endDataArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::CELL_DATA);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::PIECE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally
|
||||||
|
// could add a 'ghost' level above to visualize extrapolated values
|
||||||
|
// draw as two triangles to distingush from real levels ...
|
||||||
|
|
||||||
|
format().endTag(vtk::fileTag::POLY_DATA);
|
||||||
|
format().endVTKFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
161
src/lumpedPointMotion/lumpedPointTools.C
Normal file
161
src/lumpedPointMotion/lumpedPointTools.C
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "lumpedPointTools.H"
|
||||||
|
#include "IFstream.H"
|
||||||
|
#include "IOobjectList.H"
|
||||||
|
#include "volFields.H"
|
||||||
|
|
||||||
|
#include "lumpedPointDisplacementPointPatchVectorField.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
// file-scope
|
||||||
|
template<class GeoFieldType>
|
||||||
|
static autoPtr<GeoFieldType> loadPointField
|
||||||
|
(
|
||||||
|
const pointMesh::Mesh& mesh,
|
||||||
|
const IOobject* io
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (io && io->headerClassName() == GeoFieldType::typeName)
|
||||||
|
{
|
||||||
|
Info<< "Reading " << GeoFieldType::typeName
|
||||||
|
<< ' ' << io->name() << endl;
|
||||||
|
|
||||||
|
return autoPtr<GeoFieldType>
|
||||||
|
(
|
||||||
|
new GeoFieldType
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
io->name(),
|
||||||
|
io->instance(),
|
||||||
|
io->local(),
|
||||||
|
io->db(),
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE,
|
||||||
|
io->registerObject()
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return autoPtr<GeoFieldType>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::List<Foam::lumpedPointStateTuple>
|
||||||
|
Foam::lumpedPointTools::lumpedPointStates(Istream& is)
|
||||||
|
{
|
||||||
|
dictionary contents(is);
|
||||||
|
List<dictionary> entries(contents.lookup("response"));
|
||||||
|
|
||||||
|
DynamicList<Tuple2<scalar, lumpedPointState>> states(entries.size());
|
||||||
|
|
||||||
|
for (const dictionary& dict : entries)
|
||||||
|
{
|
||||||
|
states.append
|
||||||
|
(
|
||||||
|
lumpedPointStateTuple
|
||||||
|
(
|
||||||
|
readScalar(dict.lookup("time")),
|
||||||
|
lumpedPointState(dict)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return states.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::List<Foam::lumpedPointStateTuple>
|
||||||
|
Foam::lumpedPointTools::lumpedPointStates(const fileName& file)
|
||||||
|
{
|
||||||
|
IFstream is(file);
|
||||||
|
return lumpedPointStates(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::pointIOField
|
||||||
|
Foam::lumpedPointTools::points0Field(const polyMesh& mesh)
|
||||||
|
{
|
||||||
|
pointIOField pts
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"points",
|
||||||
|
mesh.time().constant(),
|
||||||
|
polyMesh::meshSubDir,
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false // Do not re-register
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return pts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Foam::labelList
|
||||||
|
Foam::lumpedPointTools::lumpedPointPatchList(const pointVectorField& pvf)
|
||||||
|
{
|
||||||
|
return lumpedPointDisplacementPointPatchVectorField::patchIds(pvf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::labelList Foam::lumpedPointTools::lumpedPointPatchList
|
||||||
|
(
|
||||||
|
const polyMesh& mesh
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IOobjectList objects0(mesh, "0");
|
||||||
|
|
||||||
|
pointMesh pMesh(mesh);
|
||||||
|
|
||||||
|
autoPtr<pointVectorField> displacePtr = loadPointField<pointVectorField>
|
||||||
|
(
|
||||||
|
pMesh,
|
||||||
|
objects0.lookup("pointDisplacement")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!displacePtr.valid())
|
||||||
|
{
|
||||||
|
Info<< "no valid pointDisplacement" << endl;
|
||||||
|
return labelList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return lumpedPointPatchList(displacePtr());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
86
src/lumpedPointMotion/lumpedPointTools.H
Normal file
86
src/lumpedPointMotion/lumpedPointTools.H
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
|
||||||
|
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Namespace
|
||||||
|
Foam::lumpedPointTools
|
||||||
|
|
||||||
|
Description
|
||||||
|
A collection of utility functions for handling IO related to the
|
||||||
|
lumped-mass movement.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
lumpedPointTools.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef lumpedPointTools_H
|
||||||
|
#define lumpedPointTools_H
|
||||||
|
|
||||||
|
#include "labelList.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "pointMesh.H"
|
||||||
|
#include "pointFields.H"
|
||||||
|
#include "Tuple2.H"
|
||||||
|
|
||||||
|
#include "lumpedPointState.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef Tuple2<scalar, lumpedPointState> lumpedPointStateTuple;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace lumpedPointTools
|
||||||
|
{
|
||||||
|
|
||||||
|
//- Load a list of states from an Istream
|
||||||
|
List<lumpedPointStateTuple> lumpedPointStates(Istream& is);
|
||||||
|
|
||||||
|
//- Load a list of states from a file
|
||||||
|
List<lumpedPointStateTuple> lumpedPointStates(const fileName& file);
|
||||||
|
|
||||||
|
|
||||||
|
//- Return the 0 or constant points field
|
||||||
|
pointIOField points0Field(const polyMesh& mesh);
|
||||||
|
|
||||||
|
//- Return the patch-ids associated a "lumpedPointDisplacement" type
|
||||||
|
labelList lumpedPointPatchList(const pointVectorField& pvf);
|
||||||
|
|
||||||
|
//- Get the "pointDisplacement" at time 0 and use that to determine which
|
||||||
|
// patches have a "lumpedPointDisplacement" type
|
||||||
|
labelList lumpedPointPatchList(const polyMesh& mesh);
|
||||||
|
|
||||||
|
} // End namespace lumpedPointTools
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
Reference in New Issue
Block a user