Contrib/multiSolver

From OpenFOAMWiki
< Contrib
Revision as of 04:04, 1 July 2010 by Marupio (Talk | contribs)

Subpage contents
> glossary
> In depth - moving this to programming
> multiControlDict
> multiPost
I am currently travelling and working offline. Updates will appear when I return (July 4th) or if I get internet access

1 What is it?

multiSolver is a master control class that allows you to create a superSolver composed of multiple solvers within a superLoop. All solvers operate on the same dataset in sequence. For example:

  1. icoFoam - runs to completion;
  2. data is handed over to scalarTransportFoam;
  3. scalarTransportFoam - runs to completion;
  4. data is handed back to icoFoam, and the superLoop repeats.

2 Features

  • Multiple solvers - multiple solvers can be used in sequence on the same data set.
  • Changing boundary conditions - the boundary conditions can change at distinct time intervals.
  • Independent time - each solver can operate with an independent time value, although the standard universal time can still be designated.
  • Single case directory - the settings for all solvers are stored within a single case directory using a "multiDict" dictionary format.
  • Easy data management - All the data output is sorted into subdirectories corresponding to the solver, and can be loaded / unloaded using the multiPost utility.
  • Store fields - To save memory and hard drive space, not all solvers have to use all the fields. Rather, they can "store" an unneeded field, leaving more memory and disk space. The next solver retrieves all stored fields, and no data is lost.

3 Why would you need this?

A fundamental assumption in the design of OpenFOAM is the existence of a universal time. Therefore the time object is the top-level objectRegistry (i.e. runTime hosts the database for your simulation). This design works for nearly all simulations imaginable, except for those that require more than one time frame. For these situations, multiSolver will come in handy.

4 When would you need this?

The capabilities of multiSolver are useful for:

  • multi-step processes to be modelled within a single application, e.g. fluid injection, followed by settling;
  • modelling of a flow problem characterized by two different timescales, e.g. stirring with biochemical reactions; and
  • changing boundary conditions mid-run.

Basically, if you find yourself:

  • frequently copying data between case directories;
  • frequently stopping and changing the simulation details, then restarting; or
  • using runTime++ more than once in your solver,

then multiSolver might help you.

5 Parallel runs and mesh motion not fully supported yet

NOTE: At this time, multiSolver does not support parallel runs at all; and mesh motion is allowed, provided the mesh returns to its original position between solvers. This functionality is planned for the future.

6 How do you program applications with it?

For a detailed look at programming with multiSolver, see TestMarupio/programming. Here's a simple multiSolver-enabled application, or "superSolver":

/*---------------------------------------------------------------------------*\
                             ... STANDARD HEADER ...
\*---------------------------------------------------------------------------*/
 
#include "fvCFD.H"
#include "multiSolver.H"
 
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
int main(int argc, char *argv[])
{
 
#   include "setRootCase.H"
#   include "createMultiSolver.H"
 
// * * * * * * * * * * * * * * * * icoFoam  * * * * * * * * * * * * * * * * //
 
    Info << "*** Switching to icoFoam1 ***\n" << endl;
    solverDomain = "icoFoam";
#   include "setSolverDomain.H"
 
// Paste everything from icoFoam.C, starting with #include "createTime.H",
// and ending just before (but not including) return 0;
 
// * * * * * * * * * * * * * scalarTransportFoam * * * * * * * * * * * * * * //
 
    Info << "*** Switching to scalarTransportFoam ***\n" << endl;
    solverDomain = "scalarTransportFoam";
#   include "setSolverDomain.H"
 
// Paste everything from scalarTransportFoam.C, again, starting with
// #include "createTime.H", and ending just before (but not including)
// return 0;
 
#   include "endMultiSolver.H"
    return(0);
}
 
// ************************************************************************* //

Basic strategy:

  • Write (or choose existing) solver that you intend to use with your superSolver;
  • The createFields.H files (and associate #include statements) have to be renamed if they differ between solvers;
  • Add #include "multiSolver.H" to the top of the solver;
  • Just after <tt>#include "setRootCase.H", add: #include "createMultiSolver.H"
  • Between solvers use:
    solverDomain = "nextSolverDomain";
#   include "setSolverDomain.H" 
 
  • End with:
#include "endMultiSolver.H"
return (0);

7 How do you run simulations with it?

Here is a brief overview of how to work with a multiSolver-enabled application.

7.1 MultiControlDict

The multiControlDict(glossary) is the multiSolver analogue of the controlDict. The controlDict is auto-generated based on the content of this file. The multiControlDict is the main control dictionary and therefore it does not conform to the format of a regular multiDict(glossary). For the full break-down of all settings and options available in the multiControlDict, see multiControlDict.

7.2 MultiDicts

A regular solver reads information from various dictionary files, and these affect its behaviour. When using multiSolver, there will be dictionaries whose values need to be different for each solverDomain. To specify this behaviour, a multiDict is used.

A multiDict has the following structure:

dictionaryName   fvSchemes;

multiSolver
{
    sovlerDomainName1 // this is the solverDomain name
    {
         // settings for the first solver go here
    }
    solverDomainName2 // another solverDomain name
    {
        // settings for the second solver go here
    }
    default // optional
    {
        // default settings go here
        // these are loaded first, then overwritten by solverName (above)
        // solvers whose names are not listed above inherit only these settings, or none at all if default is absent
    }
}

7.3 Boundary conditions and initial values

The boundary conditions and initial values are located in:

case/multiSolver/[solverDomainName]/0/0

This is the analogue of the case/0 directory, except there is one for every solverDomain. Unlike in a regular simulation, multiSolver will always refer to the boundary conditions located in 0/0.

multiSolver allows the boundary conditions to change between solverDomains. To accomplish this, multiSolver will use the boundaryField specified in [solverDomainName]/0/0 and copy over the latest internalField (from the previous solverDomain).

7.4 Output Data

The data is sorted into superLoop subdirectories within subdirectories named after the solverDomain:

case/multiSolver/[solverDomainName]/[superLoopIndex]/[timeValue]

The standard location of case/[timeValue] is used as a temporary loading area, mostly for post-processing.

7.5 Post-processing

OpenFOAM is hard-coded to look for data in the case/[time] directories. In order to post-process (including sampling, and data conversion) the data needs to be there. To accomplish this, multiPost is available. multiPost has four main commands:

  • -load - copy data files from their storage location to case/time (i.e. load the data for post-processing);
  • -purge - delete data files;
  • -list - display the contents found in the case directory storage location; and
  • -set - make the case directory appear as required for the given solver name.

For more details, see multiPost.

7.6 Runtime Modification

There are two levels of runtime modification: within a solverDomain, and globally.

  • Editting a standard dictionary (e.g. controlDict, or transportProperties applies to a solverDomain. Its effect depends on whether that solver has runTimeModifiable enabled. This happens at the end of a solver iteration. However, these changes will be lost in the next superLoop when the same solverDomain is initialized.
  • Editting a multiDict dictionary applies globally. This is goverend by multiDictsRunTimeModifiable setting in the multiControlDict, but these modifications do not take place until the next solverDomain is initialized. However, these changes are permanent.

7.7 Local time and Global time

A fundamental principle of multiSolver is that time is independent between solverDomains. (If this causes you apprehension, don't worry, the default behaviour uses a standard global time.) Therefore there are two defined time values:

  • localTime - the value known to the solver; and
  • globalTime - the universal time, known only by multiSolver.

8 How does it work?

OpenFOAM is incredibly flexible, and easily extensible, but implementing a change of this kind challenged its founding assumptions. Therefore, the flexibility was not there on level it needed to be, leaving little option but to use a top-level wrapper implementation.

A wrapper encloses the targeted object in a class that gives it the environment it expects to operate, while simultaneously presenting a different environment to other objects interfacing with it. At the top-level, the "other objects" are users. (Strictly speaking, at the code-level, multiSolver is not a true wrapper since it doesn't include an "OpenFOAM solver" as a member variable, but it is in principle.)

multiSolver works by mutating the case directory into what each solver requires. A transient solver will see the correct ddtSchemes setting in fvSchemes; likewise a steady state solver will see steadyState for ddtSchemes. This is the purpose of the multiDict(glossary) dictionary format.

The data output and input are hard-coded to the case/[timeValue] directory. Therefore, when multiSolver initializes the next solverDomain, it archives the existing output into the correct directory at case/multiSolver/[solverDomainName]/[superLoopIndex]/[timeValue]