Merge remote-tracking branch 'origin/feature/multisolver' into nextRelease

This commit is contained in:
Dominik Christ 2013-07-08 13:51:44 +01:00
commit 6aef940d91
51 changed files with 7218 additions and 0 deletions

8
.gitignore vendored
View file

@ -181,4 +181,12 @@ src/lduSolvers/amg/amgPolicy/samgPolicy.H
src/lduSolvers/amg/amgPolicy/aamgPolicy.C
src/lduSolvers/amg/amgPolicy/aamgPolicy.H
# The following files are blacklisted because of a DMCA complaint by ANSYS.
src/lduSolvers/tools/PriorityArray.C
src/lduSolvers/tools/PriorityArray.H
src/lduSolvers/amg/amgPolicy/samgPolicy.C
src/lduSolvers/amg/amgPolicy/samgPolicy.H
src/lduSolvers/amg/amgPolicy/aamgPolicy.C
src/lduSolvers/amg/amgPolicy/aamgPolicy.H
# end-of-file

View file

@ -0,0 +1,3 @@
multiSolverDemo.C
EXE = $(FOAM_APPBIN)/multiSolverDemo

View file

@ -0,0 +1,9 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/multiSolver/lnInclude \
-I$(LIB_SRC)/multiSolver/multiSolver
EXE_LIBS = \
-lfiniteVolume \
-L$(FOAM_USER_LIBBIN) \
-lmultiSolver

View file

