From d0c566217220f7d902cf466fb9bac0722d316fbe Mon Sep 17 00:00:00 2001 From: Gabriel Barajas <> Date: Sat, 7 Dec 2019 09:19:26 +0000 Subject: [PATCH] INT: Initial IHCantabria update for waveMaker BC Adds support for paddles to generate 3-D waves --- .../waveMakerPointPatchVectorField.C | 269 ++++++++++++++---- .../waveMakerPointPatchVectorField.H | 55 +++- 2 files changed, 262 insertions(+), 62 deletions(-) diff --git a/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.C b/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.C index 301c1e2b21f..609ba79d533 100644 --- a/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.C +++ b/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.C @@ -33,6 +33,10 @@ License #include "Time.H" #include "gravityMeshObject.H" +#include "polyMesh.H" +#include "surfaceFields.H" +#include "volFields.H" + // * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * // const Foam::Enum<Foam::waveMakerPointPatchVectorField::motionTypes> @@ -89,6 +93,48 @@ Foam::scalar Foam::waveMakerPointPatchVectorField::timeCoeff } +void Foam::waveMakerPointPatchVectorField::initialiseGeometry() +{ + // Global patch extents + const vectorField& Cp = this->patch().localPoints(); + const vectorField CpLocal(Cp); + boundBox bb(CpLocal, true); + + const scalar xMin = bb.min().x(); + const scalar xMax = bb.max().x(); + const scalar yMin = bb.min().y(); + const scalar yMax = bb.max().y(); + zSpan_ = bb.max().z() - bb.min().z(); + + zMinGb_ = bb.min().z(); + reduce(zMinGb_, minOp<scalar>()); + + // Global x, y positions of the paddle centres + xPaddle_.setSize(nPaddle_, 0); + yPaddle_.setSize(nPaddle_, 0); + const scalar xMid = xMin + 0.5*(xMax - xMin); + const scalar paddleDy = (yMax - yMin)/scalar(nPaddle_); + + for (label paddlei = 0; paddlei < nPaddle_; ++paddlei) + { + xPaddle_[paddlei] = xMid; + yPaddle_[paddlei] = paddlei*paddleDy + yMin + 0.5*paddleDy; + } + + // Local face centres + x_ = this->patch().localPoints().component(0); + y_ = this->patch().localPoints().component(1); + z_ = this->patch().localPoints().component(2); + + // Local point-to-paddle addressing + pointToPaddle_.setSize(this->patch().size(), -1); + + forAll(pointToPaddle_, ppi) + { + pointToPaddle_[ppi] = floor((y_[ppi] - yMin)/(paddleDy+0.01*paddleDy)); + } +} + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::waveMakerPointPatchVectorField::waveMakerPointPatchVectorField @@ -105,10 +151,11 @@ Foam::waveMakerPointPatchVectorField::waveMakerPointPatchVectorField wavePeriod_(0), waveHeight_(0), wavePhase_(0), - waveLength_(0), + waveAngle_(0), startTime_(0), rampTime_(1), - secondOrder_(false) + secondOrder_(false), + nPaddle_(0) {} @@ -127,7 +174,7 @@ Foam::waveMakerPointPatchVectorField::waveMakerPointPatchVectorField wavePeriod_(dict.get<scalar>("wavePeriod")), waveHeight_(dict.get<scalar>("waveHeight")), wavePhase_(dict.get<scalar>("wavePhase")), - waveLength_(this->waveLength(initialDepth_, wavePeriod_)), + waveAngle_(dict.get<scalar>("waveAngle")), startTime_ ( dict.lookupOrDefault<scalar> @@ -137,7 +184,8 @@ Foam::waveMakerPointPatchVectorField::waveMakerPointPatchVectorField ) ), rampTime_(dict.get<scalar>("rampTime")), - secondOrder_(dict.lookupOrDefault<bool>("secondOrder", false)) + secondOrder_(dict.lookupOrDefault<bool>("secondOrder", false)), + nPaddle_(readScalar(dict.lookup("nPaddle"))) { // Create the co-ordinate system if (mag(n_) < SMALL) @@ -151,6 +199,13 @@ Foam::waveMakerPointPatchVectorField::waveMakerPointPatchVectorField gHat_ = (g() - n_*(n_&g())); gHat_ /= mag(gHat_); + waveAngle_ *= constant::mathematical::pi/180; + + Info << " Initialise geometry... " << endl; + initialiseGeometry(); + + waterDepthRef_.setSize(nPaddle_, -1); + if (!dict.found("value")) { updateCoeffs(); @@ -174,10 +229,11 @@ Foam::waveMakerPointPatchVectorField::waveMakerPointPatchVectorField wavePeriod_(ptf.wavePeriod_), waveHeight_(ptf.waveHeight_), wavePhase_(ptf.wavePhase_), - waveLength_(ptf.waveLength_), + waveAngle_(ptf.waveAngle_), startTime_(ptf.startTime_), rampTime_(ptf.rampTime_), - secondOrder_(ptf.secondOrder_) + secondOrder_(ptf.secondOrder_), + nPaddle_(ptf.nPaddle_) {} @@ -195,10 +251,11 @@ Foam::waveMakerPointPatchVectorField::waveMakerPointPatchVectorField wavePeriod_(ptf.wavePeriod_), waveHeight_(ptf.waveHeight_), wavePhase_(ptf.wavePhase_), - waveLength_(ptf.waveLength_), + waveAngle_(ptf.waveAngle_), startTime_(ptf.startTime_), rampTime_(ptf.rampTime_), - secondOrder_(ptf.secondOrder_) + secondOrder_(ptf.secondOrder_), + nPaddle_(ptf.nPaddle_) {} @@ -211,86 +268,174 @@ void Foam::waveMakerPointPatchVectorField::updateCoeffs() return; } + if (firstTime==0) + { + // Set the reference water depth + if (initialDepth_ != 0 ) + { + forAll(waterDepthRef_,paddlei) + { + waterDepthRef_[paddlei] = initialDepth_; + } + } + else + { + FatalErrorInFunction + << "initialDepth is not set. Please update " + << abort(FatalError); + } + + + Info << " WaterDepth at the wavepaddles = " << waterDepthRef_ << endl; + firstTime = 1; + } + const scalar t = db().time().value() - startTime_; - const scalar waveK = constant::mathematical::twoPi/waveLength_; - const scalar sigma = constant::mathematical::twoPi/wavePeriod_; + scalarField waveLength_(nPaddle_,-1); - const scalar kh = waveK*initialDepth_; + scalarField waveK(nPaddle_,-1); + scalarField waveKx(nPaddle_,-1); + scalarField waveKy(nPaddle_,-1); + + forAll (waveK, labelP) + { + waveLength_[labelP] = waveLength (waterDepthRef_[labelP], wavePeriod_); + + waveK[labelP] = constant::mathematical::twoPi/waveLength_[labelP]; + waveKx[labelP] = waveK[labelP]*cos(waveAngle_); + waveKy[labelP] = waveK[labelP]*sin(waveAngle_); + } + const scalar sigma_ = (2.0*constant::mathematical::pi) / wavePeriod_; switch (motionType_) { case motionTypes::flap: { - const scalar m1 = - 4*sinh(kh)/(sinh(2*kh) + 2*kh)*(sinh(kh) + (1 - cosh(kh))/kh); - - scalar motionX = 0.5*waveHeight_/m1*sin(sigma*t); - - if (secondOrder_) - { - motionX += - sqr(waveHeight_)/(16*initialDepth_) - *(3*cosh(kh)/pow3(sinh(kh)) - 2/m1) - *sin(2*sigma*t); - } - const pointField& points = patch().localPoints(); - const scalarField dz(-(points & gHat_) - initialDepth_); + scalarField motionX (patch().localPoints().size(),-1); + + forAll (points, labelP) + { + + const label paddlei = pointToPaddle_[labelP]; + + scalar phaseTot = waveKx[paddlei]*xPaddle_[paddlei] + waveKy[paddlei]*yPaddle_[paddlei]; + + if (secondOrder_) + { + scalar m1_ = ((4.0*sinh(waveK[paddlei]*waterDepthRef_[paddlei])) + / (sinh(2.0*waveK[paddlei]*waterDepthRef_[paddlei])+2.0*waveK[paddlei]*waterDepthRef_[paddlei])) + * ( sinh(waveK[paddlei]*waterDepthRef_[paddlei]) + 1.0/(waveK[paddlei]*waterDepthRef_[paddlei]) + * (1.0-cosh(waveK[paddlei]*waterDepthRef_[paddlei]))); + + motionX[labelP] = waveHeight_/(2.0*m1_)*sin(phaseTot - sigma_*t) + + pow(waveHeight_,2)/(16.0*waterDepthRef_[paddlei])*(3.0*cosh(waveK[paddlei]*waterDepthRef_[paddlei]) + / pow(sinh(waveK[paddlei]*waterDepthRef_[paddlei]),3) -2.0/m1_)*sin(phaseTot - 2.0*sigma_*t); + + motionX[labelP] = timeCoeff(t) + * (1.0+((points[labelP].component(2)-zMinGb_)-waterDepthRef_[paddlei]) + / (waterDepthRef_[paddlei])) * motionX[labelP]; + } + else + { + scalar waveBoardStroke_ = (sinh(2.0*waveK[paddlei]*waterDepthRef_[paddlei]) + + 2.0*waveK[paddlei]*waterDepthRef_[paddlei]) + / (4.0*sinh(waveK[paddlei]*waterDepthRef_[paddlei])) + * (1.0 / ( sinh(waveK[paddlei]*waterDepthRef_[paddlei]) + + (1.0-cosh(waveK[paddlei]*waterDepthRef_[paddlei])) + / (waveK[paddlei]*waterDepthRef_[paddlei]) ) ) * waveHeight_; + + motionX[labelP] = timeCoeff(t) + * (1.0+((points[labelP].component(2)-zMinGb_)-waterDepthRef_[paddlei]) + / (waterDepthRef_[paddlei]))*(waveBoardStroke_/2.0)*sin(phaseTot-sigma_*t); + } + + } Field<vector>::operator= ( - n_*timeCoeff(t)*motionX*(1 + dz/initialDepth_) + n_*motionX ); break; } case motionTypes::piston: { - const scalar m1 = 2*(cosh(2*kh) - 1)/(sinh(2*kh) + 2*kh); - - scalar motionX = 0.5*waveHeight_/m1*sin(sigma*t); - - if (secondOrder_) - { - motionX += - sqr(waveHeight_) - /(32*initialDepth_)*(3*cosh(kh) - /pow3(sinh(kh)) - 2/m1); - } - - Field<vector>::operator=(n_*timeCoeff(t)*motionX); + const pointField& points = patch().localPoints(); + scalarField motionX (patch().localPoints().size(),-1); + + forAll (points, labelP) + { + const label paddlei = pointToPaddle_[labelP]; + + scalar phaseTot = waveKx[paddlei]*xPaddle_[paddlei] + waveKy[paddlei]*yPaddle_[paddlei]; + + if (secondOrder_) + { + const scalar m1_ = 2.0*(cosh(2.0*waveK[paddlei]*waterDepthRef_[paddlei]) - 1.0) + / (sinh(2.0*waveK[paddlei]*waterDepthRef_[paddlei]) + + 2.0*waveK[paddlei]*waterDepthRef_[paddlei]); + + motionX[labelP] = timeCoeff(t) * (waveHeight_/(2.0*m1_) + * sin(phaseTot - sigma_*t) + pow(waveHeight_,2) + / (32.0*waterDepthRef_[paddlei])*(3.0*cosh(waveK[paddlei]*waterDepthRef_[paddlei]) + / pow(sinh(waveK[paddlei]*waterDepthRef_[paddlei]),3)-2.0/m1_) + * sin(phaseTot - 2.0*sigma_*t)); + } + else + { + scalar waveBoardStroke_ = (sinh(2.0*waveK[paddlei]*waterDepthRef_[paddlei]) + + 2.0*waveK[paddlei]*waterDepthRef_[paddlei]) + / (2.0*(cosh(2.0*waveK[paddlei]*waterDepthRef_[paddlei]) + - 1.0)) * waveHeight_; + motionX[labelP] = timeCoeff(t)*(waveBoardStroke_/2.0) + * sin(phaseTot-sigma_*t); + } + } + + Field<vector>::operator= + ( + n_*motionX + ); break; } case motionTypes::solitary: { - const scalar kappa = sqrt(0.75*waveHeight_/(pow3(initialDepth_))); - const scalar waveCelerity = - sqrt(mag(g())*(initialDepth_ + waveHeight_)); - const scalar stroke = sqrt(16.0*waveHeight_*initialDepth_/3.0); - const scalar hr = waveHeight_/initialDepth_; - wavePeriod_ = (2.0/(kappa*waveCelerity))*(3.8 + hr); - const scalar tSolitary = -0.5*wavePeriod_ + t; - - // Newton-Rapshon - scalar theta1 = 0; - scalar theta2 = 0; - scalar er = 10000; - const scalar error = 0.001; - while (er > error) - { - theta2 = - theta1 - - (theta1 - kappa*waveCelerity*tSolitary + hr*tanh(theta1)) - /(1.0 + hr*(1.0/cosh(theta1))*(1.0/cosh(theta1))); + const pointField& points = patch().localPoints(); + scalarField motionX (patch().localPoints().size(),-1); + + forAll (points, labelP) + { + const label paddlei = pointToPaddle_[labelP]; + + scalar kappa = sqrt(0.75*waveHeight_/(pow3(waterDepthRef_[paddlei]))); + scalar waveCelerity = sqrt(mag(g())*(waterDepthRef_[paddlei] + waveHeight_)); + scalar stroke = sqrt(16.0*waveHeight_*waterDepthRef_[paddlei]/3.0); + scalar hr = waveHeight_/waterDepthRef_[paddlei]; + wavePeriod_ = (2.0/(kappa*waveCelerity))*(3.8 + hr); + scalar tSolitary = -0.5*wavePeriod_ + t; + + // Newton-Rapshon + scalar theta1 = 0; + scalar theta2 = 0; + scalar er = 10000; + const scalar error = 0.001; + while (er > error) + { + theta2 = + theta1 + - (theta1 - kappa*waveCelerity*tSolitary + hr*tanh(theta1)) + /(1.0 + hr*(1.0/cosh(theta1))*(1.0/cosh(theta1))); er = mag(theta1 - theta2); theta1 = theta2; - } + } - scalar motionX = - waveHeight_/(kappa*initialDepth_)*tanh(theta1) + 0.5*stroke; + motionX[labelP] = + waveHeight_/(kappa*waterDepthRef_[paddlei])*tanh(theta1) + 0.5*stroke; + } Field<vector>::operator=(n_*motionX); @@ -318,9 +463,11 @@ void Foam::waveMakerPointPatchVectorField::write(Ostream& os) const os.writeEntry("wavePeriod", wavePeriod_); os.writeEntry("waveHeight", waveHeight_); os.writeEntry("wavePhase", wavePhase_); + os.writeEntry("waveAngle", waveAngle_); os.writeEntry("startTime", startTime_); os.writeEntry("rampTime", rampTime_); os.writeEntry("secondOrder", secondOrder_); + os.writeEntry("nPaddle", nPaddle_); writeEntry("value", os); } diff --git a/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.H b/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.H index 2b0030c92ed..42108523eae 100644 --- a/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.H +++ b/src/waveModels/derivedPointPatchFields/waveMaker/waveMakerPointPatchVectorField.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2018-2019 IH-Cantabria - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018 ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -136,6 +136,9 @@ class waveMakerPointPatchVectorField //- Wave phase scalar wavePhase_; + //wave angle + scalar waveAngle_; + //- Wave length scalar waveLength_; @@ -148,6 +151,54 @@ class waveMakerPointPatchVectorField //- On/off second order calculation switch scalar secondOrder_; + // number wavepaddles + scalar nPaddle_; + + //- Rotation tensor from global to local system + tensor Rgl_; + + //- Rotation tensor from local to global system + tensor Rlg_; + + //- Paddle x co-ordinates / [m] + scalarField xPaddle_; + + //- Paddle y co-ordinates / [m] + scalarField yPaddle_; + + //- Addressing from point patch index to paddle index + labelList pointToPaddle_; + + //- Addressing from patch face index to paddle index + labelList faceToPaddle_; + + //- Patch face centre x co-ordinates / [m] + scalarField x_; + + //- Patch face centre y co-ordinates / [m] + scalarField y_; + + //- Patch face centre z co-ordinates / [m] + scalarField z_; + + //- Overall (point) span in z-direction / [m] + scalar zSpan_; + + //- Minimum z (point) height per patch face / [m] + scalarField zMin_; + + //- Global Minimum z (point) / [m] + scalar zMinGb_; + + //- Maximum z (point) height per patch face / [m] + scalarField zMax_; + + // calculated water depth at the patch + scalarField waterDepthRef_; + + // + scalar firstTime = 0; + // Protected Member Functions @@ -160,6 +211,8 @@ class waveMakerPointPatchVectorField //- Return the time scaling coefficient virtual scalar timeCoeff(const scalar t) const; + //- Initialise + virtual void initialiseGeometry(); public: -- GitLab