/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | Website: https://openfoam.org \\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation \\/ 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 . \*---------------------------------------------------------------------------*/ #include "waveSuperposition.H" #include "uniformDimensionedFields.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::waveSuperposition::transformation ( const vectorField& p, tensor& axes, scalar& u, vectorField& xyz ) const { const uniformDimensionedVectorField& g = db_.lookupObject("g"); const scalar magG = mag(g.value()); const vector gHat = g.value()/magG; const vector dSurf = direction_ - gHat*(gHat & direction_); const scalar magDSurf = mag(dSurf); const vector dSurfHat = direction_/magDSurf; axes = tensor(dSurfHat, - gHat ^ dSurfHat, - gHat); u = speed_*magDSurf; xyz = axes & (p - origin_); } Foam::tmp Foam::waveSuperposition::elevation ( const scalar t, const vector2DField& xy ) const { scalarField result(xy.size(), 0); forAll(waveModels_, wavei) { const vector2D d(cos(waveAngles_[wavei]), sin(waveAngles_[wavei])); result += waveModels_[wavei].elevation(t, d.x()*speed_, d & xy); } return scale(xy)*result; } Foam::tmp Foam::waveSuperposition::velocity ( const scalar t, const vectorField& xyz ) const { vectorField result(xyz.size(), vector::zero); forAll(waveModels_, wavei) { const vector2D d(cos(waveAngles_[wavei]), sin(waveAngles_[wavei])); const vector2DField xz ( zip ( d & zip(xyz.component(0), xyz.component(1)), tmp(xyz.component(2)) ) ); const vector2DField uw ( waveModels_[wavei].velocity(t, d.x()*speed_, xz) ); result += zip ( d.x()*uw.component(0), d.y()*uw.component(0), uw.component(1) ); } tmp s = scale(zip(xyz.component(0), xyz.component(1))); return s*result; } Foam::tmp Foam::waveSuperposition::pressure ( const scalar t, const vectorField& xyz ) const { scalarField result(xyz.size(), 0); forAll(waveModels_, wavei) { const vector2D d(cos(waveAngles_[wavei]), sin(waveAngles_[wavei])); const vector2DField xz ( zip ( d & zip(xyz.component(0), xyz.component(1)), tmp(xyz.component(2)) ) ); const vector2DField uw ( waveModels_[wavei].velocity(t, d.x()*speed_, xz) ); result += waveModels_[wavei].pressure(t, d.x()*speed_, xz); } tmp s = scale(zip(xyz.component(0), xyz.component(1))); return s*result; } Foam::tmp Foam::waveSuperposition::scale ( const vector2DField& xy ) const { tmp tResult(new scalarField(xy.size(), 1)); scalarField& result = tResult.ref(); if (scale_.valid()) { const scalarField x(xy.component(0)); forAll(result, i) { result[i] *= scale_->value(x[i]); } } if (crossScale_.valid()) { const scalarField y(xy.component(1)); forAll(result, i) { result[i] *= crossScale_->value(y[i]); } } return tResult; } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::waveSuperposition::waveSuperposition(const objectRegistry& db) : db_(db), origin_(vector::zero), direction_(vector(1, 0, 0)), speed_(0), waveModels_(), waveAngles_(), ramp_(), scale_(), crossScale_(), heightAboveWave_(false) {} Foam::waveSuperposition::waveSuperposition(const waveSuperposition& waves) : db_(waves.db_), origin_(waves.origin_), direction_(waves.direction_), speed_(waves.speed_), waveModels_(waves.waveModels_), waveAngles_(waves.waveAngles_), ramp_(waves.ramp_, false), scale_(waves.scale_, false), crossScale_(waves.crossScale_, false), heightAboveWave_(waves.heightAboveWave_) {} Foam::waveSuperposition::waveSuperposition ( const objectRegistry& db, const dictionary& dict ) : db_(db), origin_(dict.lookup("origin")), direction_(dict.lookup("direction")), speed_(readScalar(dict.lookup("speed"))), waveModels_(), waveAngles_(), ramp_ ( dict.found("ramp") ? Function1::New("ramp", dict) : autoPtr>() ), scale_ ( dict.found("scale") ? Function1::New("scale", dict) : autoPtr>() ), crossScale_ ( dict.found("crossScale") ? Function1::New("crossScale", dict) : autoPtr>() ), heightAboveWave_(dict.lookupOrDefault("heightAboveWave", false)) { const PtrList waveEntries(dict.lookup("waves")); waveModels_.setSize(waveEntries.size()); waveAngles_.setSize(waveEntries.size()); forAll(waveEntries, wavei) { const dictionary waveDict = waveEntries[wavei].dict(); waveModels_.set ( wavei, waveModel::New(waveDict.dictName(), db, waveDict) ); waveAngles_[wavei] = readScalar(waveDict.lookup("angle")); } } // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::waveSuperposition::~waveSuperposition() {} // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // Foam::tmp Foam::waveSuperposition::height ( const scalar t, const vectorField& p ) const { tensor axes; scalar u; vectorField xyz(p.size()); transformation(p, axes, u, xyz); return xyz.component(2) - elevation(t, zip(xyz.component(0), xyz.component(1))); } Foam::tmp Foam::waveSuperposition::ULiquid ( const scalar t, const vectorField& p ) const { tensor axes; scalar u; vectorField xyz(p.size()); transformation(p, axes, u, xyz); if (heightAboveWave_) { xyz.replace(2, height(t, p)); } return UMean(t) + (velocity(t, xyz) & axes); } Foam::tmp Foam::waveSuperposition::UGas ( const scalar t, const vectorField& p ) const { tensor axes; scalar u; vectorField xyz(p.size()); transformation(p, axes, u, xyz); axes = tensor(- axes.x(), - axes.y(), axes.z()); if (heightAboveWave_) { xyz.replace(2, height(t, p)); } return UMean(t) + (velocity(t, xyz) & axes); } Foam::tmp Foam::waveSuperposition::pLiquid ( const scalar t, const vectorField& p ) const { tensor axes; scalar u; vectorField xyz(p.size()); transformation(p, axes, u, xyz); if (heightAboveWave_) { xyz.replace(2, height(t, p)); } return pressure(t, xyz); } Foam::tmp Foam::waveSuperposition::pGas ( const scalar t, const vectorField& p ) const { return - pLiquid(t, p); } void Foam::waveSuperposition::write(Ostream& os) const { os.writeKeyword("origin") << origin_ << token::END_STATEMENT << nl; os.writeKeyword("direction") << direction_ << token::END_STATEMENT << nl; os.writeKeyword("speed") << speed_ << token::END_STATEMENT << nl; os.writeKeyword("waves") << nl << token::BEGIN_LIST << nl << incrIndent; forAll(waveModels_, wavei) { os.writeKeyword(waveModels_[wavei].type()) << nl << indent << token::BEGIN_BLOCK << nl << incrIndent; waveModels_[wavei].write(os); os.writeKeyword("angle") << waveAngles_[wavei] << token::END_STATEMENT << nl << decrIndent << indent << token::END_BLOCK << nl; } os << decrIndent << token::END_LIST << token::END_STATEMENT << nl; if (ramp_.valid()) { ramp_->writeData(os); } if (scale_.valid()) { scale_->writeData(os); } if (crossScale_.valid()) { crossScale_->writeData(os); } if (heightAboveWave_) { os.writeKeyword("heightAboveWave") << heightAboveWave_ << token::END_STATEMENT << nl; } } // ************************************************************************* //