@ -0,0 +1,55 @@
Info<< "Reading transportProperties\n" << endl;
IOdictionary transportProperties
(
IOobject
(
"transportProperties",
runTime.constant(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
);
dimensionedScalar nu
(
transportProperties.lookup("nu")
);
Info<< "Reading field p\n" << endl;
volScalarField p
(
IOobject
(
"p",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info<< "Reading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
# include "createPhi.H"
label pRefCell = 0;
scalar pRefValue = 0.0;
setRefCell(p, mesh.solutionDict().subDict("PISO"), pRefCell, pRefValue);

View file

@ -0,0 +1,55 @@
Info<< "Reading field T\n" << endl;
volScalarField T
(
IOobject
(
"T",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info<< "Reading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
Info<< "Reading transportProperties\n" << endl;
IOdictionary transportProperties
(
IOobject
(
"transportProperties",
runTime.constant(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
);
Info<< "Reading diffusivity D\n" << endl;
dimensionedScalar DT
(
transportProperties.lookup("DT")
);
# include "createPhi.H"

View file

@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
multiSolverDemo
Description
Demonstration multiSolver-enabled application.
Author
David L. F. Gaden
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "multiSolver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
# include "setRootCase.H"
# include "createMultiSolver.H"
// * * * * * * * * * * * * * * * * icoFoam1 * * * * * * * * * * * * * * * * //
Info << "*** Switching to icoFoam1 ***\n" << endl;
solverDomain = "icoFoam1";
# include "setSolverDomain.H"
# include "solverIcoFoam.H"
// * * * * * * * * * * * * * scalarTransportFoam * * * * * * * * * * * * * * //
Info << "*** Switching to scalarTransportFoam ***\n" << endl;
solverDomain = "scalarTransportFoam";
# include "setSolverDomain.H"
# include "solverScalarTransportFoam.H"
multiRun++;
// * * * * * * * * * * * * * * * * icoFoam2 * * * * * * * * * * * * * * * * //
Info << "*** Switching to icoFoam2 ***\n" << endl;
solverDomain = "icoFoam2";
# include "setSolverDomain.H"
# include "solverIcoFoam.H"
// * * * * * * * * * * * * * scalarTransportFoam * * * * * * * * * * * * * * //
Info << "*** Switching to scalarTransportFoam ***\n" << endl;
solverDomain = "scalarTransportFoam";
# include "setSolverDomain.H"
# include "solverScalarTransportFoam.H"
# include "endMultiSolver.H"
return(0);
}
// ************************************************************************* //

View file

@ -0,0 +1,69 @@
# include "createTime.H"
# include "createMesh.H"
# include "createFields_icoFoam.H"
# include "initContinuityErrs.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl;
for (runTime++; !runTime.end(); runTime++)
{
Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readPISOControls.H"
# include "CourantNo.H"
fvVectorMatrix UEqn
(
fvm::ddt(U)
+ fvm::div(phi, U)
- fvm::laplacian(nu, U)
);
solve(UEqn == -fvc::grad(p));
// --- PISO loop
for (int corr=0; corr<nCorr; corr++)
{
volScalarField rUA = 1.0/UEqn.A();
U = rUA*UEqn.H();
phi = (fvc::interpolate(U) & mesh.Sf())
+ fvc::ddtPhiCorr(rUA, U, phi);
adjustPhi(phi, U, p);
for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
{
fvScalarMatrix pEqn
(
fvm::laplacian(rUA, p) == fvc::div(phi)
);
pEqn.setReference(pRefCell, pRefValue);
pEqn.solve();
if (nonOrth == nNonOrthCorr)
{
phi -= pEqn.flux();
}
}
# include "continuityErrs.H"
U -= rUA*fvc::grad(p);
U.correctBoundaryConditions();
}
runTime.write();
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
}
Info<< "End\n" << endl;

View file

@ -0,0 +1,31 @@
# include "createTime.H"
# include "createMesh.H"
# include "createFields_scalarTransportFoam.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nCalculating scalar transport\n" << endl;
# include "CourantNo.H"
for (runTime++; !runTime.end(); runTime++)
{
Info<< "Time = " << runTime.timeName() << nl << endl;
# include "readSIMPLEControls.H"
for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
{
solve
(
fvm::ddt(T)
+ fvm::div(phi, T)
- fvm::laplacian(DT, T)
);
}
runTime.write();
}
Info<< "End\n" << endl;

View file

@ -0,0 +1,3 @@
multiSolver.C
EXE = $(FOAM_APPBIN)/multiSolver

View file

@ -0,0 +1,10 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/multiSolver/lnInclude \
-I$(LIB_SRC)/multiSolver/multiSolver
EXE_LIBS = \
-lfiniteVolume \
-L$(FOAM_USER_LIBBIN) \
-lmultiSolver

View file

@ -0,0 +1,779 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
multiSolver
Description
Post-processor utility required for working with multiSolver-enabled
applications. These applications store data output in a different
location than usual. This utility loads and unloads data from that
location to where post-processors expect it.
Author
David L. F. Gaden
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "multiSolver.H"
void parseOptions
(
wordList * ptrSolverDomains,
labelList * ptrSuperLoops,
string options
)
{
IStringStream optionsStream(options);
label nSolverDomains(0);
label nSuperLoops(0);
// Get solverDomainNames, if any
while (not optionsStream.eof())
{
token nextOption(optionsStream);
if (nextOption.isLabel())
{
ptrSuperLoops->setSize(++nSuperLoops);
ptrSuperLoops->operator[](nSuperLoops - 1)
= nextOption.labelToken();
break;
}
if (nextOption.isWord())
{
ptrSolverDomains->setSize(++nSolverDomains);
ptrSolverDomains->operator[](nSolverDomains - 1)
= nextOption.wordToken();
}
else
{
// not word, not label, fail
FatalErrorIn("multiSolver::parseOptions")
<< "Expecting word or label. Neither found at position "
<< nSolverDomains - 1 << " in " << options
<< abort(FatalError);
}
}
// Get superLoopList
while (not optionsStream.eof())
{
token nextOption(optionsStream);
if (nextOption.isLabel())
{
ptrSuperLoops->setSize(++nSuperLoops);
ptrSuperLoops->operator[](nSuperLoops - 1)
= nextOption.labelToken();
}
else if (nSuperLoops > 0)
{
// might be a range -> label : label
if (nextOption.isPunctuation())
{
token::punctuationToken p(nextOption.pToken());
if (p == token::COLON)
{
token nextNextOption(optionsStream);
if (nextNextOption.isLabel())
{
label toValue(nextNextOption.labelToken());
label fromValue
(
ptrSuperLoops->operator[](nSuperLoops - 1)
);
if (toValue > fromValue)
{
// correct range format
for (label i = fromValue + 1; i <= toValue; i++)
{
ptrSuperLoops->setSize(++nSuperLoops);
ptrSuperLoops->operator[](nSuperLoops - 1) = i;
}
}
else
{
// greater than / less than, range
FatalErrorIn("multiSolver::parseOptions")
<< "superLoop range incorrect order. 'from : "
<< "to' where 'from' should be less than "
<< "'to'. Values read are '" << fromValue
<< " : " << toValue
<< abort(FatalError);
}
}
else
{
// nextNext not label
FatalErrorIn("multiSolver::parseOptions")
<< "Incorrect syntax. Expecting label after ':' "
<< "in " << options
<< abort(FatalError);
}
}
else
{
// non : punctuation
FatalErrorIn("multiSolver::parseOptions")
<< "Incorrect syntax. Expecting label, word, or ':' "
<< "in " << options
<< abort(FatalError);
}
}
else
{
// not punctuation
FatalErrorIn("multiSolver::parseOptions")
<< "Incorrect syntax. Expecting label, word, or ':' "
<< "in " << options
<< abort(FatalError);
}
}
else
{
// not label, not word
FatalErrorIn("multiSolver::parseOptions")
<< "Incorrect syntax. Expecting label, word, or ':' "
<< "in " << options
<< abort(FatalError);
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::validOptions.insert("list","");
argList::validOptions.insert
(
"load","<[solverDomainName] [superLoopNumber(s)]>"
);
argList::validOptions.insert
(
"purge","<[solverDomainName] [superLoopNumber(s)]>"
);
argList::validOptions.insert("set","<solverDomainName>");
argList::validOptions.insert("preDecompose", "");
argList::validOptions.insert("postDecompose", "");
argList::validOptions.insert("preReconstruct", "");
argList::validOptions.insert("postReconstruct", "");
argList::validOptions.insert("global","");
argList::validOptions.insert("local","");
// default behaviour is purge the case/[time] directory before '-load'
// command. '-noPurge' prevents this. Allows for more complicated
// load data selections by executing multiSolver several times
argList::validOptions.insert("noPurge","");
// default behaviour is: if there is only one solverDomain specified, use
// setSolverDomain() on it. Same as multiSolver -set solverDomain.
// '-noSet' prevents this.
argList::validOptions.insert("noSet","");
// default behaviour is: if there are storeFields defined, when loading, it
// will copy the store fields into every time instance where they are
// absent. '-noStore' will prevent this.
argList::validOptions.insert("noStore","");
# include "setRootCase.H"
enum commandType
{
list,
load,
purge,
set,
preDecompose,
postDecompose,
preReconstruct,
postReconstruct
};
commandType command;
string options;
bool global = false;
bool local = false;
bool all = false;
bool root = false;
bool noPurge = false;
bool noSet = false;
bool noStore = false;
label nCommands(0);
// Read arguments
if (args.optionFound("list"))
{
nCommands++;
command = list;
}
if (args.optionFound("load"))
{
nCommands++;
command = load;
options = args.options()["load"];
}
if (args.optionFound("purge"))
{
nCommands++;
command = purge;
options = args.options()["purge"];
}
if (args.optionFound("set"))
{
nCommands++;
command = set;
options = args.options()["set"];
}
if (args.optionFound("preDecompose"))
{
nCommands++;
command = preDecompose;
}
if (args.optionFound("postDecompose"))
{
nCommands++;
command = postDecompose;
}
if (args.optionFound("preReconstruct"))
{
nCommands++;
command = preReconstruct;
}
if (args.optionFound("postReconstruct"))
{
nCommands++;
command = postReconstruct;
}
if (args.optionFound("global"))
{
global = true;
}
if (args.optionFound("local"))
{
local = true;
}
if (args.optionFound("noPurge"))
{
noPurge = true;
}
if (args.optionFound("noSet"))
{
noSet = true;
}
if (args.optionFound("noStore"))
{
noStore = true;
}
// Error checking
if (nCommands == 0)
{
FatalErrorIn("multiSolver::main")
<< "multiSolver - nothing to do. Use 'multiSolver -help' for assistance."
<< abort(FatalError);
}
else if (nCommands > 1)
{
FatalErrorIn("multiSolver::main")
<< "More than one command found. Use only one of:"
<< "\n\t-list"
<< "\n\t-purge"
<< "\n\t-set"
<< "\n\t-preDecompose"
<< "\n\t-postDecompose"
<< "\n\t-preReconstruct"
<< "\n\t-postReconstruct\n"
<< abort(FatalError);
}
if (global && local)
{
FatalErrorIn("multiSolver::main")
<< "Options global and local both specified. Use only one or "
<< "none."
<< abort(FatalError);
}
if ((command != load) && (noPurge || noSet || noStore))
{
FatalErrorIn("multiSolver::main")
<< "'noPurge', 'noSet' and 'noStore' can only be used with the "
<< "'-load' command."
<< abort(FatalError);
}
multiSolver multiRun
(
Foam::multiSolver::multiControlDictName,
args.rootPath(),
args.caseName()
);
const IOdictionary& mcd(multiRun.multiControlDict());
wordList solverDomains(0);
labelList superLoops(0);
if
(
(command != list)
&& (command != preDecompose)
&& (command != postDecompose)
&& (command != preReconstruct)
&& (command != postReconstruct)
)
{
parseOptions(&solverDomains, &superLoops, options);
}
// Special words - all, root
if (solverDomains.size() == 1)
{
if (solverDomains[0] == "all")
{
all = true;
}
else if (solverDomains[0] == "root")
{
root = true;
}
}
// More error checking
if (root && ((command == load) || (command == set)))
{
FatalErrorIn("multiSolver::main")
<< "'root' is not a valid option with '-load' or '-set'"
<< abort(FatalError);
}
if (all && (command == set))
{
FatalErrorIn("multiSolver::main")
<< "'all' is not a valid option with '-set'"
<< abort(FatalError);
}
if ((command == set) && ((solverDomains.size() > 1) || superLoops.size()))
{
FatalErrorIn("multiSolver::main")
<< "'-set' can only have a single solverDomain name as an option."
<< abort(FatalError);
}
if (all && superLoops.size())
{
FatalErrorIn("multiSolver::main")
<< "'all' cannot be followed by superLoop numbers. To specify "
<< "a superLoop range for all solverDomains, omit the solverDomain"
<< " name entirely. e.g. multiSolver -load '0:4 6'"
<< abort(FatalError);
}
if (root && superLoops.size())
{
FatalErrorIn("multiSolver::main")
<< "'root' cannot be followed by superLoop numbers. 'root' refers"
<< " to case/[time] directories. There are no superLoops here."
<< abort(FatalError);
}
// Check for correct solverDomain names
if
(
!all
&& !root
&& (command != list)
&& (command != preDecompose)
&& (command != postDecompose)
&& (command != preReconstruct)
&& (command != postReconstruct)
)
{
forAll(solverDomains, i)
{
if (solverDomains[i] == "default")
{
// default not permitted
FatalErrorIn("multiSolver::main")
<< "'default' is not a permitted solverDomain name."
<< abort(FatalError);
}
if (!mcd.subDict("solverDomains").found(solverDomains[i]))
{
// Incorrect solver domain name
FatalErrorIn("multiSolver::main")
<< "solverDomainName " << solverDomains[i] << " is not "
<< "found."
<< abort(FatalError);
}
}
}
// Load specified timeClusterLists
timeClusterList tclSource(0);
if (all)
{
// read all
tclSource = multiRun.readAllTimes();
forAll(tclSource, i)
{
if (tclSource[i].superLoop() == -1)
{
tclSource[i].times().clear();
}
}
tclSource.purgeEmpties();
}
else if
(
!superLoops.size()
&& (command != set)
&& (command != list)
&& (command != preDecompose)
&& (command != postDecompose)
&& (command != preReconstruct)
&& (command != postReconstruct)
)
{
// no superLoops specified - read entire solverDomains
forAll (solverDomains, sd)
{
tclSource.append
(
multiRun.readSolverDomainTimes(solverDomains[sd])
);
}
}
else if
(
!root
&& (command != set)
&& (command != list)
&& (command != preDecompose)
&& (command != postDecompose)
&& (command != preReconstruct)
&& (command != postReconstruct)
)
{
// read individual superLoops
if (!solverDomains.size())
{
solverDomains = mcd.subDict("solverDomains").toc();
}
forAll(superLoops, sl)
{
forAll(solverDomains, sd)
{
if (solverDomains[sd] == "default") continue;
tclSource.append
(
multiRun.readSuperLoopTimes
(
solverDomains[sd],
superLoops[sl]
)
);
}
}
}
if (tclSource.size())
{
if (!tclSource.purgeEmpties())
{
FatalErrorIn("multiSolver::main")
<< "No data found with specified parameters."
<< abort(FatalError);
}
}
switch (command)
{
case list:
{
Info << "Listing available data:\n" << endl;
Info << "superLoops by solverDomain:" << endl;
solverDomains = mcd.subDict("solverDomains").toc();
fileName listPath
(
multiRun.multiDictRegistry().path()/"multiSolver"
);
forAll(solverDomains, i)
{
if (solverDomains[i] == "default") continue;
Info << solverDomains[i] << ":" << endl;
Info << multiRun.findSuperLoops(listPath/solverDomains[i])
<< endl;
}
Info << endl;
break;
}
case load:
{
// Default behaviour - use local time unless overlapping, then use
// global time; if global overlaps, fail. -local and -global force
// the behaviour
bool localOverlap(!multiRun.nonOverlapping(tclSource, false));
bool globalOverlap(!multiRun.nonOverlapping(tclSource, true));
if (local && localOverlap)
{
FatalErrorIn("multiSolver::main")
<< "'-local' option used for data with overlapping local "
<< "values. Try using a single solverDomain / superLoop, "
<< "or leave '-local' off."
<< abort(FatalError);
}
if (globalOverlap)
{
FatalErrorIn("multiSolver::main")
<< "globalTime values are overlapping. This should not "
<< "happen. Ensure you have not specified the same "
<< "solverDomain and/or superLoop more than once. If "
<< "that fails, try using 'multiSolver -purge all' and "
<< "rerunning the simulation. If the problem persists, "
<< "it is a bug."
<< abort(FatalError);
}
if (!noPurge)
{
Info << "Purging existing time directories in case root"
<< endl;
multiRun.purgeTimeDirs(multiRun.multiDictRegistry().path());
}
Info << "Loading data from multiSolver directories to case root"
<< endl;
if
(
!multiRun.loadTimeClusterList
(
tclSource,
global || localOverlap,
!noStore
)
)
{
FatalErrorIn("multiRun::main")
<< "loadTimeClusterList failed. timeClusterList contents: "
<< tclSource
<< abort(FatalError);
}
break;
}
case purge:
if (root)
{
Info << "Purging time directories from case root" << endl;
multiRun.purgeTimeDirs(multiRun.multiDictRegistry().path());
}
else
{
Info << "Purging time directories from multiSolver directories"
<< endl;
forAll(tclSource, i)
{
// do not purge 'initial' directory, even if specified
if (tclSource[i].superLoop() < 0) continue;
fileName purgePath
(
multiRun.findInstancePath(tclSource[i], 0).path()
);
rmDir(purgePath);
}
}
break;
case set:
// do nothing here
break;
case preDecompose:
{
Info << "Performing preDecompose" << endl;
multiRun.preCondition();
break;
}
case postDecompose:
{
Info << "Performing postDecompose" << endl;
fileNameList dirEntries
(
readDir
(
multiRun.multiDictRegistry().path(), fileName::DIRECTORY
)
);
forAll(dirEntries, de)
{
if (dirEntries[de](9) == "processor")
{
Info << "Reading " << dirEntries[de] << endl;
multiRun.postCondition
(
dirEntries[de]
);
// Copy system to processorN
cp
(
multiRun.multiDictRegistry().path()
/multiRun.multiDictRegistry().system(),
multiRun.multiDictRegistry().path()/dirEntries[de]
);
// Copy constant/files to processorN/constant
fileNameList constantContents
(
readDir
(
multiRun.multiDictRegistry().path()
/multiRun.multiDictRegistry().constant(),
fileName::FILE
)
);
forAll(constantContents, cc)
{
cp
(
multiRun.multiDictRegistry().path()
/multiRun.multiDictRegistry().constant()
/constantContents[cc],
multiRun.multiDictRegistry().path()/dirEntries[de]
/multiRun.multiDictRegistry().constant()
);
}
// Copy constant/directories to processorN/constant
constantContents = readDir
(
multiRun.multiDictRegistry().path()
/multiRun.multiDictRegistry().constant(),
fileName::DIRECTORY
);
forAll(constantContents, cc)
{
// Ingore mesh directory
if (constantContents[cc] == "polyMesh")
{
continue;
}
cp
(
multiRun.multiDictRegistry().path()
/multiRun.multiDictRegistry().constant()
/constantContents[cc],
multiRun.multiDictRegistry().path()/dirEntries[de]
/multiRun.multiDictRegistry().constant()
);
}
}
}
multiRun.purgeTimeDirs(multiRun.multiDictRegistry().path());
break;
}
case preReconstruct:
{
Info << "Performing preReconstruct" << endl;
fileNameList dirEntries
(
readDir
(
multiRun.multiDictRegistry().path(), fileName::DIRECTORY
)
);
forAll(dirEntries, de)
{
if (dirEntries[de](9) == "processor")
{
Info << "Reading " << dirEntries[de] << endl;
multiRun.preCondition
(
dirEntries[de]
);
// Fix missing 0.00000e+00 directory if it exists
mkDir
(
multiRun.multiDictRegistry().path()/dirEntries[de]/"0"
);
}
}
break;
}
case postReconstruct:
{
Info << "Performing postReconstruct" << endl;
Info << "Reading preconditioned time directories" << endl;
multiRun.postCondition();
Info << "Purging preconditioned time directories"
<< endl;
// Clean up extra time directories
fileNameList dirEntries
(
readDir
(
multiRun.multiDictRegistry().path(), fileName::DIRECTORY
)
);
forAll(dirEntries, de)
{
if (dirEntries[de](9) == "processor")
{
multiRun.purgeTimeDirs
(
multiRun.multiDictRegistry().path()/dirEntries[de]
);
}
}
break;
}
}
// Execute set command - either from an explicit '-set' or from a '-load'
// with only one solverDomain as an option
if
(
(command == set)
|| (
(command == load)
&& (solverDomains.size() == 1)
&& (!all)
)
)
{
Info << "Changing to " << solverDomains[0] << " settings." << endl;
multiRun.setSolverDomainPostProcessing(solverDomains[0]);
}
Info << "\nCommand completed successfully.\n" << endl;
return(0);
}
// ************************************************************************* //

View file

@ -22,6 +22,8 @@ Pstream/Allwmake
wmake libo OSspecific/$WM_OSTYPE
wmake libso OpenFOAM
wmake libso multiSolver
# Decomposition methods needed by meshTools
decompositionMethods/AllwmakeLnInclude
decompositionMethods/Allwmake

View file

@ -0,0 +1,6 @@
dummyControlDict/dummyControlDict.C
multiSolver/multiSolver.C
timeCluster/timeCluster.C
timeCluster/timeClusterList.C
LIB = $(FOAM_LIBBIN)/libmultiSolver

View file

@ -0,0 +1,6 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-Ituple2Lists
LIB_LIBS = \
-lfiniteVolume

View file

@ -0,0 +1,111 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "dummyControlDict.H"
#include "IFstream.H"
// * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(dummyControlDict, 0);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::dummyControlDict::dummyControlDict()
{
this->set("deltaT", 1);
this->set("writeFrequency", 1);
}
Foam::dummyControlDict::dummyControlDict(const fileName& mcdFile)
{
this->set("deltaT", 1);
this->set("writeFrequency", 1);
IFstream mcdStream(mcdFile);
if (!mcdStream.good())
{
FatalErrorIn("dummyControlDict::dummyControlDict")
<< "Cannot find the multiControlDict file " << mcdFile << "."
<< abort(FatalError);
}
dictionary mcdDict(mcdStream);
if (mcdDict.subDict("multiSolverControl").found("timeFormat"))
{
word tf(mcdDict.subDict("multiSolverControl").lookup("timeFormat"));
this->set("timeFormat", tf);
}
if (mcdDict.subDict("multiSolverControl").found("timePrecision"))
{
label tp
(
readLabel
(
mcdDict.subDict("multiSolverControl").lookup("timePrecision")
)
);
this->set("timePrecision", tp);
}
}
Foam::dummyControlDict::dummyControlDict(const dictionary& mcdDict)
{
this->set("deltaT", 1);
this->set("writeFrequency", 1);
if (mcdDict.subDict("multiSolverControl").found("timeFormat"))
{
word tf(mcdDict.subDict("multiSolverControl").lookup("timeFormat"));
this->set("timeFormat", tf);
}
if (mcdDict.subDict("multiSolverControl").found("timePrecision"))
{
label tp
(
readLabel
(
mcdDict.subDict("multiSolverControl").lookup("timePrecision")
)
);
this->set("timePrecision", tp);
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::dummyControlDict::~dummyControlDict()
{}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View file

@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::dummyControlDict
Description
This class is a workaround that allows a class to have its own independent
objectRegistry. That requires the creation of a new Time object, which
requires a controlDict for construction. dummyControlDict creates a dummy
controlDict to feed the new Time object. The only dictionary values it
handles are deltaT, writeFrequency, and optionally, the Time class statics,
format and precision.
SourceFiles
dummyControlDict.C
Author
David L. F. Gaden
\*---------------------------------------------------------------------------*/
#ifndef dummyControlDict_H
#define dummyControlDict_H
#include "dictionary.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class dummyControlDict Declaration
\*---------------------------------------------------------------------------*/
class dummyControlDict
:
public dictionary
{
public:
TypeName("dummyControlDict");
// Constructors
//- Construct, creating the bare minimum controlDict
dummyControlDict();
//- Construct, reading the multiControlDict data from a file
explicit dummyControlDict(const fileName&);
//- Construct given the multiControlDict dictionary
explicit dummyControlDict(const dictionary&);
// Destructor
virtual ~dummyControlDict();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif

View file

@ -0,0 +1,12 @@
word solverDomain;
multiSolver multiRun
(
multiSolver::multiControlDictName,
args.rootPath(),
args.caseName()
);
while (multiRun.run())
{ // While brace
{ // dummy brace

View file

@ -0,0 +1,3 @@
} // previous solver domain goes out of scope
multiRun++;
} // end While loop

View file

@ -0,0 +1,10 @@
} // previous solver domain goes out of scope
multiRun.setSolverDomain(solverDomain);
// Clear defines that may interfere with other solver domains
#undef createPhi_H
#undef createPhiV_H
#undef initContinuityErrs_H
if (multiRun.run())
{ // next solver domain comes into scope

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,562 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::multiSolver
Description
Manages multiple solvers within one master-solver. Allows for multiple
definitions of time. Works by changing the case directory as required by
each solver.
SourceFiles
multiSolverI.H
multiSolver.C
multiSolverSetControls.C
multiSolverSetInitialSolverDomain.C
multiSolverSetNextSolverDomain.C
multiSolverTimeFunctions.C
Author
David L. F. Gaden
\*---------------------------------------------------------------------------*/
#ifndef multiSolver_H
#define multiSolver_H
#include "Time.H"
#include "dummyControlDict.H"
#include "timeClusterList.H"
#include "IFstream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class multiSolver Declaration
\*---------------------------------------------------------------------------*/
class multiSolver
{
// Private data
// A dummy controlDict, required to initialize multiDictRegistry
dummyControlDict dcd_;
// A mini-objectRegistry for the dictionaries - done this way to allow
// run-time modification of dictionaries
Time multiDictRegistry_;
// Main control dictionary for multiSolver
IOdictionary multiControlDict_;
// All multiDicts contained in the case directory
PtrList<IOdictionary> multiDicts_;
// Reference to multiSolverControl subdictionary in multiControlDict
dictionary& multiSolverControl_;
// Reference to solverDomains subdictionary in multiControlDict
dictionary& solverDomains_;
// Current solverDomain dictionary
dictionary currentSolverDomainDict_;
// List of all the solver domain prefixes
wordList prefixes_;
// True when the end condition has been met
bool finished_;
// True when superLoop++ just happened, but the previous solverDomain
// has not yet been saved (to prevent the first solverDomain from
// saving to the *next* superLoop.
bool noSaveSinceSuperLoopIncrement_;
// True if this is the lowest number on a local shared drive - parallel
// only.
bool manageLocalRoot_;
// Private member functions
// Set manageLocalRoot_ flags on all processors (parallel only)
void setUpParallel();
// Ensure all processors are synchronized (parallel only)
void synchronizeParallel() const;
// Load initial data and controls
// *** Located in multiSolverSetInitialSolverDomain.C ***
void setInitialSolverDomain(const word& solverDomainName);
// Load data and controls of a subsequent solver domain
// *** Located in multiSolverSetNextSolverDomain.C ***
void setNextSolverDomain(const word& solverDomainName);
// Sets controls from the multiSolverControl subdictionary in the
// multiControlDict
// *** Located in multiSolverSetControls.C ***
void setMultiSolverControls();
// Sets controls from the solverDomains subdictionary in the
// multiControlDict
// *** Located in multiSolverSetControls.C ***
void setSolverDomainControls(const word& solverDomainName);
// Use stopAt and finalStopAt settings to determine the endTime for
// the current solverDomain. Returns the controlDict's stopAt word,
// which may differ from that in multiControlDict. Sets finished_ to
// true if the end condition will be met.
word setLocalEndTime();
// Looks for case/multiSolver/solverDomain/initial/0. Fail if missing.
void checkTimeDirectories() const;
// Change all catalogued multiDicts to another solverDomain
void swapDictionaries(const word& solverDomainName);
// When setting up for a different solverDomain, the boundary
// conditions are allowed to change. This function copies all valid
// case/intoSolverDomain/inital/0 files, and overwrites the
// internalField with those found in the corresponding file in
// dataSourcePath. The result is placed in case/[time].
void swapBoundaryConditions
(
const fileName& dataSourcePath,
const word& intoSolverDomain
);
// Read multiDict files into the multiDictRegistry. Loads:
// - case/system/multi*
// - case/system/[local]/multi*, where [local] is anything
// - case/constant/multi*
// - case/constant/[local]/multi*
void readAllMultiDicts();
// Scan a directory for multi*; read them into the multiDictRegistry
void readMultiDictDirectory
(
const fileName& sourcePath,
const word& local = word::null
);
// Rereads modified dictionaries and sets the controls
void readIfModified();
// Converts a fileName with the naming convention:
// solverDomain@superLoop@globalOffset@fileName
// to a timeCluster
timeCluster parseConditionedFile
(
const word& pcFile,
const instant& inst
) const;
public:
// multiSolverControl enumerations
//- Read initial data control options
enum initialStartFromControls
{
misFirstTime,
misFirstTimeInStartDomain,
misFirstTimeInStartDomainInStartSuperLoop,
misStartTime,
misStartTimeInStartDomain,
misStartTimeInStartDomainInStartSuperLoop,
misLatestTime,
misLatestTimeInStartDomain,
misLatestTimeInStartDomainInStartSuperLoop
};
//- Final stop at control options
enum finalStopAtControls
{
mfsEndTime,
mfsEndTimeInEndDomain,
mfsEndTimeInEndDomainInEndSuperLoop,
mfsEndSuperLoop,
mfsWriteNow,
mfsNoWriteNow,
mfsNextWrite
};
// solverDomains enumerations
//- Time value start from control options
enum startFromControls
{
mtsFirstTime,
mtsStartTime,
mtsLatestTimeThisDomain,
mtsLatestTimeAllDomains
};
//- Stop at control options
enum stopAtControls
{
msaEndTime,
msaNoWriteNow,
msaWriteNow,
msaNextWrite,
msaIterations,
msaSolverSignal,
msaElapsedTime
};
protected:
// multiSolverControl data
label superLoop_;
word currentSolverDomain_;
static const NamedEnum<initialStartFromControls, 9>
initialStartFromControlsNames_;
initialStartFromControls initialStartFrom_;
scalar initialStartTime_;
word startDomain_;
label startSuperLoop_;
static const NamedEnum<finalStopAtControls, 7>
finalStopAtControlsNames_;
finalStopAtControls finalStopAt_;
word endDomain_;
scalar finalEndTime_;
label endSuperLoop_;
bool multiDictsRunTimeModifiable_;
scalar globalTimeOffset_;
// solverDomains data
// This data is transient, changing between solver domains
static const NamedEnum<startFromControls, 4>
startFromControlsNames_;
startFromControls startFrom_;
scalar startTime_;
static const NamedEnum<stopAtControls, 7> stopAtControlsNames_;
stopAtControls stopAt_;
scalar endTime_;
label purgeWriteSuperLoops_;
scalar deltaT_;
label iterations_;
scalar elapsedTime_;
wordList storeFields_;
public:
TypeName("multiSolver");
//- The default multiSolver dictionary name
static word multiControlDictName;
/* Not implemented yet
//- Indicates whether the 'solverSignal' option for the finalStopAt setting
// in the multiControlDict is permitted. Default false. Set this to true
// in the global space of a solver that does support solverSignal.
static bool supportsSolverSignal;
*/
// Constructors
//- Construct given the multiControlDict
multiSolver
(
const dictionary& dict,
const fileName& rootPath,
const fileName& caseName,
const word& systemName = "system",
const word& constantName = "constant"
);
//- Construct reading the multiControlDict from file
multiSolver
(
const word& multiControlDictName,
const fileName& rootPath,
const fileName& caseName,
const word& systemName = "system",
const word& constantName = "constant"
);
// Destructor
virtual ~multiSolver();
// Member functions
// Access
// Database
inline const Time& multiDictRegistry() const;
inline const IOdictionary multiControlDict() const;
// multiSolverControl data
inline const label& superLoop() const;
inline const word& currentSolverDomain() const;
inline const initialStartFromControls& initialStartFrom() const;
inline const word& startDomain() const;
inline const scalar& initialStartTime() const;
inline const finalStopAtControls& finalStopAt() const;
inline const word& endDomain() const;
inline const scalar& finalEndTime() const;
inline const label& startSuperLoop() const;
inline const label& endSuperLoop() const;
inline const bool& multiDictsRunTimeModifiable() const;
inline const scalar& globalTimeOffset() const;
// Write permission
inline scalar& globalTimeOffset();
// solverDomains data
inline const startFromControls& startFrom() const;
inline const stopAtControls& stopAt() const;
inline const scalar& startTime() const;
inline const scalar& endTime() const;
inline const label& iterations() const;
inline const scalar& elapsedTime() const;
inline const wordList& storeFields() const;
inline const label& purgeWriteSuperLoops() const;
inline const scalar& deltaT() const;
// Solver (and pre/post-processor) interface functions
// Pre-condition the directory for decomposePar or reconstructPar
void preCondition(const word& processor = word::null);
// Post-condition the directory after decomposePar or
// reconstructPar
void postCondition(const word& processor = word::null);
// Switch to another solver domain
void setSolverDomain(const word& solverDomainName);
// Switch to another solver domain for post-processing only
void setSolverDomainPostProcessing(const word& solverDomainName);
// Stop the run at the next setSolverDomain
inline void setFinished();
// Increment the superLoop (prefix)
multiSolver& operator++();
// Increment the superLoop (postfix)
multiSolver& operator++(int);
// Check
//- Return true if run should continue
bool run() const;
//- Return true if end of run
bool end() const;
// Time functions
// The multiSolver time directory structure should have the form:
// case
// '-multiSolver
// |-prefix1 {solverDomain}
// | |-initial {initial directory, superLoop -1}
// | |-0 {superLoop}
// | |-1 {superLoop}
// | | '-multiSolverTime {auto-generated dictionary}
// | '-2, etc..
// |-prefix2, etc..
//
// *** All time functions are located in ***
// *** multiSolverTimeFunctions.C ***
// Create a list of all superLoops in a directory, (usually in
// case/prefix). Only looks for integer directory names, does not
// check for valid time subdirectories.
static labelList findSuperLoops(const fileName& path);
// Find the closest global time to a given value in a
// timeClusterList. Assumes timeClusters do not overlap global time
// values (as they shouldn't). If exact is true, this function
// throws a FatalError when no exact match is found.
static timeCluster findClosestGlobalTime
(
const scalar value,
const timeClusterList& tcl,
const bool& exact = false
);
// Find the closest local time to a given value in a
// timeClusterList. Unlike global times, local times can overlap.
// If overlaps exist, it uses only the latest superloop. If exact
// is true, this function throws a FatalError when no exact match
// is found.
static timeCluster findClosestLocalTime
(
const scalar value,
const timeClusterList& tcl,
const bool& exact = false
);
// Find the latest global time
static timeCluster findLatestGlobalTime
(
const timeClusterList& tcl
);
// Find the latest global time
static timeCluster findLatestLocalTime
(
const timeClusterList& tcl
);
// Find the path to a specific entry in a time cluster
fileName findInstancePath
(
const timeCluster& tc,
const label& index
) const;
// Find the largest superLoop
static label findMaxSuperLoopValue(const timeClusterList& tcl);
// Find the timeClusterList index for the timeClusterList that has
// the largest superLoop
static labelList findMaxSuperLoopIndices(const timeClusterList& tcl);
// Checks if any of the time ranges overlap one another in a
// timeClusterList. (If startTime = previous end, this is okay.)
// True means they do not overlap.
static bool nonOverlapping
(
const timeClusterList& tcl,
const bool useGlobalTime = false
);
// Maps the time directories in a single superLoop directory
// Include a processor name, and it uses the processorN directory
timeCluster readSuperLoopTimes
(
const word& solverDomain,
const label superLoop,
const word& processor = word::null
) const;
// Maps the time directories in a single solverDomain
// Include a processor name, and it uses the processorN directory
timeClusterList readSolverDomainTimes
(
const word& solverDomain,
const word processor = word::null
) const;
// Create a snapshot of all the multiSolver time directories
// Give it a processor name, and it searches instead in the
// processor directory
timeClusterList readAllTimes
(
const word processor = word::null
) const;
// Move or copy all output time directories that are catalogued by
// a timeClusterList to case/[timeValue] format. Returns false if
// time values overlap when forced to useGlobalTime.
// loadStoreFields will copy storeFields into every time folder
// even though they do not change.
bool loadTimeClusterList
(
const timeClusterList& tcl,
const bool useGlobalTime = true,
const bool loadStoreFields = true
) const;
// Move all the time directories from sourcePath to archivePath
static void archiveTimeDirs
(
const fileName& sourcePath,
const fileName& archivePath,
const label& purgeWrite
);
// Delete all time directories in path, do not delete "constant"
static void purgeTimeDirs(const fileName& path);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "multiSolverI.H"
#endif

View file

@ -0,0 +1,182 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
inline const Time& multiSolver::multiDictRegistry() const
{
return multiDictRegistry_;
}
inline const IOdictionary multiSolver::multiControlDict() const
{
return multiControlDict_;
}
inline const label& multiSolver::superLoop() const
{
return superLoop_;
}
inline const word& multiSolver::currentSolverDomain() const
{
return currentSolverDomain_;
}
inline const multiSolver::initialStartFromControls& multiSolver::initialStartFrom() const
{
return initialStartFrom_;
}
inline const word& multiSolver::startDomain() const
{
return startDomain_;
}
inline const scalar& multiSolver::initialStartTime() const
{
return initialStartTime_;
}
inline const multiSolver::finalStopAtControls& multiSolver::finalStopAt() const
{
return finalStopAt_;
}
inline const word& multiSolver::endDomain() const
{
return endDomain_;
}
inline const scalar& multiSolver::finalEndTime() const
{
return finalEndTime_;
}
inline const label& multiSolver::startSuperLoop() const
{
return startSuperLoop_;
}
inline const label& multiSolver::endSuperLoop() const
{
return endSuperLoop_;
}
inline const bool& multiSolver::multiDictsRunTimeModifiable() const
{
return multiDictsRunTimeModifiable_;
}
inline const scalar& multiSolver::globalTimeOffset() const
{
return globalTimeOffset_;
}
inline scalar& multiSolver::globalTimeOffset()
{
return globalTimeOffset_;
}
inline const multiSolver::startFromControls& multiSolver::startFrom() const
{
return startFrom_;
}
inline const multiSolver::stopAtControls& multiSolver::stopAt() const
{
return stopAt_;
}
inline const scalar& multiSolver::startTime() const
{
return startTime_;
}
inline const scalar& multiSolver::endTime() const
{
return endTime_;
}
inline const label& multiSolver::iterations() const
{
return iterations_;
}
inline const scalar& multiSolver::elapsedTime() const
{
return elapsedTime_;
}
inline const wordList& multiSolver::storeFields() const
{
return storeFields_;
}
inline const label& multiSolver::purgeWriteSuperLoops() const
{
return purgeWriteSuperLoops_;
}
inline const scalar& multiSolver::deltaT() const
{
return deltaT_;
}
void Foam::multiSolver::setFinished()
{
finished_ = true;
}
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View file

@ -0,0 +1,39 @@
// Common elements in the constructor initialization list for multiSolver
multiDicts_(NULL),
multiSolverControl_(multiControlDict_.subDict("multiSolverControl")),
solverDomains_(multiControlDict_.subDict("solverDomains")),
currentSolverDomainDict_(),
prefixes_(solverDomains_.toc()),
finished_(false),
noSaveSinceSuperLoopIncrement_(false),
manageLocalRoot_(false),
superLoop_(0),
currentSolverDomain_("default"),
initialStartFrom_(misLatestTime),
// startDomain_,
initialStartTime_(0),
startSuperLoop_(0),
finalStopAt_(mfsEndTime),
// endDomain_,
finalEndTime_(0),
endSuperLoop_(0),
multiDictsRunTimeModifiable_(true),
globalTimeOffset_(0),
purgeWriteSuperLoops_(prefixes_.size()),
// timeValueStartFrom_,
// scalar startTime_,
// stopAtControls stopAt_,
// scalar endTime_,
// label endIterations_
storeFields_(0)

View file

@ -0,0 +1,359 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::multiSolver::setMultiSolverControls()
{
initialStartFrom_ = misLatestTime;
if (multiSolverControl_.found("initialStartFrom"))
{
initialStartFrom_ = initialStartFromControlsNames_.read
(
multiSolverControl_.lookup("initialStartFrom")
);
}
if (multiSolverControl_.found("startTime"))
{
initialStartTime_ = readScalar(multiSolverControl_.lookup("startTime"));
if (initialStartTime_ < 0)
{
FatalErrorIn("multiSolver::setMultiSolverControls")
<< "'startTime' in multiControlDict/multiSolverControl cannot "
<< "be negative."
<< abort(FatalError);
}
}
else if
(
(initialStartFrom_ == misStartTime)
|| (initialStartFrom_ == misStartTimeInStartDomain)
|| (initialStartFrom_ == misStartTimeInStartDomainInStartSuperLoop)
)
{
FatalIOErrorIn
(
"multiSolver::setMultiSolverControls", multiSolverControl_
)
<< "'startTime' is required in multiControlDict/multiSolverControl "
<< "if 'initialStartFrom' is set to 'startTime', "
<< "'startTimeInStartDomain', or "
<< "'startTimeInStartDomainInStartStuperLoop'"
<< exit(FatalIOError);
}
if (multiSolverControl_.found("startDomain"))
{
startDomain_ = word(multiSolverControl_.lookup("startDomain"));
}
else if
(
(initialStartFrom_ == misFirstTimeInStartDomain)
|| (initialStartFrom_ == misFirstTimeInStartDomainInStartSuperLoop)
|| (initialStartFrom_ == misStartTimeInStartDomain)
|| (initialStartFrom_ == misStartTimeInStartDomainInStartSuperLoop)
|| (initialStartFrom_ == misLatestTimeInStartDomain)
|| (initialStartFrom_ == misLatestTimeInStartDomainInStartSuperLoop)
)
{
FatalIOErrorIn("multiSolver::setMultiSolverControls", multiSolverControl_)
<< "'startDomain' is required in "
<< "multiControlDict/multiSolverControl if 'initialStartFrom' is "
<< "set to 'firstTimeInStartDomain', "
<< "'firstTimeInStartDomainInStartSuperLoop', "
<< "'startTimeInStartDomain', "
<< "'startTimeInStartDomainInStartSuperLoop', "
<< "'latestTimeInStartDomain', or "
<< "'latestTimeInStartDomainInStartSuperLoop'."
<< abort(FatalError);
}
finalStopAt_ = mfsEndTime;
if (multiSolverControl_.found("finalStopAt"))
{
finalStopAt_ = finalStopAtControlsNames_.read
(
multiSolverControl_.lookup("finalStopAt")
);
}
if (multiSolverControl_.found("endDomain"))
{
endDomain_ = word(multiSolverControl_.lookup("endDomain"));
}
else if
(
(finalStopAt_ == mfsEndTimeInEndDomain)
|| (finalStopAt_ == mfsEndTimeInEndDomainInEndSuperLoop)
)
{
FatalErrorIn("multiSolver::setMultiSolverControls")
<< "endTime is required in multiControlDict/multiSolverControl if "
<< "finalStopAt is set to 'endTimeInEndDomain', or "
<< "'endTimeInEndDomainInEndSuperLoop'."
<< abort(FatalError);
}
if (multiSolverControl_.found("endTime"))
{
finalEndTime_ =
readScalar(multiSolverControl_.lookup("endTime"));
}
else if
(
(finalStopAt_ == mfsEndTime)
|| (finalStopAt_ == mfsEndTimeInEndDomain)
|| (finalStopAt_ == mfsEndTimeInEndDomainInEndSuperLoop)
)
{
FatalErrorIn("multiSolver::setMultiSolverControls")
<< "'endTime' is required in "
<< "multiControlDict/multiSolverControl if 'finalStopAt' is set to "
<< "'endTime', 'endTimeInEndDomain', or "
<< "'endTimeInEndDomainInEndSuperLoop'."
<< abort(FatalError);
}
if (multiSolverControl_.found("startSuperLoop"))
{
startSuperLoop_ =
readLabel(multiSolverControl_.lookup("startSuperLoop"));
}
else if
(
(initialStartFrom_ == misFirstTimeInStartDomainInStartSuperLoop)
|| (initialStartFrom_ == misStartTimeInStartDomainInStartSuperLoop)
|| (initialStartFrom_ == misLatestTimeInStartDomainInStartSuperLoop)
)
{
FatalErrorIn("multiSolver::setMultiSolverControls")
<< "'startSuperLoop' is required in "
<< "multiControlDict/multiSolverControl if 'initialStartFrom' is "
<< "set to 'firstTimeInStartDomainInSuperLoop', "
<< "'startTimeInStartDomainInStartSuperLoop', or "
<< "'latestTimeInStartDomainInStartSuperLoop'."
<< abort(FatalError);
}
if (multiSolverControl_.found("endSuperLoop"))
{
endSuperLoop_ =
readLabel(multiSolverControl_.lookup("endSuperLoop"));
}
else if
(
(finalStopAt_ == mfsEndSuperLoop)
|| (finalStopAt_ == mfsEndTimeInEndDomainInEndSuperLoop)
)
{
FatalErrorIn("multiSolver::setMultiSolverControls")
<< "'endSuperLoops' is required in "
<< "multiControlDict/multiSolverControl if 'finalStopAt' is set to "
<< "'endSuperLoop' or 'endTimeInEndDomainInEndSuperLoop'."
<< abort(FatalError);
}
multiDictsRunTimeModifiable_ = true;
if (multiSolverControl_.found("multiDictsRunTimeModifiable"))
{
multiDictsRunTimeModifiable_ =
multiSolverControl_.lookup("multiDictsRunTimeModifiable");
}
prefixes_.clear();
prefixes_ = solverDomains_.toc();
if
(
(prefixes_.size() == 0)
|| ((prefixes_.size() == 1) && (prefixes_[0] == "default"))
)
{
FatalErrorIn("multiSolver::setMultiSolverControls")
<< "No solver domains found in multiControlDict. Expecting "
<< "subdictionary solverDomains to contain at least one entry "
<< "other than 'default'."
<< abort(FatalError);
}
dictionary solverDomainsDefault
(
solverDomains_.found("default")
? solverDomains_.subDict("default")
: dictionary()
);
}
void Foam::multiSolver::setSolverDomainControls(const word& solverDomainName)
{
currentSolverDomainDict_.clear();
if (solverDomains_.found("default"))
{
currentSolverDomainDict_.merge(solverDomains_.subDict("default"));
}
currentSolverDomainDict_.merge(solverDomains_.subDict(solverDomainName));
startFrom_ = mtsLatestTimeAllDomains;
if (currentSolverDomainDict_.found("startFrom"))
{
startFrom_ = startFromControlsNames_.read
(
currentSolverDomainDict_.lookup("startFrom")
);
}
if (currentSolverDomainDict_.found("startTime"))
{
startTime_ = readScalar(currentSolverDomainDict_.lookup("startTime"));
if (startTime_ < 0)
{
FatalErrorIn("multiSolver::setSolverDomainControls")
<< "'startTime' in multiControlDict/solverDomains/"
<< solverDomainName << " cannot be negative."
<< abort(FatalError);
}
}
else if (startFrom_ == mtsStartTime)
{
FatalErrorIn("multiSolver::setSolverDomainControls")
<< "'startTime' not defined in solverDomain '" << solverDomainName
<< "' or 'default'. startTime is required when startFrom "
<< "is set to 'startTime'."
<< abort(FatalError);
}
stopAt_ = msaEndTime;
if (currentSolverDomainDict_.found("stopAt"))
{
stopAt_ = stopAtControlsNames_.read
(
currentSolverDomainDict_.lookup("stopAt")
);
if
(
(stopAt_ == msaIterations)
&& (currentSolverDomainDict_.found("adjustTimeStep"))
&& (
readBool(currentSolverDomainDict_.lookup
("adjustTimeStep")) == true
)
)
{
FatalErrorIn("multiSolver::setSolverDomainControls")
<< "'stopAt' in multiControlDict/sovlerDomains cannot be set "
<< "to 'iterations' when 'adjustTimeStep' is 'true'."
<< abort(FatalError);
}
}
endTime_ = 0;
if (currentSolverDomainDict_.found("endTime"))
{
endTime_ = readScalar(currentSolverDomainDict_.lookup("endTime"));
}
if (currentSolverDomainDict_.found("iterations"))
{
iterations_ = readLabel
(
currentSolverDomainDict_.lookup("iterations")
);
}
else if (stopAt_ == msaIterations)
{
FatalErrorIn("multiSolver::setSolverDomainControls")
<< "'iterations' not defined in solverDomain '"
<< solverDomainName << "' or 'default'. iterations is required "
<< "when stopAt is set to iterations."
<< abort(FatalError);
}
if (currentSolverDomainDict_.found("elapsedTime"))
{
elapsedTime_ = readScalar(currentSolverDomainDict_.lookup("elapsedTime"));
}
else if (stopAt_ == msaElapsedTime)
{
FatalErrorIn("multiSolver::setSolverDomainControls")
<< "'elapsedTime' not defined in solverDomain '"
<< solverDomainName << "' or 'default'. elapsedTime is required "
<< "when stopAt is set to elapsedTime."
<< abort(FatalError);
}
if (currentSolverDomainDict_.found("storeFields"))
{
storeFields_ = wordList
(
currentSolverDomainDict_.lookup("storeFields")
);
}
purgeWriteSuperLoops_ = 0;
if (currentSolverDomainDict_.found("purgeWriteSuperLoops"))
{
purgeWriteSuperLoops_ = readLabel
(
currentSolverDomainDict_.lookup("purgeWriteSuperLoops")
);
}
if (currentSolverDomainDict_.found("deltaT"))
{
deltaT_ = readScalar
(
currentSolverDomainDict_.lookup("deltaT")
);
}
else
{
FatalErrorIn("multiSolver::setSolverDomainControls")
<< "'deltaT' not defined in solverDomain '"
<< solverDomainName << "' or 'default'. deltaT is required."
<< abort(FatalError);
}
if
(
currentSolverDomainDict_.found("timeFormat")
|| currentSolverDomainDict_.found("timePrecision")
)
{
WarningIn("multiSolver::setSolverDomainControls")
<< "Dictionary entry 'timeFormat' or 'timePrecision' found in "
<< "multiControlDict/solverDomain subdictionaries and will be "
<< "ignored. This setting must be applied universally in "
<< "multiControlDict/multiSolverControl."
<< endl;
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View file

@ -0,0 +1,265 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
void Foam::multiSolver::setInitialSolverDomain(const word& solverDomainName)
{
if (!solverDomains_.found(solverDomainName))
{
FatalErrorIn("multiSolver::setInitialSolverDomain")
<< "Initial solverDomainName '" << solverDomainName << "' does"
<< " not exist in multiSolver dictionary. Found entries are: "
<< solverDomains_.toc()
<< abort(FatalError);
}
currentSolverDomain_ = solverDomainName;
setSolverDomainControls(currentSolverDomain_);
// Purge all time directories from case directory root
purgeTimeDirs(multiDictRegistry_.path());
// Read initial settings and determine data source (from which path the
// initial data is copied, the starting superLoop_, and the current
// globalTime (used to determine globalOffset). Rules that are applied:
//
// 1. superLoop_ = data source superLoop
// a. unless data source solverDomain != currentSolverDomain_, in
// which case, superLoop_ = data source superLoop + 1
// 2. globalTime = data source globalTime. globalTime does not increment
// when swapping solver domains.
// 3. startTime = data source local time
// a. unless data source solverDomain != currentSolverDomain_, in
// which case, startTime is dictated by the solverDomains
// subdictionary.
// 4. endTime is determined by the solverDomains subdictionary
// a. unless the finalStopAt trumps it
timeCluster tcSource;
switch (initialStartFrom_)
{
case misFirstTime:
tcSource = findClosestGlobalTime
(
0, readSuperLoopTimes(currentSolverDomain_, -1)
);
break;
case misFirstTimeInStartDomain:
tcSource = findClosestGlobalTime
(
0, readSuperLoopTimes(startDomain_, -1)
);
break;
case misFirstTimeInStartDomainInStartSuperLoop:
tcSource = findClosestGlobalTime
(
0, readSuperLoopTimes(startDomain_, startSuperLoop_)
);
break;
case misStartTime:
if (initialStartTime_ == 0)
{
tcSource = findClosestGlobalTime
(
initialStartTime_,
readSuperLoopTimes(currentSolverDomain_, -1)
);
}
else
{
tcSource = findClosestGlobalTime
(
initialStartTime_, readAllTimes()
);
}
break;
case misStartTimeInStartDomain:
tcSource = findClosestLocalTime
(
initialStartTime_, readSolverDomainTimes(startDomain_)
);
break;
case misStartTimeInStartDomainInStartSuperLoop:
tcSource = findClosestLocalTime
(
initialStartTime_,
readSuperLoopTimes(startDomain_, startSuperLoop_)
);
break;
case misLatestTime:
tcSource = findLatestGlobalTime(readAllTimes());
break;
case misLatestTimeInStartDomain:
tcSource = findLatestLocalTime(readSolverDomainTimes(startDomain_));
break;
case misLatestTimeInStartDomainInStartSuperLoop:
tcSource = findLatestLocalTime
(
readSuperLoopTimes(startDomain_, startSuperLoop_)
);
break;
}
if (!tcSource.times().size())
{
// No relevant data found, set to initial conditions
tcSource = timeCluster
(
Time::findTimes
(
multiDictRegistry_.path()/"multiSolver"/currentSolverDomain_
/"initial"
),
0,
-1, // superLoop of -1 signifies "initial" directory
currentSolverDomain_
);
}
fileName sourcePath(findInstancePath(tcSource, 0));
superLoop_ = tcSource.superLoop();
// If starting from initial conditions, superLoop_ = -1
if (superLoop_ < 0) superLoop_ = 0;
scalar globalTime(tcSource.globalValue(0));
scalar localStartTime(tcSource.localValue(0));
// Now to apply the exceptions if currentSolverDomain_ != data source
// solverDomain (see long comment above).
if (sourcePath.path().path().name() != currentSolverDomain_)
{
superLoop_++;
switch (startFrom_)
{
case mtsFirstTime:
localStartTime = 0;
break;
case mtsStartTime:
localStartTime = startTime_;
break;
case mtsLatestTimeThisDomain:
{
timeCluster tcTemp
(
findLatestLocalTime
(
readSolverDomainTimes(currentSolverDomain_)
)
);
localStartTime = tcTemp.localValue(0);
}
break;
case mtsLatestTimeAllDomains:
localStartTime = globalTime;
break;
}
}
startTime_ = localStartTime;
globalTimeOffset_ = globalTime - startTime_;
// Give multiDictRegistry a time value (required for regIOobject::write()
// to case/[timeValue]
multiDictRegistry_.setTime(startTime_, 0);
// Copy the source data to case/[localTime]
cp(sourcePath, multiDictRegistry_.path());
mv
(
multiDictRegistry_.path()/sourcePath.name(),
multiDictRegistry_.path()/Time::timeName(startTime_)
);
// If the source data was in a different domain, swap the boundary conditions
if (sourcePath.path().path().name() != currentSolverDomain_)
{
swapBoundaryConditions
(
multiDictRegistry_.path()/Time::timeName(startTime_),
currentSolverDomain_
);
}
// Determine localEndTime and stopAtSetting
word stopAtSetting(setLocalEndTime());
// Build the new controlDict
IOdictionary newControlDict
(
IOobject
(
Time::controlDictName,
multiDictRegistry_.system(),
multiDictRegistry_,
IOobject::NO_READ,
IOobject::AUTO_WRITE,
false
),
currentSolverDomainDict_
);
// Remove multiSolver-specific values from dictionary
newControlDict.remove("startFrom");
newControlDict.remove("startTime");
newControlDict.remove("stopAt");
newControlDict.remove("endTime");
newControlDict.remove("iterations");
newControlDict.remove("purgeWriteSuperLoops");
newControlDict.remove("timeFormat");
newControlDict.remove("timePrecision");
newControlDict.remove("storeFields");
newControlDict.remove("elapsedTime");
// Add values to obtain the desired behaviour
newControlDict.set("startFrom", "startTime");
newControlDict.set("startTime", startTime_);
newControlDict.set("stopAt", stopAtSetting);
newControlDict.set("endTime", endTime_);
if (multiSolverControl_.found("timeFormat"))
{
newControlDict.set
(
"timeFormat",
word(multiSolverControl_.lookup("timeFormat"))
);
}
if (multiSolverControl_.found("timePrecision"))
{
newControlDict.set
(
"timePrecision",
readScalar(multiSolverControl_.lookup("timePrecision"))
);
}
// Write the dictionary to the case directory
newControlDict.regIOobject::write();
swapDictionaries(currentSolverDomain_);
}

View file

@ -0,0 +1,277 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
void Foam::multiSolver::setNextSolverDomain(const word& solverDomainName)
{
if (!solverDomains_.found(solverDomainName))
{
FatalErrorIn("multiSolver::setNextSolverDomain")
<< "Next solverDomainName '" << solverDomainName << "' does"
<< " not exist in multiSolver dictionary. Found entries are: "
<< solverDomains_.toc()
<< abort(FatalError);
}
readIfModified();
// Check if superLoop was just incremented to prevent saving the initial
// solverDomain data to the *next* superLoop
label saveToSuperLoop(superLoop_);
if (noSaveSinceSuperLoopIncrement_)
{
saveToSuperLoop--;
}
// Create archive path
fileName archivePath
(
multiDictRegistry_.path()/"multiSolver"/currentSolverDomain_/name
(
saveToSuperLoop
)
);
// Move all case/[time] to case/multiSolver/prefix/superloop/time
archiveTimeDirs
(
multiDictRegistry_.path(),
archivePath,
purgeWriteSuperLoops_
);
// Create multiSolverTime dictionary
IOdictionary multiSolverTime
(
IOobject
(
"multiSolverTime",
multiDictRegistry_.constant(),
multiDictRegistry_,
IOobject::NO_READ,
IOobject::AUTO_WRITE,
false
)
);
multiSolverTime.set("globalOffset", globalTimeOffset_);
// Write multiSolverTime to the case/constant directory, then move to
// archivePath
multiSolverTime.regIOobject::write();
mv(multiDictRegistry_.constantPath()/"multiSolverTime", archivePath);
// tcSource is where the latest data has been moved to
timeCluster tcSource
(
findLatestLocalTime
(
readSuperLoopTimes(currentSolverDomain_, saveToSuperLoop)
)
);
// Copy previous solverDomain data for use later (needed for storeFields)
wordList previousStoreFields(storeFields_);
word previousSolverDomain = currentSolverDomain_;
// Change all solverDomain data to the new solverDomain
currentSolverDomain_ = solverDomainName;
setSolverDomainControls(currentSolverDomain_);
fileName sourcePath(findInstancePath(tcSource, 0));
scalar globalTime(tcSource.globalValue(0));
scalar localStartTime(0);
switch (startFrom_)
{
case mtsFirstTime:
localStartTime = 0;
break;
case mtsStartTime:
localStartTime = startTime_;
break;
case mtsLatestTimeThisDomain:
{
timeCluster tcTemp
(
findLatestLocalTime
(
readSolverDomainTimes(currentSolverDomain_)
)
);
localStartTime = tcTemp.localValue(0);
}
break;
case mtsLatestTimeAllDomains:
localStartTime = globalTime;
break;
}
startTime_ = localStartTime;
globalTimeOffset_ = globalTime - startTime_;
// Give multiDictRegistry a time value (required for regIOobject::write()
// to case/[timeValue]
multiDictRegistry_.setTime(startTime_, 0);
word stopAtSetting("endTime");
if (!finished_)
{
// Copy the source data to case/[localTime]
cp(sourcePath, multiDictRegistry_.path());
mv
(
multiDictRegistry_.path()/sourcePath.name(),
multiDictRegistry_.path()/Time::timeName(startTime_)
);
// Copy the previous domain's storeFields from its first timestep to
// current time directory
if (previousStoreFields.size())
{
fileName storedSourcePath
(
findInstancePath
(
findClosestLocalTime
(
0,
readSuperLoopTimes
(
previousSolverDomain,
saveToSuperLoop
)
),
0
)
);
forAll (previousStoreFields, i)
{
// Copy the stored fields to case/[localTime].
if (exists(storedSourcePath/previousStoreFields[i]))
{
fileName storedSource(storedSourcePath/previousStoreFields[i]);
cp
(
storedSource,
multiDictRegistry_.path()/Time::timeName(startTime_)
/previousStoreFields[i]
);
}
else
{
FatalErrorIn("multiSolver::setNextSolverDomain")
<< "Attempting to copy stored field "
<< previousStoreFields[i] << " from "
<< previousSolverDomain << " to "
<< currentSolverDomain_ << " in superLoop "
<< saveToSuperLoop << ". File not found. This may occur "
<< "if " << previousSolverDomain << " is the first "
<< "solverDomain to be initialized, and you did not put "
<< "the stored fields into its 0/0 directory."
<< abort(FatalError);
}
}
}
swapBoundaryConditions
(
multiDictRegistry_.path()/Time::timeName(startTime_),
currentSolverDomain_
);
// Determine localEndTime and stopAtSetting
stopAtSetting = setLocalEndTime();
}
else //finished_
{
stopAtSetting = "noWriteNow";
}
// Build the new controlDict
IOdictionary newControlDict
(
IOobject
(
Time::controlDictName,
multiDictRegistry_.system(),
multiDictRegistry_,
IOobject::NO_READ,
IOobject::AUTO_WRITE,
false
),
currentSolverDomainDict_
);
// Remove multiSolver-specific values from dictionary
newControlDict.remove("startFrom");
newControlDict.remove("startTime");
newControlDict.remove("stopAt");
newControlDict.remove("endTime");
newControlDict.remove("iterations");
newControlDict.remove("purgeWriteSuperLoops");
newControlDict.remove("timeFormat");
newControlDict.remove("timePrecision");
newControlDict.remove("storeFields");
newControlDict.remove("elapsedTime");
// Add values to obtain the desired behaviour
newControlDict.set("startFrom", "startTime");
newControlDict.set("startTime", startTime_);
newControlDict.set("stopAt", stopAtSetting);
newControlDict.set("endTime", endTime_);
if (multiSolverControl_.found("timeFormat"))
{
newControlDict.set
(
"timeFormat",
word(multiSolverControl_.lookup("timeFormat"))
);
}
if (multiSolverControl_.found("timePrecision"))
{
newControlDict.set
(
"timePrecision",
readScalar(multiSolverControl_.lookup("timePrecision"))
);
}
// Write the dictionary to the case directory
newControlDict.regIOobject::write();
// Change all the dictionaries
swapDictionaries(currentSolverDomain_);
// Remove noSaves flag
if (noSaveSinceSuperLoopIncrement_)
{
noSaveSinceSuperLoopIncrement_ = false;
}
}

View file

@ -0,0 +1,758 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::labelList Foam::multiSolver::findSuperLoops(const fileName& path)
{
fileNameList dirEntries(readDir(path, fileName::DIRECTORY));
labelList superLoopList(dirEntries.size());
label nSuperLoops(0);
// Loop through dirEntries, checking for valid integers, sort entries
forAll(dirEntries, de)
{
// Check if directory is "initial"
if (dirEntries[de] == "initial")
{
superLoopList[nSuperLoops++] = -1;
continue;
}
IStringStream superLoopStream(dirEntries[de]);
token superLoopToken(superLoopStream);
// Check if directory is an integer
if (superLoopToken.isLabel() && superLoopStream.eof())
{
superLoopList[nSuperLoops++] = superLoopToken.labelToken();
}
}
superLoopList.setSize(nSuperLoops);
sort(superLoopList);
return superLoopList;
}
Foam::timeCluster Foam::multiSolver::findClosestGlobalTime
(
const Foam::scalar value,
const Foam::timeClusterList& tcl,
const bool& exact
)
{
scalar maxDiff(-VGREAT);
scalar minDiff(VGREAT);
label underShoot(-1);
label best(-1);
label initial(-1);
// Find closest global minimum that does not exceed value
forAll(tcl, i)
{
if (!tcl[i].times().size()) continue;
scalar diff(tcl[i].globalMinValue() - value);
if ((diff <= 0) && (diff >= maxDiff))
{
// "initial" directory may be a duplicate match - others take
// priority.
if ((tcl[i].superLoop() < 0) && (diff > maxDiff))
{
initial = i;
}
else
{
initial = -1;
best = i;
}
maxDiff = diff;
}
else if ((diff > 0) && (diff < minDiff))
{
// This is in case all timeClusters exceed value - then we have to
// return the closest minValue
minDiff = diff;
underShoot = i;
}
}
if (initial != -1)
{
// "initial" directory is the only match
best = initial;
}
if (best == -1)
{
if (minDiff != -1)
{
// All timeClusters exceed value, return closest minValue
best = underShoot;
}
else
{
FatalErrorIn("multiSolver::findClosestGlobalTime")
<< "The timeClusterList passed to this function has no non-"
<< "empty instantLists. Use timeClusterList::purgeEmpties "
<< "and check its return value to prevent this."
<< abort(FatalError);
}
}
label timeIndex
(
Time::findClosestTimeIndex
(
tcl[best].times(), value - tcl[best].globalOffset()
)
);
if (exact && (maxDiff < -VSMALL))
{
FatalErrorIn("multiSolver::findClosestGlobalTime")
<< "No exact match found for global time = " << value
<< abort(FatalError);
}
return tcl[best](timeIndex);
}
Foam::timeCluster Foam::multiSolver::findClosestLocalTime
(
const Foam::scalar value,
const Foam::timeClusterList& tcl,
const bool& exact
)
{
scalar maxDiff(-VGREAT);
scalar minDiff(VGREAT);
label underShoot(-1);
label best(-1);
label initial(-1);
timeClusterList tclDummy;
const timeClusterList * tclPtr;
if (nonOverlapping(tcl))
{
tclPtr = & tcl;
}
else
{
tclDummy = tcl.selectiveSubList(findMaxSuperLoopIndices(tcl));
tclPtr = & tclDummy;
}
for (label i = 0; i < tclPtr->size(); i++)
{
if (!tclPtr->operator[](i).times().size()) continue;
scalar diff(tclPtr->operator[](i).localMinValue() - value);
if ((diff <= 0) && (diff >= maxDiff))
{
// "initial" directory may be a duplicate match - others take
// priority.
if ((tclPtr->operator[](i).superLoop() < 0) && (diff > maxDiff))
{
initial = i;
}
else
{
initial = -1;
best = i;
}
maxDiff = diff;
}
else if ((diff > 0) && (diff < minDiff))
{
// This is in case all timeClusters exceed value - then we have to
// return the closest minValue
minDiff = diff;
underShoot = i;
}
}
if (initial != -1)
{
// "initial" directory is the only match
best = initial;
}
if (best == -1)
{
if (minDiff != -1)
{
// All timeClusters exceed value, return closest minValue
best = underShoot;
}
else
{
FatalErrorIn("multiSolver::findClosestLocalTime")
<< "The timeClusterList passed to this function has no non-"
<< "empty instantLists. Use timeClusterList::purgeEmpties "
<< "and check its return value to prevent this."
<< abort(FatalError);
}
}
label timeIndex
(
Time::findClosestTimeIndex
(
tclPtr->operator[](best).times(), value
)
);
if (exact && (maxDiff < -VSMALL))
{
FatalErrorIn("multiSolver::findClosestLocalTime")
<< "No exact match found for local time = " << value
<< abort(FatalError);
}
return tclPtr->operator[](best)(timeIndex);
}
Foam::timeCluster Foam::multiSolver::findLatestGlobalTime
(
const Foam::timeClusterList& tcl
)
{
timeCluster bestMax(0);
timeCluster currentMax;
forAll(tcl, i)
{
if (tcl[i].times().size() == 0) continue;
currentMax = tcl[i](tcl[i].globalMaxIndex());
if
(
(currentMax.globalValue(0) > bestMax.globalValue(0))
|| (
(currentMax.globalValue(0) == bestMax.globalValue(0))
&& (currentMax.superLoop() != -1)
)
)
{
bestMax = currentMax;
}
}
if (bestMax.solverDomainName() == word::null)
{
FatalErrorIn("multiSolver::findLatestGlobalTime")
<< "The timeClusterList passed to this function has no non-empty "
<< "instantLists. Use timeClusterList::purgeEmpties and check its"
<< " return value to prevent this."
<< abort(FatalError);
}
return bestMax;
}
Foam::timeCluster Foam::multiSolver::findLatestLocalTime
(
const Foam::timeClusterList& tcl
)
{
timeClusterList dummyTcl;
const timeClusterList * tclPtr;
timeCluster bestMax(0);
timeCluster currentMax;
if (nonOverlapping(tcl))
{
tclPtr = & tcl;
}
else
{
dummyTcl = tcl.selectiveSubList(findMaxSuperLoopIndices(tcl));
tclPtr = & dummyTcl;
}
for (label i = 0; i < tclPtr->size(); i++)
{
if (tclPtr->operator[](i).times().size() == 0) continue;
currentMax =
tclPtr->operator[](i)(tclPtr->operator[](i).localMaxIndex());
if
(
(currentMax.localValue(0) > bestMax.localValue(0))
|| (
(currentMax.localValue(0) == bestMax.localValue(0))
&& (currentMax.superLoop() != -1)
)
)
{
bestMax = currentMax;
}
}
if (bestMax.solverDomainName() == word::null)
{
FatalErrorIn("multiSolver::findLatestLocalTime")
<< "The timeClusterList passed to this function has no non-empty "
<< "instantLists. Use timeClusterList::purgeEmpties and check its"
<< " return value to prevent this."
<< abort(FatalError);
}
return bestMax;
}
Foam::fileName Foam::multiSolver::findInstancePath
(
const timeCluster& tc,
const label& index
) const
{
if (!tc.times().size())
{
FatalErrorIn("multiSolver::findInstancePath")
<< "The timeClusterList passed to this function has no non-empty "
<< "instantLists. Use timeClusterList::purgeEmpties and check its"
<< " return value to prevent this."
<< abort(FatalError);
}
if (tc.superLoop() < 0)
{
// Initial directory
return fileName
(
multiDictRegistry_.path()/"multiSolver"/tc.solverDomainName()
/"initial"/tc[index].name()
);
}
else
{
return fileName
(
multiDictRegistry_.path()/"multiSolver"/tc.solverDomainName()
/name(tc.superLoop())/tc[index].name()
);
}
}
Foam::label Foam::multiSolver::findMaxSuperLoopValue(const timeClusterList& tcl)
{
if (!tcl.size())
{
FatalErrorIn("multiSolver::findMaxSuperLoopValue")
<< "The timeClusterList passed to this function is empty. Use "
<< "timeClusterList::purgeEmpties and check its return value to "
<< "prevent this."
<< abort(FatalError);
}
return tcl[findMaxSuperLoopIndices(tcl)[0]].superLoop();
}
Foam::labelList Foam::multiSolver::findMaxSuperLoopIndices(const timeClusterList& tcl)
{
label currentMax(-2);
labelList bestIndices(0);
label maxesFound(0);
forAll(tcl, i)
{
if (!tcl[i].times().size()) continue;
if (currentMax == tcl[i].superLoop())
{
bestIndices.setSize(++maxesFound);
bestIndices[maxesFound - 1] = i;
}
else if (currentMax < tcl[i].superLoop())
{
currentMax = tcl[i].superLoop();
maxesFound = 1;
bestIndices.setSize(1);
bestIndices[0] = i;
}
}
if (bestIndices.size() == 0)
{
FatalErrorIn("multiSolver::findMaxSuperLoopIndices")
<< "The timeClusterList passed to this function is empty. Use "
<< "timeClusterList::purgeEmpties and check its return value to "
<< "prevent this."
<< abort(FatalError);
}
return bestIndices;
}
bool Foam::multiSolver::nonOverlapping
(
const Foam::timeClusterList& tcl,
const bool useGlobalTime
)
{
// see tuple2Lists.H
scalarScalarList range(tcl.size());
if (useGlobalTime)
{
forAll(tcl, i)
{
if (!tcl[i].times().size())
{
range[i].first() = 0;
range[i].second() = 0;
}
else
{
range[i].first() = tcl[i].globalMinValue();
range[i].second() = tcl[i].globalMaxValue();
}
}
}
else
{
forAll(tcl, i)
{
if (!tcl[i].times().size())
{
range[i].first() = 0;
range[i].second() = 0;
}
else
{
range[i].first() = tcl[i].localMinValue();
range[i].second() = tcl[i].localMaxValue();
}
}
}
sortTuple2ListBy1stThen2nd(range);
for (label i = 0; i < (range.size() - 1); i++)
{
// Using '-SMALL' below is a temporary bug fix
if (range[i + 1].first() - range[i].second() < -SMALL)
{
// timeClusters overlap
return false;
}
}
return true;
}
Foam::timeCluster Foam::multiSolver::readSuperLoopTimes
(
const Foam::word& solverDomain,
const Foam::label superLoop,
const Foam::word& processor
) const
{
fileName currentPath;
if (processor.size())
{
currentPath = multiDictRegistry_.path()/processor;
}
else
{
currentPath = multiDictRegistry_.path();
}
if (superLoop < 0)
{
currentPath = currentPath/"multiSolver"/solverDomain
/"initial";
}
else
{
currentPath = currentPath/"multiSolver"/solverDomain
/name(superLoop);
}
fileName mstFileName
(
currentPath/"multiSolverTime"
);
IFstream mstFile(mstFileName);
bool mstFileGood(false);
scalar globalOffset(0);
if (mstFile.good())
{
dictionary mstDict(mstFile);
if (mstDict.found("globalOffset"))
{
globalOffset =
readScalar(mstDict.lookup("globalOffset"));
mstFileGood = true;
}
}
if ((!mstFileGood) && (superLoop != -1))
{
WarningIn("multiSolver::readSuperLoopTimes")
<< "Bad or missing multiSolverTime dictionary (auto-"
<< "generated) in case/multiSolver/" << solverDomain
<< "/" << superLoop << ". Assuming globalOffset = 0"
<< endl;
}
timeCluster tc
(
Time::findTimes(currentPath),
globalOffset,
superLoop,
solverDomain
);
return tc;
}
Foam::timeClusterList Foam::multiSolver::readSolverDomainTimes
(
const word& solverDomain,
const word processor
) const
{
timeClusterList tcl(0);
label nTimeClusters(0);
fileName locale;
if (processor.size())
{
locale = processor/"multiSolver";
}
else
{
locale = "multiSolver";
}
fileName currentPath
(
multiDictRegistry_.path()/locale/solverDomain
);
labelList superLoopList(multiSolver::findSuperLoops(currentPath));
// Loop through superLoopList, check for valid data, store in tcl
forAll(superLoopList, sl)
{
timeCluster tc
(
readSuperLoopTimes(solverDomain, superLoopList[sl], processor)
);
// If there are no time directories, ignore this superLoop
if (tc.times().size() == 0) continue;
// Store timeCluster
tcl.setSize(++nTimeClusters);
tcl[nTimeClusters - 1] = tc;
}
return tcl;
}
Foam::timeClusterList Foam::multiSolver::readAllTimes
(
const word processor
) const
{
timeClusterList tcl(0);
// Loop through solverDomains
forAll(prefixes_, pf)
{
if (prefixes_[pf] == "default") continue;
timeClusterList tclIn(readSolverDomainTimes(prefixes_[pf], processor));
tcl.append(tclIn);
}
return tcl;
}
bool Foam::multiSolver::loadTimeClusterList
(
const Foam::timeClusterList& tcl,
const bool useGlobalTime,
const bool loadStoreFields
) const
{
if (!nonOverlapping(tcl, useGlobalTime)) return false;
wordList storeFields;
forAll(tcl, i)
{
fileName currentPath
(
findInstancePath(tcl[i], 0).path()
);
instantList il(Time::findTimes(currentPath));
fileName storeFieldsPath
(
currentPath/il[Time::findClosestTimeIndex(il, -1.0)].name()
);
if
(
loadStoreFields
&& solverDomains_
.subDict(tcl[i].solverDomainName())
.found("storeFields")
)
{
storeFields = wordList(solverDomains_
.subDict(tcl[i].solverDomainName())
.lookup("storeFields"));
}
else
{
storeFields.clear();
}
forAll(tcl[i].times(), j)
{
fileName storeFieldsDestination
(
multiDictRegistry_.path()/tcl[i].times()[j].name()
);
cp
(
currentPath/tcl[i].times()[j].name(),
multiDictRegistry_.path()
);
if (useGlobalTime)
{
storeFieldsDestination = multiDictRegistry_.path()/
Time::timeName
(
tcl[i].globalValue(j)
);
mv
(
multiDictRegistry_.path()/tcl[i].times()[j].name(),
storeFieldsDestination
);
}
if
(
loadStoreFields
&& (storeFieldsPath != storeFieldsDestination)
)
{
forAll(storeFields, j)
{
cp
(
storeFieldsPath/storeFields[j],
storeFieldsDestination
);
}
}
} // end cycle through instants
} // end cycle through timeClusters
return true;
}
void Foam::multiSolver::archiveTimeDirs
(
const Foam::fileName& sourcePath,
const Foam::fileName& archivePath,
const Foam::label& purgeWrite
)
{
if (archivePath.name() == "initial")
{
FatalErrorIn("multiSolver::archiveTimeDirs")
<< "Attempting to archive to the 'initial' directory. This is "
<< "not permitted. sourcePath = " << sourcePath << ", archivePath"
<< " = " << archivePath
<< abort(FatalError);
}
if (exists(archivePath))
{
purgeTimeDirs(archivePath);
}
mkDir(archivePath);
// Perform purgeWrite of superLoop directories
if (purgeWrite)
{
labelList allSL(findSuperLoops(archivePath.path()));
label currentSL(atoi(archivePath.name().c_str()));
sort(allSL);
label i = 0;
while (allSL[i] < currentSL)
{
i++;
}
for (label j = 1; j <= (i - purgeWrite); j++)
{
rmDir(archivePath.path()/name(allSL[j]));
}
}
instantList timeDirs(Time::findTimes(sourcePath));
forAll(timeDirs, i)
{
if (timeDirs[i].name() == "constant") continue;
mv(sourcePath/timeDirs[i].name(), archivePath/timeDirs[i].name());
}
}
void Foam::multiSolver::purgeTimeDirs(const Foam::fileName& path)
{
instantList timeDirs(Time::findTimes(path));
forAll(timeDirs, i)
{
if (timeDirs[i].name() == "constant") continue;
rmDir(path/timeDirs[i].name());
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View file

@ -0,0 +1,243 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "timeClusterList.H"
#include "Time.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const char* const Foam::timeCluster::typeName = "timeCluster";
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::timeCluster::timeCluster()
{}
Foam::timeCluster::timeCluster
(
const instantList& times,
const scalar globalOffset,
const label superLoop,
const word& solverDomainName,
const word& preConName
)
:
instantList(times),
globalOffset_(globalOffset),
superLoop_(superLoop),
solverDomainName_(solverDomainName),
preConName_(preConName)
{}
Foam::timeCluster::timeCluster
(
const timeCluster& tc,
const label index
)
:
instantList(1, tc[index]),
globalOffset_(tc.globalOffset_),
superLoop_(tc.superLoop_),
solverDomainName_(tc.solverDomainName_),
preConName_(tc.preConName_)
{}
Foam::timeCluster::timeCluster(const Foam::scalar t)
:
instantList(1, instant(0)),
globalOffset_(0),
superLoop_(0),
solverDomainName_(word::null),
preConName_(word::null)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::scalar Foam::timeCluster::globalValue(const label& index) const
{
return this->operator[](index).value() + globalOffset_;
}
Foam::scalar Foam::timeCluster::globalMinValue() const
{
return this->localMinValue() + globalOffset_;
}
Foam::scalar Foam::timeCluster::globalMaxValue() const
{
return this->localMaxValue() + globalOffset_;
}
Foam::label Foam::timeCluster::globalMinIndex() const
{
return this->localMinIndex();
}
Foam::label Foam::timeCluster::globalMaxIndex() const
{
return this->localMaxIndex();
}
Foam::scalar Foam::timeCluster::globalFindClosestTimeValue
(
const scalar timeValue
) const
{
return this->operator[]
(
Foam::Time::findClosestTimeIndex
(
this->times(), timeValue - globalOffset_
)
).value() + globalOffset_;
}
Foam::label Foam::timeCluster::globalFindClosestTimeIndex
(
const scalar timeValue
) const
{
return Foam::Time::findClosestTimeIndex
(
this->times(), timeValue - globalOffset_
);
}
Foam::scalar Foam::timeCluster::localValue(const label& index) const
{
return this->operator[](index).value();
}
Foam::scalar Foam::timeCluster::localMinValue() const
{
return this->operator[](this->localMinIndex()).value();
}
Foam::scalar Foam::timeCluster::localMaxValue() const
{
return this->operator[](this->localMaxIndex()).value();
}
Foam::label Foam::timeCluster::localMinIndex() const
{
label bestIndex(0);
scalar min(VGREAT);
forAll(*this, i)
{
if (this->operator[](i).value() < min)
{
min = this->operator[](i).value();
bestIndex = i;
}
}
return bestIndex;
}
Foam::label Foam::timeCluster::localMaxIndex() const
{
label bestIndex(0);
scalar max(0);
forAll(*this, i)
{
if (this->operator[](i).value() > max)
{
max = this->operator[](i).value();
bestIndex = i;
}
}
return bestIndex;
}
Foam::scalar Foam::timeCluster::localFindClosestTimeValue
(
const scalar timeValue
) const
{
return this->operator[]
(
Foam::Time::findClosestTimeIndex
(
this->times(), timeValue
)
).value();
}
Foam::label Foam::timeCluster::localFindClosestTimeIndex
(
const scalar timeValue
) const
{
return Foam::Time::findClosestTimeIndex
(
this->times(), timeValue
);
}
Foam::timeCluster Foam::timeCluster::operator()(const Foam::label index) const
{
return timeCluster(*this, index);
}
// * * * * * * * * * * * * * Friend IOstream Operators * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, timeCluster& I)
{
return is >> I.globalOffset_
>> I.superLoop_
>> I.solverDomainName_
>> I.preConName_
>> I.times();
}
Foam::Ostream& Foam::operator<<(Ostream& os, const timeCluster& I)
{
return os << "/* globalOffset: */\t" << I.globalOffset_ << nl
<< "/* superLoop: */\t" << I.superLoop_ << nl
<< "/* solverDomain: */\t" << I.solverDomainName_ << nl
<< "/* preConName: */\t" << I.preConName_ << nl
<< "/* Instant list: */\t" << I.times();
}
// ************************************************************************* //

View file

@ -0,0 +1,233 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::timeCluster
Description
A cluster of time instances, used with multiSolver. Catalogues all the
time directories within a superLoop, within a solverDomain. A single
time cluster describes what would be analogous to all the time directories
for a solver that does not use multiSolver.
SourceFiles
timeCluster.C
Author
David L. F. Gaden
\*---------------------------------------------------------------------------*/
#ifndef timeCluster_H
#define timeCluster_H
#include "word.H"
#include "scalar.H"
#include "instantList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of friend functions and operators
class timeCluster;
// Friend IOstream Operators
Istream& operator>>(Istream&, timeCluster&);
Ostream& operator<<(Ostream&, const timeCluster&);
/*---------------------------------------------------------------------------*\
Class timeCluster Declaration
\*---------------------------------------------------------------------------*/
class timeCluster
:
public instantList
{
// Private data
scalar globalOffset_;
label superLoop_;
word solverDomainName_;
// PreConditioned file name - used only for pre and post conditioning
// a data set for parallel runs
word preConName_;
public:
// Public classes
//- Less function class used in sorting timeClusters
class less
{
public:
bool operator()(const timeCluster& one, const timeCluster& two) const
{
return one.globalMinValue() < two.globalMinValue();
}
};
// Static data members
static const char* const typeName;
// Constructors
//- Construct null
timeCluster();
//- Construct from components
timeCluster
(
const instantList& times,
const scalar globalOffset,
const label superLoop,
const word& solverDomainName,
const word& preConName = word::null
);
//- Construct given a timeCluster and an index
// This creates a 'timeCluster' that holds a single instant
// in time, whose other values match those of tc.
timeCluster
(
const timeCluster& tc,
const label index
);
//- Construct a time cluster given a scalar value. This constructs
// a timeCluster with a single instant of time at value t, and whose
// other values are zero or empty.
explicit timeCluster(const scalar t);
// Member Functions
// Access
//- Times
inline const instantList& times() const;
inline instantList& times();
//- Global offset
inline scalar globalOffset() const;
inline scalar& globalOffset();
//- SuperLoop
inline label superLoop() const;
inline label& superLoop();
//- Solver domain name
inline const word& solverDomainName() const;
inline word& solverDomainName();
//- Solver domain name
inline const word& preConName() const;
inline word& preConName();
// Derived values
//- Global value at index
scalar globalValue(const label& index) const;
//- Search for and return global min value. If empty,
// returns VGREAT.
scalar globalMinValue() const;
//- Search for and return global max value. If empty,
// returns 0.
scalar globalMaxValue() const;
//- Search for and return index of global min value
label globalMinIndex() const;
//- Search for and return index of global max value
label globalMaxIndex() const;
//- Global closest time
scalar globalFindClosestTimeValue(const scalar) const;
//- Global closest time index
label globalFindClosestTimeIndex(const scalar) const;
//- Local value at index
scalar localValue(const label& index) const;
//- Search for and return local min value
scalar localMinValue() const;
//- Search for and return local max value
scalar localMaxValue() const;
//- Search for and return index of global min value. If empty,
// returns VGREAT
label localMinIndex() const;
//- Search for and return index of global max value. If empty,
// returns 0.
label localMaxIndex() const;
//-Local closest time
scalar localFindClosestTimeValue(const scalar) const;
//-Local closest time index
label localFindClosestTimeIndex(const scalar) const;
// Operators
//- Chip off a single instant given an index, return as timeCluster
// This retains superLoop, solverDomain, etc.. with a timevalue
timeCluster operator()(const label index) const;
// Friend IOstream Operators
friend Istream& operator>>(Istream&, timeCluster&);
friend Ostream& operator<<(Ostream&, const timeCluster&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "timeClusterI.H"
#endif
// ************************************************************************* //

View file

@ -0,0 +1,88 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
inline const instantList& timeCluster::times() const
{
const instantList& times(*this);
return times;
}
inline instantList& timeCluster::times()
{
instantList& times(*this);
return times;
}
inline scalar timeCluster::globalOffset() const
{
return globalOffset_;
}
inline scalar& timeCluster::globalOffset()
{
return globalOffset_;
}
inline label timeCluster::superLoop() const
{
return superLoop_;
}
inline label& timeCluster::superLoop()
{
return superLoop_;
}
inline const word& timeCluster::solverDomainName() const
{
return solverDomainName_;
}
inline word& timeCluster::solverDomainName()
{
return solverDomainName_;
}
inline const word& timeCluster::preConName() const
{
return preConName_;
}
inline word& timeCluster::preConName()
{
return preConName_;
}
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View file

@ -0,0 +1,156 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "timeClusterList.H"
#include "Time.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const char* const Foam::timeClusterList::typeName = "timeClusterList";
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::timeClusterList::timeClusterList()
:
List<timeCluster>()
{}
Foam::timeClusterList::timeClusterList(const Foam::label size)
:
List<timeCluster>(size)
{}
Foam::timeClusterList::timeClusterList(const timeCluster& tcIn)
:
List<timeCluster>(1, tcIn)
{}
Foam::timeClusterList::timeClusterList(const Foam::label size, const Foam::timeCluster& tcIn)
:
List<timeCluster>(size, tcIn)
{}
Foam::timeClusterList::timeClusterList(const labelList& subIndices, const timeClusterList& tclIn)
:
List<timeCluster>(subIndices.size())
{
forAll(subIndices, i)
{
this->operator[](i) = tclIn[subIndices[i]];
}
}
Foam::timeClusterList::timeClusterList(Foam::Istream& is)
:
List<timeCluster>(is)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::timeClusterList::globalSort()
{
Foam::sort(*this, timeCluster::less());
}
void Foam::timeClusterList::append(const timeClusterList& tclIn)
{
label wasSize = this->size();
this->setSize(tclIn.size() + this->size());
for (label i = 0; i < tclIn.size(); i++)
{
this->operator[](i + wasSize) = tclIn[i];
}
}
void Foam::timeClusterList::append(const timeCluster& tcIn)
{
label wasSize = this->size();
this->setSize(this->size() + 1);
this->operator[](wasSize) = tcIn;
}
bool Foam::timeClusterList::purgeEmpties()
{
if (!this->size()) return false;
label empties(0);
for (label i = 0; i < this->size(); i++)
{
if (!this->operator[](i).times().size())
{
empties++;
continue;
}
if (empties)
{
this->operator[](i - empties) = this->operator[](i);
}
}
if (empties)
{
this->setSize(this->size() - empties);
}
if (!this->size()) return false;
return true;
}
Foam::timeClusterList Foam::timeClusterList::selectiveSubList
(
const labelList& indices
) const
{
timeClusterList tcl(indices.size());
forAll(indices, i)
{
if (indices[i] > this->size())
{
FatalErrorIn("timeClusterList::selectiveSubList")
<< "Out of range index passed to this function. Indices "
<< "passed are: \n" << indices << "\nFailure at index " << i
<< ", with value " << indices[i] << ".\n This timeClusterList "
<< "has size " << this->size() << "."
<< abort(FatalError);
}
tcl[i] = this->operator[](indices[i]);
}
return tcl;
}
// ************************************************************************* //

View file

@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::timeClusterList
Description
List of timeClusters with some additional functions
SourceFiles
timeClusterList.C
\*---------------------------------------------------------------------------*/
#ifndef timeClusterList_H
#define timeClusterList_H
#include "timeCluster.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class timeClusterList Declaration
\*---------------------------------------------------------------------------*/
class timeClusterList
:
public List<timeCluster>
{
public:
// Static data members
static const char* const typeName;
// Constructors
//- Null constructor
timeClusterList();
//- Construct with given size.
explicit timeClusterList(const label);
//- Construct from a timeCluster.
timeClusterList(const timeCluster&);
//- Construct with given size and value for all elements.
timeClusterList(const label, const timeCluster&);
//- Construct as a sublist of another timeClusterList. This is not
// like the SubList in that this is not a new class, rather it is only
// producing a new copy that contains the specified entries.
timeClusterList(const labelList&, const timeClusterList&);
//- Construct from Istream.
timeClusterList(Istream&);
// Member functions
//- Sort by global time
void globalSort();
//- Append another timeClusterList on the end of this one
void append(const timeClusterList& tclIn);
//- Append a timeCluster on the end of this list
void append(const timeCluster& tcIn);
//- Remove timeClusters with empty instantLists return false if all are
// empty
bool purgeEmpties();
//- Return a sublist using the specified indexes
timeClusterList selectiveSubList(const labelList&) const;
};
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,113 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Typedef
Foam::tuple2List
Description
List of paired values, with sorting capability
Author
David L. F. Gaden
\*---------------------------------------------------------------------------*/
#ifndef tuple2Lists_H
#define tuple2Lists_H
#include "Tuple2.H"
#include "List.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef List<Tuple2<label, label> > labelLabelList;
typedef List<Tuple2<label, scalar> > labelScalarList;
typedef List<Tuple2<scalar, label> > scalarLabelList;
typedef List<Tuple2<scalar, scalar> > scalarScalarList;
template<class type1, class type2>
bool lessFirst(Tuple2<type1, type2> t1, Tuple2<type1, type2> t2)
{
return (t1.first() < t2.first());
}
template<class type1, class type2>
bool lessFirstSecond(Tuple2<type1, type2> t1, Tuple2<type1, type2> t2)
{
return
(
(t1.first() < t2.first())
|| ((t1.first() == t2.first()) && (t1.second() < t2.second()))
);
}
template<class type1, class type2>
bool lessSecond(Tuple2<type1, type2> t1, Tuple2<type1, type2> t2)
{
return (t1.second() < t2.second());
}
template<class type1, class type2>
bool lessSecondFirst(Tuple2<type1, type2> t1, Tuple2<type1, type2> t2)
{
return
(
(t2.first() < t1.first())
|| ((t2.first() == t1.first()) && (t2.second() < t1.second()))
);
}
template<class type1, class type2>
void sortTuple2ListBy1st(List<Tuple2<type1, type2> >& t2l)
{
sort(t2l, lessFirst<type1, type2>);
}
template<class type1, class type2>
void sortTuple2ListBy2nd(List<Tuple2<type1, type2> >& t2l)
{
sort(t2l, lessSecond<type1, type2>);
}
template<class type1, class type2>
void sortTuple2ListBy1stThen2nd(List<Tuple2<type1, type2> >& t2l)
{
sort(t2l, lessFirstSecond<type1, type2>);
}
template<class type1, class type2>
void sortTuple2ListBy2ndThen1st(List<Tuple2<type1, type2> >& t2l)
{
sort(t2l, lessSecondFirst<type1, type2>);
}
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -0,0 +1,32 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5-dev |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object multiTransportProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dictionaryName transportProperties;
multiSolver
{
scalarTransportFoam
{
DT DT [0 2 -1 0 0 0 0] 0.0;
}
icoFoam1
{
nu nu [0 2 -1 0 0 0 0] 0.01;
}
icoFoam2
{
nu nu [0 2 -1 0 0 0 0] 0.01;
}
}

View file

@ -0,0 +1,90 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object blockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
convertToMeters 0.1;
vertices
(
(0 0 0)
(1.5 0 0)
(1.5 1 0)
(0 1 0)
(2.5 0 0)
(4 0 0)
(4 1 0)
(2.5 1 0)
(1.5 2.5 0)
(2.5 2.5 0)
(0 0 0.1)
(1.5 0 0.1)
(1.5 1 0.1)
(0 1 0.1)
(2.5 0 0.1)
(4 0 0.1)
(4 1 0.1)
(2.5 1 0.1)
(1.5 2.5 0.1)
(2.5 2.5 0.1)
);
blocks
(
hex (0 1 2 3 10 11 12 13) (20 20 1) simpleGrading (1 1 1)
hex (1 4 7 2 11 14 17 12) (20 20 1) simpleGrading (1 1 1)
hex (4 5 6 7 14 15 16 17) (20 20 1) simpleGrading (1 1 1)
hex (2 7 9 8 12 17 19 18) (20 20 1) simpleGrading (1 1 1)
);
edges
(
);
patches
(
wall steetWalls
(
(1 0 10 11)
(4 1 11 14)
(5 4 14 15)
(2 3 13 12)
(6 7 17 16)
)
wall branchWalls
(
(8 2 12 18)
(7 9 19 17)
)
patch westStreet
(
(3 0 10 13)
)
patch eastStreet
(
(5 6 16 15)
)
patch northBranch
(
(9 8 18 19)
)
);
mergePatchPairs
(
);
// ************************************************************************* //

View file

@ -0,0 +1,58 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5-dev |
| \\ / A nd | Revision: exported |
| \\/ M anipulation | Web: http://www.OpenFOAM.org |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class polyBoundaryMesh;
location "constant/polyMesh";
object boundary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
6
(
steetWalls
{
type wall;
nFaces 100;
startFace 3100;
}
branchWalls
{
type wall;
nFaces 40;
startFace 3200;
}
westStreet
{
type patch;
nFaces 20;
startFace 3240;
}
eastStreet
{
type patch;
nFaces 20;
startFace 3260;
}
northBranch
{
type patch;
nFaces 20;
startFace 3280;
}
defaultFaces
{
type empty;
nFaces 3200;
startFace 3300;
}
)
// ************************************************************************* //

View file

@ -0,0 +1,21 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.7.1 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object transportProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
nu nu [ 0 2 -1 0 0 0 0 ] 0.01;
// ************************************************************************* //

View file

@ -0,0 +1,50 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
object p;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 0 0 1 0 0 0];
internalField uniform 0;
boundaryField
{
steetWalls
{
type zeroGradient;
}
branchWalls
{
type zeroGradient;
}
westStreet
{
type zeroGradient;
}
eastStreet
{
type zeroGradient;
}
northBranch // inlet
{
type fixedValue;
value uniform 1;
}
defaultFaces
{
type empty;
}
}
// ************************************************************************* //

View file

@ -0,0 +1,53 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
object U;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 1 -1 0 0 0 0];
internalField uniform (0 0 0);
boundaryField
{
steetWalls
{
type fixedValue;
value uniform (0 0 0);
}
branchWalls
{
type fixedValue;
value uniform (0 0 0);
}
westStreet // closed
{
type fixedValue;
value uniform (0 0 0);
}
eastStreet // outlet
{
type zeroGradient;
}
northBranch // inlet
{
type fixedValue;
value uniform (0 -1 0);
}
defaultFaces
{
type empty;
}
}
// ************************************************************************* //

View file

@ -0,0 +1,50 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
object p;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 2 -2 0 0 0 0];
internalField uniform 0;
boundaryField
{
steetWalls
{
type zeroGradient;
}
branchWalls
{
type zeroGradient;
}
westStreet // closed
{
type zeroGradient;
}
eastStreet // outlet
{
type fixedValue;
value uniform 0;
}
northBranch // inlet
{
type zeroGradient;
}
defaultFaces
{
type empty;
}
}
// ************************************************************************* //

View file

@ -0,0 +1,50 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
object p;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 0 0 1 0 0 0];
internalField uniform 0;
boundaryField
{
steetWalls
{
type zeroGradient;
}
branchWalls
{
type zeroGradient;
}
westStreet
{
type zeroGradient;
}
eastStreet
{
type zeroGradient;
}
northBranch
{
type fixedValue;
value uniform 1;
}
defaultFaces
{
type empty;
}
}
// ************************************************************************* //

View file

@ -0,0 +1,52 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
object U;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 1 -1 0 0 0 0];
internalField uniform (0 0 0);
boundaryField
{
steetWalls
{
type fixedValue;
value uniform (0 0 0);
}
branchWalls
{
type fixedValue;
value uniform (0 0 0);
}
westStreet // outlet
{
type zeroGradient;
}
eastStreet // inlet
{
type fixedValue;
value uniform (-1 0 0);
}
northBranch // outlet
{
type zeroGradient;
}
defaultFaces
{
type empty;
}
}
// ************************************************************************* //

View file

@ -0,0 +1,51 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
object p;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 2 -2 0 0 0 0];
internalField uniform 0;
boundaryField
{
steetWalls
{
type zeroGradient;
}
branchWalls
{
type zeroGradient;
}
westStreet // outlet
{
type fixedValue;
value uniform 0;
}
eastStreet // inlet
{
type zeroGradient;
}
northBranch // outlet
{
type fixedValue;
value uniform 0;
}
defaultFaces
{
type empty;
}
}
// ************************************************************************* //

View file

@ -0,0 +1,50 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
object p;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 0 0 1 0 0 0];
internalField uniform 0;
boundaryField
{
steetWalls
{
type zeroGradient;
}
branchWalls
{
type zeroGradient;
}
westStreet
{
type zeroGradient;
}
eastStreet
{
type zeroGradient;
}
northBranch // inlet
{
type fixedValue;
value uniform 1;
}
defaultFaces
{
type empty;
}
}
// ************************************************************************* //

View file

@ -0,0 +1,52 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
object U;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 1 -1 0 0 0 0];
internalField uniform (0 0 0);
boundaryField
{
steetWalls
{
type fixedValue;
value uniform (0 0 0);
}
branchWalls
{
type fixedValue;
value uniform (0 0 0);
}
westStreet // outlet
{
type zeroGradient;
}
eastStreet // closed
{
type zeroGradient;
}
northBranch // inlet
{
type fixedValue;
value uniform (0 -1 0);
}
defaultFaces
{
type empty;
}
}
// ************************************************************************* //

View file

@ -0,0 +1,47 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.7.1 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
writeFormat ascii;
writePrecision 6;
writeCompression uncompressed;
runTimeModifiable yes;
application icoFoam;
deltaT 0.01;
writeControl timeStep;
writeInterval 1;
startFrom startTime;
startTime 0.1;
stopAt endTime;
endTime 0.1;
timeFormat scientific;
timePrecision 6;
// ************************************************************************* //

View file

@ -0,0 +1,60 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.7.1 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
ddtSchemes
{
default Euler;
}
gradSchemes
{
default Gauss linear;
grad(p) Gauss linear;
}
divSchemes
{
default none;
div(phi,U) Gauss linear;
}
laplacianSchemes
{
default none;
laplacian(nu,U) Gauss linear corrected;
laplacian((1|A(U)),p) Gauss linear corrected;
}
interpolationSchemes
{
default linear;
interpolate(HbyA) linear;
}
snGradSchemes
{
default corrected;
}
fluxRequired
{
default no;
p ;
}
// ************************************************************************* //

View file

@ -0,0 +1,45 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.7.1 |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
solvers
{
p
{
solver PCG;
preconditioner DIC;
tolerance 1e-06;
relTol 0;
}
U
{
solver PBiCG;
preconditioner DILU;
tolerance 1e-05;
relTol 0;
}
}
PISO
{
nCorrectors 2;
nNonOrthogonalCorrectors 0;
pRefCell 0;
pRefValue 0;
}
// ************************************************************************* //

View file

@ -0,0 +1,70 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5-dev |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object multiSolverDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
multiSolverControl
{
initialStartFrom startTime;
startTime 0;
finalStopAt endSuperLoop;
endSuperLoop 3;
timeFormat scientific;
timePrecision 6;
}
solverDomains
{
icoFoam1
{
application icoFoam;
startFrom startTime;
startTime 0;
stopAt endTime;
endTime 0.1;
deltaT 0.01;
writeControl timeStep;
writeInterval 1;
storeFields ( T );
}
icoFoam2
{
application icoFoam;
startFrom startTime;
startTime 0;
stopAt endTime;
endTime 0.1;
deltaT 0.01;
writeControl timeStep;
writeInterval 1;
storeFields ( T );
}
scalarTransportFoam
{
application scalarTransportFoam;
startFrom latestTimeAllDomains;
stopAt elapsedTime;
elapsedTime 1;
deltaT 0.1;
writeControl timeStep;
writeInterval 1;
storeFields ( p );
}
default
{
writeFormat ascii;
writePrecision 6;
writeCompression uncompressed;
runTimeModifiable yes;
}
}

View file

@ -0,0 +1,150 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5-dev |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object multiFvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dictionaryName fvSchemes;
multiSolver
{
icoFoam1
{
ddtSchemes
{
default Euler;
}
gradSchemes
{
default Gauss linear;
grad(p) Gauss linear;
}
divSchemes
{
default none;
div(phi,U) Gauss linear;
}
laplacianSchemes
{
default none;
laplacian(nu,U) Gauss linear corrected;
laplacian((1|A(U)),p) Gauss linear corrected;
}
interpolationSchemes
{
default linear;
interpolate(HbyA) linear;
}
snGradSchemes
{
default corrected;
}
fluxRequired
{
default no;
p;
}
}
icoFoam2
{
ddtSchemes
{
default Euler;
}
gradSchemes
{
default Gauss linear;
grad(p) Gauss linear;
}
divSchemes
{
default none;
div(phi,U) Gauss linear;
}
laplacianSchemes
{
default none;
laplacian(nu,U) Gauss linear corrected;
laplacian((1|A(U)),p) Gauss linear corrected;
}
interpolationSchemes
{
default linear;
interpolate(HbyA) linear;
}
snGradSchemes
{
default corrected;
}
fluxRequired
{
default no;
p;
}
}
scalarTransportFoam
{
ddtSchemes
{
default none;
ddt(T) Euler;
}
gradSchemes
{
default Gauss linear;
}
divSchemes
{
default none;
div(phi,T) Gauss upwind;
}
laplacianSchemes
{
default none;
laplacian(DT,T) Gauss linear corrected;
}
interpolationSchemes
{
default linear;
}
snGradSchemes
{
default corrected;
}
fluxRequired
{
default no;
}
}
}
// ************************************************************************* //

View file

@ -0,0 +1,100 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5-dev |
| \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object multiFvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dictionaryName fvSolution;
multiSolver
{
icoFoam1
{
solvers
{
p
{
solver PCG;
preconditioner DIC;
tolerance 1e-06;
relTol 0;
};
U
{
solver PBiCG;
preconditioner DILU;
tolerance 1e-05;
relTol 0;
};
}
PISO
{
nCorrectors 2;
nNonOrthogonalCorrectors 0;
pRefCell 0;
pRefValue 0;
}
}
icoFoam2
{
solvers
{
p
{
solver PCG;
preconditioner DIC;
tolerance 1e-06;
relTol 0;
};
U
{
solver PBiCG;
preconditioner DILU;
tolerance 1e-05;
relTol 0;
};
}
PISO
{
nCorrectors 2;
nNonOrthogonalCorrectors 0;
pRefCell 0;
pRefValue 0;
}
}
scalarTransportFoam
{
solvers
{
T
{
solver PBiCG;
preconditioner DILU;
tolerance 1e-05;
relTol 0;
};
}
SIMPLE
{
nNonOrthogonalCorrectors 0;
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //