Difference between revisions of "Contrib/multiSolver"

From OpenFOAMWiki
Line 3: Line 3:
 
<BR>'''OpenFOAM 1.5-dev''', '''OpenFOAM 1.6-ext''' and '''OpenFOAM 1.7.1''' as well
 
<BR>'''OpenFOAM 1.5-dev''', '''OpenFOAM 1.6-ext''' and '''OpenFOAM 1.7.1''' as well
 
<BR>
 
<BR>
<small>Subpage contents<BR>
+
<small>Subpage contents (alphabetical)<BR>
> [[Contrib_multiSolver/installation|installation]]<BR>
+
 
> [[Contrib_multiSolver/glossary|glossary]]<BR>
 
> [[Contrib_multiSolver/glossary|glossary]]<BR>
 +
> [[Contrib_multiSolver/installation|installation]]<BR>
 
> [[Contrib_multiSolver/multiControlDict|multiControlDict]]<BR>
 
> [[Contrib_multiSolver/multiControlDict|multiControlDict]]<BR>
> [[Contrib_multiSolver/Post processing|post processing]]<BR>
 
 
> [[Contrib_multiSolver/parallel|parallel]]<BR>
 
> [[Contrib_multiSolver/parallel|parallel]]<BR>
> [[Contrib_multiSolver/programming|programming]]<BR></small>
+
> [[Contrib_multiSolver/Post processing|post processing]]<BR>
 +
> [[Contrib_multiSolver/programming|programming]]<BR>
 +
> [[Contrib_multiSolver/Using_multiSolver|using multiSolver]]<BR></small>
 
<BR>
 
<BR>
 
'''Major upgrade - multiSolver''' now fully supports [[Contrib_multiSolver/parallel|parallel]] runs.
 
'''Major upgrade - multiSolver''' now fully supports [[Contrib_multiSolver/parallel|parallel]] runs.
Line 53: Line 54:
 
then '''multiSolver''' might help you.
 
then '''multiSolver''' might help you.
  
== Parallel ==
+
== Learn more ==
'''Parallel runs are now supported!'''  See [[Contrib_multiSolver/parallel|here]] for more information.
+
* ''"I'm sold, let me install it!"'' - Check out the [[Contrib_multiSolver/installation|installation sub-page]].
 +
* ''"I'm a user. How do I work with a '[[Contrib_multiSolver/glossary#superSolver|superSolver]]'?"''  Check out the [[Contrib_multiSolver/Using_multiSolver|user's guide sub-page]].
 +
* ''"How do I post-process a '[[Contrib_multiSolver/glossary#superSolver|superSolver]]'?"'''  Check out the [[Contrib_multiSolver/Post_processing|post processing sub-page]].
 +
* ''"One processor is for losers.  How do I work with it in parallel?"'' Check out the [[Contrib_multiSolver/parallel|parellel sub-page]].
 +
* ''"I'm a developper.  How do I program with '''multiSolver'''?"''  Check out the [[Contrib_multiSolver/programming|programming sub-page]].
  
 
== Mesh motion not fully supported yet ==
 
== Mesh motion not fully supported yet ==
'''NOTE:''' At this time, '''multiSolver''' allows for mesh motion, provided the mesh returns to its original position between solvers.  This functionality is planned for the future.
+
'''NOTE:''' At this time, '''multiSolver''' allows for mesh motion, provided the mesh returns to its original position between solvers.  This functionality is planned for the future.  I plan to do this in the late summer or fall (2011).
 
+
== How do you program applications with it? ==
+
First [[Contrib_multiSolver/installation|install]] it.
+
 
+
For a detailed look at programming with multiSolver, see [[Contrib_multiSolver/programming]]<span id="simpleExample">Here's a simple '''multiSolver'''-enabled application, or "[[Contrib_multiSolver/glossary#superSolver|superSolver]]":
+
 
+
<cpp>/*---------------------------------------------------------------------------*\
+
                            ... 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);
+
}
+
 
+
// ************************************************************************* //
+
</cpp></span>
+
 
+
'''Basic strategy:'''
+
 
+
* Write (or choose existing) solvers that you intend to use with your [[Contrib_multiSolver/glossary#superSolver|superSolver]];
+
* The <tt>createFields.H</tt> files (and associate <tt>#include</tt> statements) have to be renamed if they differ between solvers;
+
* Add <tt>#include "multiSolver.H"</tt> to the top of the solver;
+
* Just after <tt>#include "setRootCase.H"</tt>, add: <tt>#include "createMultiSolver.H"</tt>
+
* Between solvers use:
+
<cpp>    solverDomain = "nextSolverDomain";
+
#  include "setSolverDomain.H"</cpp>
+
* End with:
+
<cpp>#include "endMultiSolver.H"
+
return (0);</cpp>
+
 
+
== How do you run simulations with it? ==
+
First [[Contrib_multiSolver/installation|install]] it.
+
 
+
Here is a brief overview of how to work with a '''multiSolver'''-enabled application.
+
 
+
=== MultiControlDict ===
+
The [[Contrib_multiSolver/multiControlDict|multiControlDict]][[Contrib_multiSolver/glossary#multiControlDict|(glossary)]] is the '''multiSolver''' analogue of the <tt>controlDict</tt>.  The <tt>controlDict</tt> is auto-generated based on the content of this file.  The [[Contrib_multiSolver/multiControlDict|multiControlDict]] is the main control dictionary and therefore it does not conform to the format of a regular [[#multiDicts|multiDict]][[Contrib_multiSolver/glossary#multiDict|(glossary)]].  For the full break-down of all settings and options available in the multiControlDict, see [[Contrib_multiSolver/multiControlDict|multiControlDict]].
+
 
+
=== 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 [[Contrib_multiSolver/glossary#solverDomain|solverDomain]].  To specify this behaviour, a [[Contrib_multiSolver/glossary#multiDict|multiDict]] is used.
+
 
+
Multidicts:
+
 
+
* sit in the same directory as the dictionary they are managing;
+
* have the prefix <tt>multi</tt>, followed by the name of their child dictionary; and
+
* are not required if the dictionary doesn't need to change between solvers.
+
 
+
For example, a typical constant directory might look like:
+
 
+
constant
+
|-environmentalProperties    standard dictionary (does not change)
+
|-multiTransportProperties  multiDictionary (describes change)
+
'-transportProperties        auto-generated dictionary (changes)
+
 
+
In this directory, there are three files:
+
* <tt>environmentalProperties</tt> - this is a standard dictionary.  It is user-editable and will not change during a run.  '''multiSolver''' ignores these files;
+
* <tt>multiTransportProperties</tt> - this is a [[Contrib_multiSolver/glossary#multiDict|multiDict]].  It is also user-editable and will not change during a run.  '''multiSolver''' recognizes it by its prefix "<tt>multi</tt>".  It describes how the dictionary <tt>transportProperties</tt> should change during a run;
+
* <tt>transportProperties</tt> - this dictionary is automatically generated by '''multiSolver'''.  Its content changes during a run (and during post-processing).  Editing this file is only useful for ''runTime modification''.
+
 
+
A [[Contrib_multiSolver/glossary#multiDict|multiDict]] has the following structure:
+
dictionaryName  fvSchemes;
+
+
multiSolver
+
{
+
    sovlerDomainName1 // this is the [[Contrib_multiSolver/glossary#solverDomain|solverDomain]] name
+
    {
+
          // settings for the first solver go here
+
    }
+
    solverDomainName2 // another [[Contrib_multiSolver/glossary#solverDomain|solverDomain]] name
+
    {
+
        // settings for the second solver go here
+
    }
+
    solverDomainName3 // etc..
+
    {
+
    }
+
    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
+
    }
+
}
+
 
+
Sometimes, two or more [[Contrib_multiSolver/glossary#solverDomain|solverDomains]] will have identical dictionaries.  Rather than write out their settings several times, the <tt>sameAs</tt> keyword is available:
+
 
+
solverDomainName1
+
{
+
    // settings for the first solver go here
+
}
+
solverDomainName2
+
{
+
    sameAs  solverDomainName1;
+
}
+
 
+
'''Remember:''' although the <tt>multiControlDict</tt> has the same naming conventions, this file is not a [[Contrib_multiSolver/glossary#multiDict|multiDict]].  It contains the main control settings for '''multiSolver''', and has a different format from a [[Contrib_multiSolver/glossary#multiDict|multiDict]].
+
 
+
=== Boundary conditions and initial values ===
+
The boundary conditions and initial values are located in:
+
 
+
:<tt>case/multiSolver/<nowiki>[</nowiki>[[Contrib_multiSolver/glossary#solverDomainName|solverDomainName]]<nowiki>]</nowiki>/initial/0</tt>
+
 
+
This is the analogue of the <tt>case/0</tt> directory, except there is one for every [[Contrib_multiSolver/glossary#solverDomain|solverDomain]].  Unlike in a regular simulation, '''multiSolver''' will ''always'' refer to the boundary conditions located in <tt>initial/0</tt>.
+
 
+
==== Changing boundary conditions ====
+
'''multiSolver''' allows the boundary conditions to change between [[Contrib_multiSolver/glossary#solverDomain|solverDomains]].  To accomplish this, the latest ''internalField'' is combined with the ''boundaryField'' from <tt>initial/0</tt>.
+
 
+
==== Advanced boundary condition settings ====
+
It is possible that some boundary conditions may create ''boundaryField'' values that need to be kept up to date.  These values would be lost with the default behaviour described above.  For example, say you have a custom outlet boundary condition called... I don't know... <tt>obliqueFractalInversion</tt>, and during a simulation, it creates a field called <tt>fractalness</tt>, and this field needs to be kept up to date.  In other words, you want '''multiSolver''' to ''remember'' <tt>fractalness</tt>.  To accomplish this, a <tt>multiSolverRemember</tt> list may be specified in <tt>initial/0</tt>:
+
 
+
boundaryField
+
{
+
    inlet
+
    {
+
        type                  fixedValue;
+
        value                uniform (1 0 0);
+
    }
+
    outlet
+
    {
+
        type                  obliqueFractalInversion;
+
        fractalness          uniform 0;
+
        '''multiSolverRemember  (fractalness);'''
+
    }
+
}
+
 
+
Now '''multiSolver''' will always keep this component of the boundary field up to date.  This feature also works for more than one entry in the same boundary patch; and for more than one boundary patch.  For instance:
+
 
+
boundaryField
+
{
+
    inlet
+
    {
+
        type                  fluffyPuddingInlet;
+
        dFluffinessDt        uniform (0 0 0);
+
        value                uniform (1 0 0);
+
        '''multiSolverRemember  (dFluffinessDt);'''
+
    }
+
    outlet
+
    {
+
        type                  strangeFractalInversion;
+
        fractalness          uniform 0;
+
        strangeness          uniform 1;
+
        '''multiSolverRemember  (fractalness strangeness);'''
+
    }
+
}
+
 
+
=== Output Data ===
+
The data is sorted into [[Contrib_multiSolver/glossary#superLoop|superLoop]] subdirectories within subdirectories named after the [[Contrib_multiSolver/glossary#solverDomain|solverDomain]]:
+
 
+
:<tt>case/multiSolver/<nowiki>[</nowiki>[[Contrib_multiSolver/glossary#solverDomainName|solverDomainName]]<nowiki>]</nowiki>/<nowiki>[</nowiki>[[Contrib_multiSolver/glossary#superLoopIndex|superLoopIndex]]<nowiki>]</nowiki>/[timeValue]</tt>
+
 
+
The standard location of <tt>case/[timeValue]</tt> is used as a temporary loading area, mostly for post-processing.
+
 
+
=== Post-processing ===
+
OpenFOAM is hard-coded to look for data in the <tt>case/[time]</tt> directories.  In order to post-process (including sampling, and data conversion) the data needs to be there.  To accomplish this, [[Contrib_multiSolver/Post processing|a post processing utility]] is available.  Typing the command <tt>multiSolver</tt> in the terminal accesses this.  It has four main commands:
+
 
+
* <tt>-load</tt> - copy data files from their storage location to <tt>case/time</tt> (i.e. load the data for post-processing);
+
* <tt>-purge</tt> - delete data files;
+
* <tt>-list</tt> - display the contents found in the case directory storage location; and
+
* <tt>-set</tt> - make the case directory appear as required for the given solver name.
+
 
+
For more details, see [[Contrib_multiSolver/Post processing|post processing]].
+
 
+
=== Runtime Modification ===
+
There are two levels of runtime modification: within a [[Contrib_multiSolver/glossary#solverDomain|solverDomain]], and globally.
+
 
+
* Editting a standard dictionary (e.g. <tt>controlDict</tt>, or <tt>transportProperties</tt> applies to a [[Contrib_multiSolver/glossary#solverDomain|solverDomain]].  Its effect depends on whether that solver has <tt>runTimeModifiable</tt> enabled.  This happens at the end of a solver iteration.  However, these changes will be lost in the next [[Contrib_multiSolver/glossary#superLoop|superLoop]] when the same [[Contrib_multiSolver/glossary#solverDomain|solverDomain]] is initialized.
+
 
+
* Editting a [[Contrib_multiSolver/glossary#multiDict|multiDict]] dictionary applies globally.  This is goverend by <tt>multiDictsRunTimeModifiable</tt> setting in the [[Contrib_multiSolver/multiControlDict|multiControlDict]], but these modifications do not take place until the next [[Contrib_multiSolver/glossary#solverDomain|solverDomain]] is initialized.  However, these changes are permanent.
+
 
+
=== Local time and Global time ===
+
A fundamental principle of '''multiSolver''' is that time is independent between [[Contrib_multiSolver/glossary#solverDomain|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.
+
 
+
==== Initial start ====
+
The [[Contrib_multiSolver/multiControlDict|multiControlDict]] has settings for an initial start defined gloablly (<tt>initialStartAt</tt>), and an initial start defined for each solverDomain (<tt>startAt</tt>).  Sometimes these settings may appear to come into conflict.  What happens when <tt>initialStartAt</tt> is set to <tt>latestTimeAllDomains</tt>, but <tt>startAt</tt> is set to <tt>startTime = 0</tt>?
+
 
+
The <tt>initialStartAt</tt> settings are where the ''initial data'' is read from.  The <tt>startAt</tt> settings are where the ''local time value'' starts from.  Sometimes you may be trying to resume from the middle of a run, and the initial time value should pick up from where it left off.  '''multiSolver''' tries to determine when this is the case.  The rules are:
+
 
+
* <tt>startAt</tt> time is equal to the localTime of the <tt>initialStartAt</tt> data source;
+
* if the <tt>initialStartAt</tt> is from a different solverDomain than the initial solverDomain, the <tt>startAt</tt> time specified in the <tt>multiControlDict</tt> is used instead.
+
 
+
==== Switching domains ====
+
When switching domains:
+
* globalTime stays the same (i.e. time does not step when switching domains); and
+
* localTime is set to the value specified by the <tt>startAt</tt> settings in the <tt>multiControlDict</tt>.
+
 
+
==== End time ====
+
The local <tt>stopAt</tt> settings are always compared with the global <tt>finalStopAt</tt> settings.  If the <tt>finalStopAt</tt> value occurs ''before'' the local <tt>stopAt</tt> value, the <tt>finalStopAt</tt> value is used, and the end condition is set.
+
 
+
==== Initial superLoop ====
+
The initial superLoop value is determined by the <tt>initialStartAt</tt> settings.  It is set to be equal to the superLoop value of the <tt>initialStartAt</tt> data source.  If the <tt>initialStartAt</tt> data source is from a different solverDomain than the initial solverDomain, the ''next'' superLoop is used.
+
 
+
=== Store fields ===
+
Some solvers may not need to use all the fields created by other solvers.  On the other hand, these other solvers need the latest values for these fields.  There are two options for handling this:
+
 
+
# add the unneeded fields to the <tt>createFields.H</tt> of the solver.  The extra fields will be carried in memory, and written out at every time step.
+
# declare these fields as <tt>storeFields</tt> in the [[Contrib_multiSolver/glossary#multiControlDict|multiControlDict]].  With this option, for the solver that doesn't need them, these fields will not be loaded in memory, and will be written only to the first timestep in each run.
+
 
+
'''Note:''' If the ''first'' [[Contrib_multiSolver/glossary#solverDomain|solverDomain]] to run has a <tt>storeFields</tt> declared, that field must also exist in this solver's <tt>initial/0</tt> directory.
+
 
+
== 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 <tt>ddtSchemes</tt> setting in <tt>fvSchemes</tt>; likewise a steady state solver will see <tt>steadyState</tt> for <tt>ddtSchemes</tt>.  This is the purpose of the [[#multiDicts|multiDict]][[Contrib_multiSolver/glossary#multiDict|(glossary)]] dictionary format.
+
 
+
The data output and input are hard-coded to the <tt>case/[timeValue]</tt> directory.  Therefore, when '''multiSolver''' initializes the next [[Contrib_multiSolver/glossary#solverDomain|solverDomain]], it archives the existing output into the correct directory at <tt>case/multiSolver/<nowiki>[</nowiki>[[Contrib_multiSolver/glossary#solverDomainName|solverDomainName]]<nowiki>]</nowiki>/<nowiki>[</nowiki>[[Contrib_multiSolver/glossary#superLoopIndex|superLoopIndex]]<nowiki>]</nowiki>/[timeValue]</tt>, and copies the latest field values to the initial time the next solver expects.
+
  
 
== Update info ==
 
== Update info ==
Line 304: Line 69:
 
* ''2011-04-05'': Major upgrade - now works for parallel simulations
 
* ''2011-04-05'': Major upgrade - now works for parallel simulations
 
* ''2011-06-03'': Minor bug fix - decompose nolonger omits the initial directories
 
* ''2011-06-03'': Minor bug fix - decompose nolonger omits the initial directories
 +
* ''2011-07-01'': Overhauled the documentation on the wiki page (no change to the code)

Revision as of 16:36, 1 July 2011

multiSolver allows you to run more than one solver on the same dataset in sequence.
Valid versions: OF version 15.png OF version 16.png OF version 17.png
OpenFOAM 1.5-dev, OpenFOAM 1.6-ext and OpenFOAM 1.7.1 as well
Subpage contents (alphabetical)
> glossary
> installation
> multiControlDict
> parallel
> post processing
> programming
> using multiSolver

Major upgrade - multiSolver now fully supports parallel runs.

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 universal time can still be used.
  • 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 post processing utility.
  • Store fields - To save memory and hard drive space, not all solvers have to use all the fields. Rather, they can "store" any unneeded fields, 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 Learn more

6 Mesh motion not fully supported yet

NOTE: At this time, multiSolver allows for mesh motion, provided the mesh returns to its original position between solvers. This functionality is planned for the future. I plan to do this in the late summer or fall (2011).

7 Update info

  • 2010-07-23: Initial import
  • 2011-03-29: Minor bug fix for 1.6-ext and 1.7.1
  • 2011-04-05: Major upgrade - now works for parallel simulations
  • 2011-06-03: Minor bug fix - decompose nolonger omits the initial directories
  • 2011-07-01: Overhauled the documentation on the wiki page (no change to the code)