diff --git a/ReleaseNotes-dev b/ReleaseNotes-dev index 12aa0ed485..a135a9b086 100644 --- a/ReleaseNotes-dev +++ b/ReleaseNotes-dev @@ -66,6 +66,11 @@ -doc display application documentation in browser -help print the usage +*** *New* basicSolidThermo solids thermophysical library + + Used in all conjugate heat transfer solvers + + constant properties + + temperature dependent properties + + temperature and direction (in local coordinate system) dependent properties *** *New* Surface film library + Creation of films by particle addition, or initial film distribution + Coupled with the lagrangian/intermediate cloud hierarchy library @@ -87,6 +92,10 @@ *** *Updated* particle tracking algorithm *** *Updated* split cyclics into two separate patches. See doc/changed/splitCyclics.txt *** *New* compact binary I/O for faces and cells. This speeds up reading/writing meshes in binary. +*** *Updated* runTimeModifiable + + on linux uses inotify instead of time stamps - more efficient for large + numbers of monitored files. No more fileModificationSkew needed. + + single integer reduction instead of one reduction per monitored file. * Solvers A number of new solvers have been developed for a range of engineering applications. There has been a set of improvements to certain classes of @@ -125,6 +134,8 @@ (nonuniformTransform)cyclic _ + extrudes into master direction (i.e. away from the owner cell if flipMap is false) + + =topoSet=: replacement of cellSet,faceSet,pointSet utilities. + Comparable to a dictionary driven =setSet= utility. *** Updated utilities + =setFields=: optionally use faceSets to set patch values (see e.g. hotRoom tutorial). + =blockMesh=: specify patches via dictionary instead of type only. This @@ -133,6 +144,8 @@ * Post-processing + =foamToEnsight=: parallel continuous data. new =-nodeValues= option to generate and output nodal field data. + + =singleCellMesh=: new utility to convert mesh and fields to a single cell + mesh. Great for postprocessing. + Function objects: + =residualControl=: new function object to allow users to terminate steady state calculations when the defined residual levels are achieved @@ -144,7 +157,9 @@ + =streamLine=: generate streamlines; ouputs both trajectory and field data * New tutorials - There is a large number of new tutorials to support the new solvers in the + There is a large number of new tutorials for existing and new solvers in the release. + =reactingParcelFilmFoam= tutorials: + multipleBoxes, hotBoxes, panel, evaporationTest + + =interDyMFoam= tutorials: + + testTubeMixer: showcases =solidBodyMotionFunction= diff --git a/applications/solvers/multiphase/bubbleFoam/createRASTurbulence.H b/applications/solvers/multiphase/bubbleFoam/createRASTurbulence.H index 049b6c0b36..1ef67b292e 100644 --- a/applications/solvers/multiphase/bubbleFoam/createRASTurbulence.H +++ b/applications/solvers/multiphase/bubbleFoam/createRASTurbulence.H @@ -55,7 +55,7 @@ ( dimensionedScalar::lookupOrAddToDict ( - "alphaEps", + "alphak", kEpsilonDict, 1.0 ) diff --git a/applications/utilities/mesh/manipulation/setSet/setSet.C b/applications/utilities/mesh/manipulation/setSet/setSet.C index 7b204e984f..117d5283a5 100644 --- a/applications/utilities/mesh/manipulation/setSet/setSet.C +++ b/applications/utilities/mesh/manipulation/setSet/setSet.C @@ -934,18 +934,31 @@ int main(int argc, char *argv[]) { char* linePtr = readline("readline>"); - rawLine = string(linePtr); - - if (*linePtr) + if (linePtr) { - add_history(linePtr); - write_history(historyFile); - } + rawLine = string(linePtr); - free(linePtr); // readline uses malloc, not new. + if (*linePtr) + { + add_history(linePtr); + write_history(historyFile); + } + + free(linePtr); // readline uses malloc, not new. + } + else + { + break; + } } # else { + if (!std::cin.good()) + { + Info<< "End of cin" << endl; + // No error. + break; + } Info<< "Command>" << flush; std::getline(std::cin, rawLine); } diff --git a/applications/utilities/postProcessing/miscellaneous/execFlowFunctionObjects/execFlowFunctionObjects.C b/applications/utilities/postProcessing/miscellaneous/execFlowFunctionObjects/execFlowFunctionObjects.C index ccc1ec2948..4f3f4deebe 100644 --- a/applications/utilities/postProcessing/miscellaneous/execFlowFunctionObjects/execFlowFunctionObjects.C +++ b/applications/utilities/postProcessing/miscellaneous/execFlowFunctionObjects/execFlowFunctionObjects.C @@ -68,13 +68,13 @@ namespace Foam functionObjectList fol(runTime, dict); fol.start(); - fol.execute(); + fol.execute(true); // override outputControl - force writing } else { functionObjectList fol(runTime); fol.start(); - fol.execute(); + fol.execute(true); // override outputControl - force writing } } } diff --git a/bin/tools/CleanFunctions b/bin/tools/CleanFunctions index 1ada431b20..b140bf246b 100644 --- a/bin/tools/CleanFunctions +++ b/bin/tools/CleanFunctions @@ -65,6 +65,7 @@ cleanCase() rm -rf processor* > /dev/null 2>&1 rm -rf probes* > /dev/null 2>&1 rm -rf forces* > /dev/null 2>&1 + rm -rf sets > /dev/null 2>&1 rm -rf system/machines > /dev/null 2>&1 (cd constant/polyMesh && \ rm -rf \ diff --git a/doc/changes/splitCyclic.txt b/doc/changes/splitCyclic.txt index 3d0ffb71cf..0797151faf 100644 --- a/doc/changes/splitCyclic.txt +++ b/doc/changes/splitCyclic.txt @@ -59,6 +59,14 @@ It will check if anything needs to be converted, backup the current file to .old and split any cyclic patchFields into two entries. +Mesh converters +--------------- +Most mesh formats use cyclics in a single patch (i.e. the old way). +The converters have been adapted to use the patch 'oldCyclic' instead of +'cyclic'. oldCyclic uses the 17x automatic ordering but writes 'type cyclic' +so afterwards foamUpgradeCyclics can be run to upgrade. + + decomposePar ------------ Decomposes cyclics into processorCyclic: diff --git a/src/ODE/ODESolvers/SIBS/SIBS.C b/src/ODE/ODESolvers/SIBS/SIBS.C index 6018af2e14..41f73e78a1 100644 --- a/src/ODE/ODESolvers/SIBS/SIBS.C +++ b/src/ODE/ODESolvers/SIBS/SIBS.C @@ -37,8 +37,11 @@ namespace Foam const label SIBS::nSeq_[iMaxX_] = {2, 6, 10, 14, 22, 34, 50, 70}; const scalar - SIBS::safe1 = 0.25, SIBS::safe2 = 0.7, - SIBS::redMax = 1.0e-5, SIBS::redMin = 0.0, SIBS::scaleMX = 0.1; + SIBS::safe1 = 0.25, + SIBS::safe2 = 0.7, + SIBS::redMax = 1.0e-5, + SIBS::redMin = 0.7, + SIBS::scaleMX = 0.1; }; diff --git a/src/OSspecific/POSIX/fileMonitor.C b/src/OSspecific/POSIX/fileMonitor.C index 4779142778..c7e590d6e5 100644 --- a/src/OSspecific/POSIX/fileMonitor.C +++ b/src/OSspecific/POSIX/fileMonitor.C @@ -170,7 +170,9 @@ namespace Foam << "inotify instances" << endl << " (/proc/sys/fs/inotify/max_user_instances" << " on Linux)" << endl - << " or switch off runTimeModifiable." << endl + << " , switch off runTimeModifiable." << endl + << " or compile this file with FOAM_USE_STAT to use" + << " time stamps instead of inotify." << endl << " Continuing without additional file monitoring." << endl; } diff --git a/src/OpenFOAM/db/functionObjects/OutputFilterFunctionObject/OutputFilterFunctionObject.C b/src/OpenFOAM/db/functionObjects/OutputFilterFunctionObject/OutputFilterFunctionObject.C index cb07c911c4..d7d78f1591 100644 --- a/src/OpenFOAM/db/functionObjects/OutputFilterFunctionObject/OutputFilterFunctionObject.C +++ b/src/OpenFOAM/db/functionObjects/OutputFilterFunctionObject/OutputFilterFunctionObject.C @@ -128,7 +128,10 @@ bool Foam::OutputFilterFunctionObject::start() template -bool Foam::OutputFilterFunctionObject::execute() +bool Foam::OutputFilterFunctionObject::execute +( + const bool forceWrite +) { if (enabled_) { @@ -139,7 +142,7 @@ bool Foam::OutputFilterFunctionObject::execute() ptr_->execute(); - if (outputControl_.output()) + if (forceWrite || outputControl_.output()) { ptr_->write(); } diff --git a/src/OpenFOAM/db/functionObjects/OutputFilterFunctionObject/OutputFilterFunctionObject.H b/src/OpenFOAM/db/functionObjects/OutputFilterFunctionObject/OutputFilterFunctionObject.H index 0e894a38b7..88facb0e6f 100644 --- a/src/OpenFOAM/db/functionObjects/OutputFilterFunctionObject/OutputFilterFunctionObject.H +++ b/src/OpenFOAM/db/functionObjects/OutputFilterFunctionObject/OutputFilterFunctionObject.H @@ -183,7 +183,7 @@ public: virtual bool start(); //- Called at each ++ or += of the time-loop - virtual bool execute(); + virtual bool execute(const bool forceWrite); //- Called when Time::run() determines that the time-loop exits virtual bool end(); diff --git a/src/OpenFOAM/db/functionObjects/functionObject/functionObject.C b/src/OpenFOAM/db/functionObjects/functionObject/functionObject.C index 14904c7f43..37c80eee83 100644 --- a/src/OpenFOAM/db/functionObjects/functionObject/functionObject.C +++ b/src/OpenFOAM/db/functionObjects/functionObject/functionObject.C @@ -112,7 +112,7 @@ const Foam::word& Foam::functionObject::name() const bool Foam::functionObject::end() { - return execute(); + return execute(false); } diff --git a/src/OpenFOAM/db/functionObjects/functionObject/functionObject.H b/src/OpenFOAM/db/functionObjects/functionObject/functionObject.H index f965c6353b..a5a44c7218 100644 --- a/src/OpenFOAM/db/functionObjects/functionObject/functionObject.H +++ b/src/OpenFOAM/db/functionObjects/functionObject/functionObject.H @@ -147,8 +147,9 @@ public: //- Called at the start of the time-loop virtual bool start() = 0; - //- Called at each ++ or += of the time-loop - virtual bool execute() = 0; + //- Called at each ++ or += of the time-loop. forceWrite overrides the + // outputControl behaviour. + virtual bool execute(const bool forceWrite) = 0; //- Called when Time::run() determines that the time-loop exits. // By default it simply calls execute(). diff --git a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C index 10d293cb93..2515b0b161 100644 --- a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C +++ b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C @@ -144,7 +144,7 @@ bool Foam::functionObjectList::start() } -bool Foam::functionObjectList::execute() +bool Foam::functionObjectList::execute(const bool forceWrite) { bool ok = true; @@ -157,7 +157,7 @@ bool Foam::functionObjectList::execute() forAll(*this, objectI) { - ok = operator[](objectI).execute() && ok; + ok = operator[](objectI).execute(forceWrite) && ok; } } diff --git a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H index 9b20bf2508..e583b2fbea 100644 --- a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H +++ b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H @@ -153,8 +153,10 @@ public: //- Called at the start of the time-loop virtual bool start(); - //- Called at each ++ or += of the time-loop - virtual bool execute(); + //- Called at each ++ or += of the time-loop. forceWrite overrides + // the usual outputControl behaviour and forces writing always + // (used in postprocessing mode) + virtual bool execute(const bool forceWrite = false); //- Called when Time::run() determines that the time-loop exits virtual bool end(); diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index dc325c1ddf..14aa39935e 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -287,6 +287,7 @@ $(ddtSchemes)/steadyStateDdtScheme/steadyStateDdtSchemes.C $(ddtSchemes)/EulerDdtScheme/EulerDdtSchemes.C $(ddtSchemes)/CoEulerDdtScheme/CoEulerDdtSchemes.C $(ddtSchemes)/SLTSDdtScheme/SLTSDdtSchemes.C +$(ddtSchemes)/localEulerDdtScheme/localEulerDdtSchemes.C $(ddtSchemes)/backwardDdtScheme/backwardDdtSchemes.C $(ddtSchemes)/boundedBackwardDdtScheme/boundedBackwardDdtScheme.C $(ddtSchemes)/boundedBackwardDdtScheme/boundedBackwardDdtSchemes.C diff --git a/src/finiteVolume/finiteVolume/ddtSchemes/localEulerDdtScheme/localEulerDdtScheme.C b/src/finiteVolume/finiteVolume/ddtSchemes/localEulerDdtScheme/localEulerDdtScheme.C new file mode 100644 index 0000000000..b0e2f9bb11 --- /dev/null +++ b/src/finiteVolume/finiteVolume/ddtSchemes/localEulerDdtScheme/localEulerDdtScheme.C @@ -0,0 +1,584 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2010 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 . + +\*---------------------------------------------------------------------------*/ + +#include "localEulerDdtScheme.H" +#include "surfaceInterpolate.H" +#include "fvMatrices.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace fv +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template +const volScalarField& localEulerDdtScheme::localRDeltaT() const +{ + return mesh().objectRegistry::lookupObject(rDeltaTName_); +} + + +template +tmp > +localEulerDdtScheme::fvcDdt +( + const dimensioned& dt +) +{ + const volScalarField& rDeltaT = localRDeltaT(); + + IOobject ddtIOobject + ( + "ddt(" + dt.name() + ')', + mesh().time().timeName(), + mesh() + ); + + if (mesh().moving()) + { + tmp > tdtdt + ( + new GeometricField + ( + ddtIOobject, + mesh(), + dimensioned + ( + "0", + dt.dimensions()/dimTime, + pTraits::zero + ) + ) + ); + + tdtdt().internalField() = + rDeltaT.internalField()*dt.value()*(1.0 - mesh().V0()/mesh().V()); + + return tdtdt; + } + else + { + return tmp > + ( + new GeometricField + ( + ddtIOobject, + mesh(), + dimensioned + ( + "0", + dt.dimensions()/dimTime, + pTraits::zero + ), + calculatedFvPatchField::typeName + ) + ); + } +} + + +template +tmp > +localEulerDdtScheme::fvcDdt +( + const GeometricField& vf +) +{ + const volScalarField& rDeltaT = localRDeltaT(); + + IOobject ddtIOobject + ( + "ddt(" + vf.name() + ')', + mesh().time().timeName(), + mesh() + ); + + if (mesh().moving()) + { + return tmp > + ( + new GeometricField + ( + ddtIOobject, + mesh(), + rDeltaT.dimensions()*vf.dimensions(), + rDeltaT.internalField()* + ( + vf.internalField() + - vf.oldTime().internalField()*mesh().V0()/mesh().V() + ), + rDeltaT.boundaryField()* + ( + vf.boundaryField() - vf.oldTime().boundaryField() + ) + ) + ); + } + else + { + return tmp > + ( + new GeometricField + ( + ddtIOobject, + rDeltaT*(vf - vf.oldTime()) + ) + ); + } +} + + +template +tmp > +localEulerDdtScheme::fvcDdt +( + const dimensionedScalar& rho, + const GeometricField& vf +) +{ + const volScalarField& rDeltaT = localRDeltaT(); + + IOobject ddtIOobject + ( + "ddt(" + rho.name() + ',' + vf.name() + ')', + mesh().time().timeName(), + mesh() + ); + + if (mesh().moving()) + { + return tmp > + ( + new GeometricField + ( + ddtIOobject, + mesh(), + rDeltaT.dimensions()*rho.dimensions()*vf.dimensions(), + rDeltaT.internalField()*rho.value()* + ( + vf.internalField() + - vf.oldTime().internalField()*mesh().V0()/mesh().V() + ), + rDeltaT.boundaryField()*rho.value()* + ( + vf.boundaryField() - vf.oldTime().boundaryField() + ) + ) + ); + } + else + { + return tmp > + ( + new GeometricField + ( + ddtIOobject, + rDeltaT*rho*(vf - vf.oldTime()) + ) + ); + } +} + + +template +tmp > +localEulerDdtScheme::fvcDdt +( + const volScalarField& rho, + const GeometricField& vf +) +{ + const volScalarField& rDeltaT = localRDeltaT(); + + IOobject ddtIOobject + ( + "ddt(" + rho.name() + ',' + vf.name() + ')', + mesh().time().timeName(), + mesh() + ); + + if (mesh().moving()) + { + return tmp > + ( + new GeometricField + ( + ddtIOobject, + mesh(), + rDeltaT.dimensions()*rho.dimensions()*vf.dimensions(), + rDeltaT.internalField()* + ( + rho.internalField()*vf.internalField() + - rho.oldTime().internalField() + *vf.oldTime().internalField()*mesh().V0()/mesh().V() + ), + rDeltaT.boundaryField()* + ( + rho.boundaryField()*vf.boundaryField() + - rho.oldTime().boundaryField() + *vf.oldTime().boundaryField() + ) + ) + ); + } + else + { + return tmp > + ( + new GeometricField + ( + ddtIOobject, + rDeltaT*(rho*vf - rho.oldTime()*vf.oldTime()) + ) + ); + } +} + + +template +tmp > +localEulerDdtScheme::fvmDdt +( + const GeometricField& vf +) +{ + tmp > tfvm + ( + new fvMatrix + ( + vf, + vf.dimensions()*dimVol/dimTime + ) + ); + + fvMatrix& fvm = tfvm(); + + const scalarField& rDeltaT = localRDeltaT().internalField(); + + fvm.diag() = rDeltaT*mesh().V(); + + if (mesh().moving()) + { + fvm.source() = rDeltaT*vf.oldTime().internalField()*mesh().V0(); + } + else + { + fvm.source() = rDeltaT*vf.oldTime().internalField()*mesh().V(); + } + + return tfvm; +} + + +template +tmp > +localEulerDdtScheme::fvmDdt +( + const dimensionedScalar& rho, + const GeometricField& vf +) +{ + tmp > tfvm + ( + new fvMatrix + ( + vf, + rho.dimensions()*vf.dimensions()*dimVol/dimTime + ) + ); + fvMatrix& fvm = tfvm(); + + const scalarField& rDeltaT = localRDeltaT().internalField(); + + fvm.diag() = rDeltaT*rho.value()*mesh().V(); + + if (mesh().moving()) + { + fvm.source() = rDeltaT + *rho.value()*vf.oldTime().internalField()*mesh().V0(); + } + else + { + fvm.source() = rDeltaT + *rho.value()*vf.oldTime().internalField()*mesh().V(); + } + + return tfvm; +} + + +template +tmp > +localEulerDdtScheme::fvmDdt +( + const volScalarField& rho, + const GeometricField& vf +) +{ + tmp > tfvm + ( + new fvMatrix + ( + vf, + rho.dimensions()*vf.dimensions()*dimVol/dimTime + ) + ); + fvMatrix& fvm = tfvm(); + + const scalarField& rDeltaT = localRDeltaT().internalField(); + + fvm.diag() = rDeltaT*rho.internalField()*mesh().V(); + + if (mesh().moving()) + { + fvm.source() = rDeltaT + *rho.oldTime().internalField() + *vf.oldTime().internalField()*mesh().V0(); + } + else + { + fvm.source() = rDeltaT + *rho.oldTime().internalField() + *vf.oldTime().internalField()*mesh().V(); + } + + return tfvm; +} + + +template +tmp::fluxFieldType> +localEulerDdtScheme::fvcDdtPhiCorr +( + const volScalarField& rA, + const GeometricField& U, + const fluxFieldType& phi +) +{ + IOobject ddtIOobject + ( + "ddtPhiCorr(" + rA.name() + ',' + U.name() + ',' + phi.name() + ')', + mesh().time().timeName(), + mesh() + ); + + if (mesh().moving()) + { + return tmp + ( + new fluxFieldType + ( + ddtIOobject, + mesh(), + dimensioned::type> + ( + "0", + rA.dimensions()*phi.dimensions()/dimTime, + pTraits::type>::zero + ) + ) + ); + } + else + { + const volScalarField& rDeltaT = localRDeltaT(); + + return tmp + ( + new fluxFieldType + ( + ddtIOobject, + fvcDdtPhiCoeff(U.oldTime(), phi.oldTime())* + ( + fvc::interpolate(rDeltaT*rA)*phi.oldTime() + - (fvc::interpolate(rDeltaT*rA*U.oldTime()) & mesh().Sf()) + ) + ) + ); + } +} + + +template +tmp::fluxFieldType> +localEulerDdtScheme::fvcDdtPhiCorr +( + const volScalarField& rA, + const volScalarField& rho, + const GeometricField& U, + const fluxFieldType& phi +) +{ + IOobject ddtIOobject + ( + "ddtPhiCorr(" + + rA.name() + ',' + rho.name() + ',' + U.name() + ',' + phi.name() + ')', + mesh().time().timeName(), + mesh() + ); + + if (mesh().moving()) + { + return tmp + ( + new fluxFieldType + ( + ddtIOobject, + mesh(), + dimensioned::type> + ( + "0", + rA.dimensions()*rho.dimensions()*phi.dimensions()/dimTime, + pTraits::type>::zero + ) + ) + ); + } + else + { + const volScalarField& rDeltaT = localRDeltaT(); + + if + ( + U.dimensions() == dimVelocity + && phi.dimensions() == dimVelocity*dimArea + ) + { + return tmp + ( + new fluxFieldType + ( + ddtIOobject, + fvcDdtPhiCoeff(U.oldTime(), phi.oldTime()) + *( + fvc::interpolate(rDeltaT*rA*rho.oldTime())*phi.oldTime() + - (fvc::interpolate(rDeltaT*rA*rho.oldTime()*U.oldTime()) + & mesh().Sf()) + ) + ) + ); + } + else if + ( + U.dimensions() == dimVelocity + && phi.dimensions() == dimDensity*dimVelocity*dimArea + ) + { + return tmp + ( + new fluxFieldType + ( + ddtIOobject, + fvcDdtPhiCoeff + ( + U.oldTime(), + phi.oldTime()/fvc::interpolate(rho.oldTime()) + ) + *( + fvc::interpolate(rDeltaT*rA*rho.oldTime()) + *phi.oldTime()/fvc::interpolate(rho.oldTime()) + - ( + fvc::interpolate + ( + rDeltaT*rA*rho.oldTime()*U.oldTime() + ) & mesh().Sf() + ) + ) + ) + ); + } + else if + ( + U.dimensions() == dimDensity*dimVelocity + && phi.dimensions() == dimDensity*dimVelocity*dimArea + ) + { + return tmp + ( + new fluxFieldType + ( + ddtIOobject, + fvcDdtPhiCoeff(rho.oldTime(), U.oldTime(), phi.oldTime()) + *( + fvc::interpolate(rDeltaT*rA)*phi.oldTime() + - ( + fvc::interpolate(rDeltaT*rA*U.oldTime())&mesh().Sf() + ) + ) + ) + ); + } + else + { + FatalErrorIn + ( + "localEulerDdtScheme::fvcDdtPhiCorr" + ) << "dimensions of phi are not correct" + << abort(FatalError); + + return fluxFieldType::null(); + } + } +} + + +template +tmp localEulerDdtScheme::meshPhi +( + const GeometricField& +) +{ + return tmp + ( + new surfaceScalarField + ( + IOobject + ( + "meshPhi", + mesh().time().timeName(), + mesh() + ), + mesh(), + dimensionedScalar("0", dimVolume/dimTime, 0.0) + ) + ); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace fv + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/finiteVolume/finiteVolume/ddtSchemes/localEulerDdtScheme/localEulerDdtScheme.H b/src/finiteVolume/finiteVolume/ddtSchemes/localEulerDdtScheme/localEulerDdtScheme.H new file mode 100644 index 0000000000..bb3f2187fe --- /dev/null +++ b/src/finiteVolume/finiteVolume/ddtSchemes/localEulerDdtScheme/localEulerDdtScheme.H @@ -0,0 +1,210 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2010 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 . + +Class + Foam::fv::localEulerDdtScheme + +Description + Local time-step first-order Euler implicit/explicit ddt. + The reciprocal of the local time-step field is looked-up from the + database with the name provided. + + This scheme should only be used for steady-state computations + using transient codes where local time-stepping is preferably to + under-relaxation for transport consistency reasons. + + See also CoEulerDdtScheme. + +SourceFiles + localEulerDdtScheme.C + localEulerDdtSchemes.C + +\*---------------------------------------------------------------------------*/ + +#ifndef localEulerDdtScheme_H +#define localEulerDdtScheme_H + +#include "ddtScheme.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace fv +{ + +/*---------------------------------------------------------------------------*\ + Class localEulerDdtScheme Declaration +\*---------------------------------------------------------------------------*/ + +template +class localEulerDdtScheme +: + public fv::ddtScheme +{ + // Private Data + + //- Name of the reciprocal local time-step field + word rDeltaTName_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + localEulerDdtScheme(const localEulerDdtScheme&); + + //- Disallow default bitwise assignment + void operator=(const localEulerDdtScheme&); + + //- Return the reciprocal of the local time-step + const volScalarField& localRDeltaT() const; + + +public: + + //- Runtime type information + TypeName("localEuler"); + + + // Constructors + + //- Construct from mesh and Istream + localEulerDdtScheme(const fvMesh& mesh, Istream& is) + : + ddtScheme(mesh, is), + rDeltaTName_(is) + {} + + + // Member Functions + + //- Return mesh reference + const fvMesh& mesh() const + { + return fv::ddtScheme::mesh(); + } + + tmp > fvcDdt + ( + const dimensioned& + ); + + tmp > fvcDdt + ( + const GeometricField& + ); + + tmp > fvcDdt + ( + const dimensionedScalar&, + const GeometricField& + ); + + tmp > fvcDdt + ( + const volScalarField&, + const GeometricField& + ); + + tmp > fvmDdt + ( + const GeometricField& + ); + + tmp > fvmDdt + ( + const dimensionedScalar&, + const GeometricField& + ); + + tmp > fvmDdt + ( + const volScalarField&, + const GeometricField& + ); + + typedef typename ddtScheme::fluxFieldType fluxFieldType; + + tmp fvcDdtPhiCorr + ( + const volScalarField& rA, + const GeometricField& U, + const fluxFieldType& phi + ); + + tmp fvcDdtPhiCorr + ( + const volScalarField& rA, + const volScalarField& rho, + const GeometricField& U, + const fluxFieldType& phi + ); + + tmp meshPhi + ( + const GeometricField& + ); +}; + + +template<> +tmp localEulerDdtScheme::fvcDdtPhiCorr +( + const volScalarField& rA, + const volScalarField& U, + const surfaceScalarField& phi +); + + +template<> +tmp localEulerDdtScheme::fvcDdtPhiCorr +( + const volScalarField& rA, + const volScalarField& rho, + const volScalarField& U, + const surfaceScalarField& phi +); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace fv + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "localEulerDdtScheme.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/finiteVolume/ddtSchemes/localEulerDdtScheme/localEulerDdtSchemes.C b/src/finiteVolume/finiteVolume/ddtSchemes/localEulerDdtScheme/localEulerDdtSchemes.C new file mode 100644 index 0000000000..53f12e5b7e --- /dev/null +++ b/src/finiteVolume/finiteVolume/ddtSchemes/localEulerDdtScheme/localEulerDdtSchemes.C @@ -0,0 +1,39 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 1991-2010 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 . + +\*---------------------------------------------------------------------------*/ + +#include "localEulerDdtScheme.H" +#include "fvMesh.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace fv +{ + makeFvDdtScheme(localEulerDdtScheme) +} +} + +// ************************************************************************* // diff --git a/src/finiteVolume/finiteVolume/fvc/fvcSmooth/fvcSmooth.C b/src/finiteVolume/finiteVolume/fvc/fvcSmooth/fvcSmooth.C index c04d16dcc9..47cfb5582a 100644 --- a/src/finiteVolume/finiteVolume/fvc/fvcSmooth/fvcSmooth.C +++ b/src/finiteVolume/finiteVolume/fvc/fvcSmooth/fvcSmooth.C @@ -255,8 +255,7 @@ void Foam::fvc::sweep changedFaces.append(facei); changedFacesInfo.append ( - sweepData(max(field[own], field[nbr]), - Cf[facei]) + sweepData(max(field[own], field[nbr]), Cf[facei]) ); } } diff --git a/src/finiteVolume/finiteVolume/fvc/fvcSmooth/fvcSmooth.H b/src/finiteVolume/finiteVolume/fvc/fvcSmooth/fvcSmooth.H index ced147e3dc..2ce5b1b5d3 100644 --- a/src/finiteVolume/finiteVolume/fvc/fvcSmooth/fvcSmooth.H +++ b/src/finiteVolume/finiteVolume/fvc/fvcSmooth/fvcSmooth.H @@ -21,12 +21,22 @@ License You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . -function - Foam::fvc::smooth +InNamespace + Foam::fvc Description - Function that uses smoothData to apply spatial smoothing of a - volume field using the FaceCellWave algorithm + Provides functions smooth spread and sweep which use the FaceCellWave + algorithm to smooth and redistribute the first field argument. + + smooth: smooths the field by ensuring the values in neighbouring + cells are at least coeff* the cell value. + + spread: redistributes the field by spreading the maximum value within + the region defined by the value and gradient of alpha. + + sweep: redistributes the field by sweeping the maximum value where the + gradient of alpha is large away from that starting point of the + sweep. SourceFiles fvcSmooth.C diff --git a/src/finiteVolume/finiteVolume/fvc/fvcSmooth/smoothData.H b/src/finiteVolume/finiteVolume/fvc/fvcSmooth/smoothData.H index b55c93a52a..d027f9f2a2 100644 --- a/src/finiteVolume/finiteVolume/fvc/fvcSmooth/smoothData.H +++ b/src/finiteVolume/finiteVolume/fvc/fvcSmooth/smoothData.H @@ -25,9 +25,9 @@ Class Foam::smoothData Description - Helper class used by the smoothVolField class + Helper class used by the fvc::smooth and fvc::spread functions. -Files +SourceFiles smoothData.H smoothDataI.H diff --git a/src/finiteVolume/finiteVolume/fvc/fvcSmooth/sweepData.H b/src/finiteVolume/finiteVolume/fvc/fvcSmooth/sweepData.H index ebee81c0f7..1bfec88fdf 100644 --- a/src/finiteVolume/finiteVolume/fvc/fvcSmooth/sweepData.H +++ b/src/finiteVolume/finiteVolume/fvc/fvcSmooth/sweepData.H @@ -25,9 +25,9 @@ Class Foam::sweepData Description - Helper class used by fvcSmooth + Helper class used by fvc::sweep function. -Files +SourceFiles sweepData.H sweepDataI.H diff --git a/src/postProcessing/functionObjects/field/streamLine/streamLine.C b/src/postProcessing/functionObjects/field/streamLine/streamLine.C index f052f0580e..42b324e8d2 100644 --- a/src/postProcessing/functionObjects/field/streamLine/streamLine.C +++ b/src/postProcessing/functionObjects/field/streamLine/streamLine.C @@ -53,16 +53,10 @@ void Foam::streamLine::track() initialParticles ); - //Pout<< "Seeding particles." << endl; - const sampledSet& seedPoints = sampledSetPtr_(); forAll(seedPoints, i) { - //Pout<< "Seeded particle at " << seedPoints[i] - // << " at cell:" << seedPoints.cells()[i] - // << endl; - particles.addParticle ( new streamLineParticle @@ -228,6 +222,7 @@ void Foam::streamLine::track() vvInterp, UIndex, // index of U in vvInterp trackForward_, // track in +u direction + nSubCycle_, // step through cells in steps? allTracks_, allScalars_, allVectors_ @@ -299,6 +294,19 @@ void Foam::streamLine::read(const dictionary& dict) UName_ = dict.lookupOrDefault("U", "U"); dict.lookup("trackForward") >> trackForward_; dict.lookup("lifeTime") >> lifeTime_; + if (lifeTime_ < 1) + { + FatalErrorIn(":streamLine::read(const dictionary&)") + << "Illegal value " << lifeTime_ << " for lifeTime" + << exit(FatalError); + } + + dict.lookup("nSubCycle") >> nSubCycle_; + if (nSubCycle_ < 1) + { + nSubCycle_ = 1; + } + cloudName_ = dict.lookupOrDefault("cloudName", "streamLine"); dict.lookup("seedSampleSet") >> seedSet_; @@ -326,7 +334,6 @@ void Foam::streamLine::execute() { // const Time& runTime = const_cast(obr_.time()); // Pout<< "**streamLine::execute : time:" << runTime.timeName() << endl; -// Pout<< "**streamLine::execute : time:" << runTime.timeIndex() << endl; // // bool isOutputTime = false; // diff --git a/src/postProcessing/functionObjects/field/streamLine/streamLine.H b/src/postProcessing/functionObjects/field/streamLine/streamLine.H index 55edc7efe0..ed39204d22 100644 --- a/src/postProcessing/functionObjects/field/streamLine/streamLine.H +++ b/src/postProcessing/functionObjects/field/streamLine/streamLine.H @@ -92,6 +92,9 @@ class streamLine //- Maximum lifetime (= number of cells) of particle label lifeTime_; + //- Number of subcycling steps + label nSubCycle_; + //- Optional specified name of particles word cloudName_; diff --git a/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.C b/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.C index 406a1177b2..eaa65685f7 100644 --- a/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.C +++ b/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.C @@ -36,6 +36,24 @@ namespace Foam // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // +// Estimate dt to cross cell in a few steps +Foam::scalar Foam::streamLineParticle::calcSubCycleDeltaT +( + streamLineParticle::trackData& td, + const scalar dt, + const vector& U +) const +{ + streamLineParticle testParticle(*this); + bool oldKeepParticle = td.keepParticle; + bool oldSwitchProcessor = td.switchProcessor; + scalar fraction = testParticle.trackToFace(position()+dt*U, td); + td.keepParticle = oldKeepParticle; + td.switchProcessor = oldSwitchProcessor; + // Adapt the dt to subdivide the trajectory into 4 substeps. + return dt *fraction/td.nSubCycle_; +} + Foam::vector Foam::streamLineParticle::interpolateFields ( const streamLineParticle::trackData& td, @@ -171,34 +189,56 @@ bool Foam::streamLineParticle::move && lifeTime_ > 0 ) { - // TBD: implement subcycling so step through cells in more than - // one step. - // set the lagrangian time-step scalar dt = min(dtMax, tEnd); - // Store current position and sampled velocity. - --lifeTime_; - sampledPositions_.append(position()); - vector U = interpolateFields(td, position(), cell()); - - if (!td.trackForward_) + // Cross cell in steps + for (label subIter = 0; subIter < td.nSubCycle_; subIter++) { - U = -U; - } + --lifeTime_; - dt *= trackToFace(position()+dt*U, td); + // Store current position and sampled velocity. + sampledPositions_.append(position()); + vector U = interpolateFields(td, position(), cell()); - tEnd -= dt; - stepFraction() = 1.0 - tEnd/trackTime; + if (!td.trackForward_) + { + U = -U; + } - if (tEnd <= ROOTVSMALL) - { - // Force removal - lifeTime_ = 0; + + if (subIter == 0 && td.nSubCycle_ > 1) + { + // Adapt dt to cross cell in a few steps + dt = calcSubCycleDeltaT(td, dt, U); + } + else if (subIter == td.nSubCycle_-1) + { + // Do full step on last subcycle + dt = min(dtMax, tEnd); + } + + + scalar fraction = trackToFace(position()+dt*U, td); + dt *= fraction; + + tEnd -= dt; + stepFraction() = 1.0 - tEnd/deltaT; + + if (tEnd <= ROOTVSMALL) + { + // Force removal + lifeTime_ = 0; + } + + if (!td.keepParticle || td.switchProcessor || lifeTime_ == 0) + { + break; + } } } + if (!td.keepParticle || lifeTime_ == 0) { if (lifeTime_ == 0) diff --git a/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.H b/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.H index a7eb9f33ff..0124d2a6a0 100644 --- a/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.H +++ b/src/postProcessing/functionObjects/field/streamLine/streamLineParticle.H @@ -72,6 +72,7 @@ public: const PtrList >& vvInterp_; const label UIndex_; const bool trackForward_; + const label nSubCycle_; DynamicList& allPositions_; List >& allScalars_; @@ -87,6 +88,7 @@ public: const PtrList >& vvInterp, const label UIndex, const bool trackForward, + const label nSubCycle, DynamicList >& allPositions, List >& allScalars, List >& allVectors @@ -97,6 +99,7 @@ public: vvInterp_(vvInterp), UIndex_(UIndex), trackForward_(trackForward), + nSubCycle_(nSubCycle), allPositions_(allPositions), allScalars_(allScalars), allVectors_(allVectors) @@ -123,6 +126,15 @@ private: // Private Member Functions + //- Estimate dt to cross from current face to next one in nSubCycle + // steps. + scalar calcSubCycleDeltaT + ( + streamLineParticle::trackData& td, + const scalar dt, + const vector& U + ) const; + //- Interpolate all quantities; return interpolated velocity. vector interpolateFields ( diff --git a/tutorials/incompressible/simpleFoam/motorBike/system/controlDict b/tutorials/incompressible/simpleFoam/motorBike/system/controlDict index c81f8fd588..eed783b8a9 100644 --- a/tutorials/incompressible/simpleFoam/motorBike/system/controlDict +++ b/tutorials/incompressible/simpleFoam/motorBike/system/controlDict @@ -83,7 +83,10 @@ functions fields (p U k); // Cells particles can travel before being removed - lifeTime 1000; + lifeTime 10000; + + // Number of steps per cell (estimate). Set to 1 to disable subcycling. + nSubCycle 5; // Cloud name to use cloudName particleTracks; diff --git a/tutorials/incompressible/simpleFoam/pitzDaily/system/controlDict b/tutorials/incompressible/simpleFoam/pitzDaily/system/controlDict index 86cf5ca88a..e608ae6e77 100644 --- a/tutorials/incompressible/simpleFoam/pitzDaily/system/controlDict +++ b/tutorials/incompressible/simpleFoam/pitzDaily/system/controlDict @@ -85,7 +85,10 @@ functions fields (p k U); // Cells particles can travel before being removed - lifeTime 1000; + lifeTime 10000; + + // Number of steps per cell (estimate). Set to 1 to disable subcycling. + nSubCycle 5; // Cloud name to use cloudName particleTracks;