Files
openfoam/src/lumpedPointMotion/pointPatchFields/lumpedPointDisplacementPointPatchVectorField.C
Mark Olesen b0136d835e ENH: lumped point motion using local linear basic functions (#1341)
- the earlier implementation of externally controlled lumped point
  motion (see merge request !120 and OpenFOAM-v1706 release notes) was
  conceived for the motion of simple structures such as buildings or
  simple beams. The motion controller was simply defined in terms of
  an orientation axis and divisions along that axis.

  To include complex structures, multiple motion controllers are
  defined in terms of support points and connectivity.

  The points can have additional node Ids associated with them, which
  makes it easier to map to/from FEA models.

  OLD system/lumpedPointMovement specification
  --------------------------------------------

      //- Reference axis for the locations
      axis            (0 0 1);

      //- Locations of the lumped points
      locations       (0 0.05 .. 0.5);

  NEW system/lumpedPointMovement specification
  --------------------------------------------

      // Locations of the lumped points
      points
      (
          (0  0  0.00)
          (0  0  0.05)
          ...
          (0  0  0.50)
      );

      //- Connectivity for motion controllers
      controllers
      {
          vertical
          {
              pointLabels (0 1 2 3 4 5 6 7 8 9 10);
          }
      }

  And the controller(s) must be associated with the given
  pointDisplacement patch. Eg,

     somePatch
     {
         type            lumpedPointDisplacement;
         value           uniform (0 0 0);
         controllers     ( vertical );   // <-- NEW
     }

TUT: adjust building motion tutorial

- use new controllor definitions
- replace building response file with executable
- add updateControl in dynamicMeshDict for slowly moving structure
2020-06-17 15:16:27 +02:00

435 lines
11 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
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::label Foam::lumpedPointDisplacementPointPatchVectorField::setPatchControls
(
const pointVectorField& pvf,
const pointField& points0
)
{
label count = 0;
const pointVectorField::Boundary& bf = pvf.boundaryField();
const polyBoundaryMesh& patches = pvf.mesh().mesh().boundaryMesh();
forAll(bf, patchi)
{
// Patch of this type
const auto* p = isA<patchType>(bf[patchi]);
if (p)
{
// Patch controls (mapping) for calculating forces/moments
const_cast<lumpedPointMovement&>(p->movement())
.setPatchControl
(
patches[patchi],
p->controllers(),
points0
);
++count;
}
}
return count;
}
Foam::label Foam::lumpedPointDisplacementPointPatchVectorField::setInterpolators
(
const pointVectorField& pvf,
const pointField& points0
)
{
label count = 0;
const pointVectorField::Boundary& bf = pvf.boundaryField();
forAll(bf, patchi)
{
// Patch of this type
const auto* p = isA<patchType>(bf[patchi]);
if (p)
{
// Patch controls (mapping) for calculating forces/moments
const_cast<lumpedPointMovement&>(p->movement())
.setInterpolator
(
p->patch(),
points0
);
++count;
}
}
return count;
}
Foam::labelList
Foam::lumpedPointDisplacementPointPatchVectorField::patchIds
(
const pointVectorField& pvf
)
{
const pointVectorField::Boundary& bf = pvf.boundaryField();
DynamicList<label> patchLst(bf.size());
forAll(bf, patchi)
{
// Patch 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 (when possible)
const auto* solver =
obr.cfindObject<displacementMotionSolver>("dynamicMeshDict");
if (solver)
{
if (points0Ptr_)
{
points0Ptr_.reset(nullptr);
}
return solver->points0();
}
else if (!points0Ptr_)
{
points0Ptr_.reset
(
new pointIOField
(
points0MotionSolver::points0IO
(
this->patch().boundaryMesh().mesh().mesh()
)
)
);
}
return *points0Ptr_;
}
const Foam::lumpedPointMovement&
Foam::lumpedPointDisplacementPointPatchVectorField::movement() const
{
const objectRegistry& obr = this->patch().boundaryMesh().mesh().db();
lumpedPointIOMovement* ptr =
lumpedPointIOMovement::getMovementObject(obr);
if (ptr)
{
return *ptr; // Already exists
}
// Create and register with this patch as the owner
ptr = lumpedPointIOMovement::New(obr, this->patch().index()).ptr();
return objectRegistry::store(ptr);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::lumpedPointDisplacementPointPatchVectorField::
lumpedPointDisplacementPointPatchVectorField
(
const pointPatch& p,
const DimensionedField<vector, pointMesh>& iF
)
:
fixedValuePointPatchField<vector>(p, iF),
controllers_()
{}
Foam::lumpedPointDisplacementPointPatchVectorField::
lumpedPointDisplacementPointPatchVectorField
(
const pointPatch& p,
const DimensionedField<vector, pointMesh>& iF,
const dictionary& dict
)
:
fixedValuePointPatchField<vector>(p, iF, dict),
controllers_()
{
dict.readIfPresent("controllers", controllers_);
if (controllers_.empty())
{
WarningInFunction
<< "No controllers specified, using all lumped points for patch: "
<< this->patch().name() << nl << nl;
}
// controllers_ : check? remove duplicates?
}
Foam::lumpedPointDisplacementPointPatchVectorField::
lumpedPointDisplacementPointPatchVectorField
(
const lumpedPointDisplacementPointPatchVectorField& pf,
const pointPatch& p,
const DimensionedField<vector, pointMesh>& iF,
const pointPatchFieldMapper& mapper
)
:
fixedValuePointPatchField<vector>(pf, p, iF, mapper),
controllers_(pf.controllers_)
{}
Foam::lumpedPointDisplacementPointPatchVectorField::
lumpedPointDisplacementPointPatchVectorField
(
const lumpedPointDisplacementPointPatchVectorField& pf,
const DimensionedField<vector, pointMesh>& iF
)
:
fixedValuePointPatchField<vector>(pf, iF),
controllers_(pf.controllers_)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::lumpedPointDisplacementPointPatchVectorField::
~lumpedPointDisplacementPointPatchVectorField()
{
// de-register movement if in use and managed by this patch
lumpedPointIOMovement* ptr =
lumpedPointIOMovement::getMovementObject
(
this->patch().boundaryMesh().mesh().db()
);
if (ptr && ptr->ownerId() == this->patch().index())
{
movement().coupler().shutdown();
ptr->checkOut();
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::lumpedPointDisplacementPointPatchVectorField::updateCoeffs()
{
if (this->updated())
{
return;
}
const label timeIndex = this->db().time().timeIndex();
enum Time::stopAtControls action = Time::stopAtControls::saUnknown;
if (movement().ownerId() == this->patch().index())
{
// The ownerId is always the lowest patch number,
// thus will always be triggered first
if (lumpedPointMovement::debug)
{
Pout<<"masterPatch: " << this->patch().index() << endl;
}
const polyMesh& mesh = this->patch().boundaryMesh().mesh().mesh();
// Mapping for calculating forces
// as well as face point interpolation
if (!movement().hasMapping())
{
// Add mapping for calculating forces/moments
setPatchControls
(
static_cast<const pointVectorField&>
(
this->internalField()
),
this->points0()
);
}
int triggered = 0;
if
(
movement().coupler().slaveFirst()
&& !movement().coupler().initialized()
)
{
// Master does nothing yet, but slave will
triggered = -1;
}
else if (movement().couplingPending(timeIndex))
{
// Trigger is pending, or coupling not yet not initialized
triggered = 1;
}
if (triggered > 0)
{
// Synchronized for all processes
List<vector> forces, moments;
movement().forcesAndMoments(mesh, forces, moments);
if (lumpedPointMovement::debug)
{
Pout<<"gatherForces: " << forces << " called from patch "
<< this->patch().index() << endl;
if (Pstream::master())
{
Pout<<"output forces to file: 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, &(this->db().time()));
// Signal external source to execute
movement().coupler().useSlave();
}
}
if (triggered)
{
// Wait for slave to provide data (includes MPI barrier)
// and catch any abort information sent from slave
action = movement().coupler().waitForSlave();
const_cast<lumpedPointMovement&>(movement()).readState();
movement().couplingCompleted(timeIndex);
}
}
if (!movement().hasInterpolator(this->patch()))
{
const_cast<lumpedPointMovement&>(movement()).setInterpolator
(
this->patch(),
this->points0()
);
}
tmp<pointField> tdisp =
movement().pointsDisplacement
(
this->patch(),
this->points0()
);
this->operator==(tdisp);
fixedValuePointPatchField<vector>::updateCoeffs();
// Process any abort information sent from slave
if
(
action != this->db().time().stopAt()
&& action != Time::stopAtControls::saUnknown
)
{
this->db().time().stopAt(action);
}
}
void Foam::lumpedPointDisplacementPointPatchVectorField::write(Ostream& os)
const
{
pointPatchField<vector>::write(os);
if (controllers_.size())
{
os.writeEntry("controllers", controllers_);
}
writeEntry("value", os);
}
// ************************************************************************* //