Difference between revisions of "Contrib equationReader/Programming"

From OpenFOAMWiki
(Migrated to github)
 
Line 1: Line 1:
Most of the programming features can be gleaned from the '''equationReader''' demo application.  Please also refer to that.
+
This project has migrated over to '''github'''.
  
== Creating an equationReader object ==
+
'''''[http://github.com/Marupio/equationReader/wiki Click here for the new website.]'''''
To add '''equationReader''' to an application:
+
  
* Put <tt>#include "IOEquationReader.H"</tt> at the top of your main source file;
+
http://github.com/Marupio/equationReader/wiki
* Put <tt>#include "createEquationReader.H"</tt> somewhere after <tt>createTime</tt>;
+
 
+
== Adding data sources ==
+
You need to add data sources - this is where '''equationReader''' looks for its variables.
+
 
+
=== Beware of duplicate sources ===
+
Currently, '''equationReader''' does not check if you are adding multiple variables of the same name.  When this happens, you never know which source will be used.  I didn't add it because it didn't occur to me until I started writing this paragraph.  Expect it in the future.
+
 
+
=== Is the data permanent? ===
+
Data must be permanently available.  For instance, <tt>mesh.C()</tt> is a valid data source because it returns a &reference.  But <tt>turbulence->R()</tt> is not valid because it returns an object (or <tt>tmp<object></tt>), and hence is ''derived'' from other permanent sources.
+
 
+
To use ''derived'' data sources, there are two options.
+
 
+
1. Create a permanent copy, and update it at every timestep.  This is demonstrated in the '''equationReaderDemo''' application.
+
 
+
2. Create an ''activeVariable''.
+
 
+
=== Active variables ===
+
'''(Advanced developers)'''
+
 
+
An ''activeVariable'' is one that does not permanently store its data, and provides values ''on-demand'' to '''equationReader'''.  The key to this is it must be able to calculate a single cell value on-demand, and not the entire field at once.  The interface is given in the <tt>equationReader/equationVariable/equationVariable.H</tt> file.
+
 
+
=== Functions to add data sources ===
+
To add data sources:
+
 
+
* for <tt>scalars</tt>, <tt>dimensionedScalars</tt>, <tt>scalarFields</tt>, <tt>GeometricScalarFields</tt>, etc.:
+
    eqns.scalarSources().addSource(''scalarObject'');
+
:or if it doesn't have its own name (i.e. <tt>scalars</tt> and <tt>scalarFields</tt>) or you want to assign it a different name:
+
    eqns.scalarSources().addData(''scalarObject'', ''name'');
+
* for <tt>vectors</tt>, <tt>dimensionedVectors</tt>, <tt>vectorFields</tt>, <tt>GeometricVectorFields</tt>, etc.:
+
    eqns.vectorSources().addSource(''vectorObject'');
+
:or if it doesn't have its own name (i.e. <tt>scalars</tt> and <tt>scalarFields</tt>) or you want to assign it a different name:
+
    eqns.vectorSources().addSource(''vectorObject'', ''name'');
+
* and so on for other Types (<tt>tensor</tt>, <tt>diagTensor</tt>, <tt>symmTensor</tt>, and <tt>sphericalTensor</tt>);
+
* for <tt>dictionaries</tt> or <tt>activeVariables</tt>:
+
    eqns.addSource(''dataObject'');
+
 
+
== Reading in the equations ==
+
To read equations from a dictionary use:
+
eqns.readEquation(''dictionaryName'', ''equationName'');
+
 
+
== Searching the equations ==
+
'''equationReader''' allows you to search its equations.  Similar to the <tt>dictionary</tt> object, this will return <tt>true</tt> if <tt>''equationName''</tt> exists:
+
eqns.found(''equationName'');
+
The ''evaluate'' functions below call for <tt>''eqnNameOrIndex''</tt>.  This means you can either use a <tt>word</tt> (the <tt>equationName</tt>), or a <tt>label</tt> (the <tt>equationIndex</tt>).  The <tt>equationIndex</tt> is faster, as '''equationReader''' doesn't have to perform its own lookup.  '''''Never assume the <tt>equationIndex</tt> is equal to the order in which the equations were read.'''''  If the equations depend on one another, they may not always be in the same index.  To learn the <tt>equationIndex</tt>, use:
+
equationIndex = eqns.lookup(''equationName'');
+
 
+
== Evaluating equations ==
+
Once you are done adding data sources, and reading equations, you can start evaluating equations.
+
 
+
=== All data sources required ===
+
When evaluating an equation, '''equationReader''' needs access to all the possible variables and other equations that equation might depend on.  If that variable or equation isn't found, '''equationReader''' produces a '''FatalError'''.  '''''Therefore it is a mistake to try adding more data sources after the first evaluation.'''''
+
 
+
=== No mesh available ===
+
'''equationReader''' doesn't care about the mesh... all it cares about are the sizes of the the fields.  '''''The size of the variable fields must match.'''''  Index checking is expensive, so it is only available in <tt>FULLDEBUG</tt> mode.  These rules apply:
+
 
+
* a single-element variable (e.g. a <tt>scalar</tt>, or a <tt>dimensionedVector</tt>) is assumed ''uniform throughout the entire domain'', and can be used in any equation;
+
* a field variable (e.g. a <tt>scalarField</tt>, or a <tt>DimensionedVectorField</tt>) does not have a boundary field, therefore it is only available to equations of other fields or internal fields.  Attempting to use it in a <tt>GeometricField</tt> is a mistake; and
+
* a <tt>GeometricField</tt> variable can be used with any equation.
+
 
+
There are two indices to indicate field / boundary field position:
+
 
+
* <tt>cellIndex</tt> - this is the position within a field (e.g. cell number in the internal field, or face number on a boundary patch);
+
* <tt>geoIndex</tt>:
+
** 0 = the internal field;
+
** greater than 0 = the boundary patches.  The <tt>geoIndex</tt> is therefore 1-indexed on the boundaryField: <tt>patchI = geoIndex - 1</tt>.
+
 
+
If you omit either of these in the evaluation equations, they are assumed equal to zero.
+
 
+
=== Evaluation functions ===
+
* for single element types:
+
    scalarA = eqns.evaluateScalar
+
    (
+
        ''eqnNameOrIndex'',
+
        ''[cellIndex]'',
+
        ''[geoIndex]''
+
    );
+
    vectorA.x() = eqns.evaluateScalar
+
    (
+
        ''xEqnNameOrIndex'',
+
        ''[cellIndex]'',
+
        ''[geoIndex]''
+
    ); // and so on for all its components
+
    tensorA.xx() = eqns.evaluateScalar
+
    (
+
        ''xxEqnNameOrIndex'',
+
        ''[cellIndex]'',
+
        ''[geoIndex]''
+
    ); // and so on for all its components
+
* for <tt>dimensionedScalars</tt>:
+
    dimensionedScalarA = eqns.evaluateDimensioned
+
    (
+
        ''eqnNameOrIndex'',
+
        ''[cellIndex]'',
+
        ''[geoIndex]''
+
    );
+
* for other <tt>dimensionedTypes</tt> - there is no elegant dimensionChecking... use this hack:
+
    vectorA.x() = eqns.evaluateScalar
+
    (
+
        ''xEqnNameOrIndex'',
+
        ''[cellIndex]'',
+
        ''[geoIndex]''
+
    );
+
    vectorA.y() = eqns.evaluateScalar
+
    (
+
        ''yEqnNameOrIndex'',
+
        ''[cellIndex]'',
+
        ''[geoIndex]''
+
    );
+
    vectorA.z() = eqns.evaluateScalar
+
    (
+
        ''zEqnNameOrIndex'',
+
        ''[cellIndex]'',
+
        ''[geoIndex]''
+
    );
+
    vectorA.dimensions() = eqns.evaluateDimensions(''xEqnNameOrIndex'');
+
    vectorA.dimensions() = eqns.evaluateDimensions(''yEqnNameOrIndex'');
+
    vectorA.dimensions() = eqns.evaluateDimensions(''zEqnNameOrIndex'');
+
* for <tt>scalarFields</tt>:
+
    eqns.evaluateScalarField(''resultScalarField'', ''eqnNameOrIndex'', ''[geoIndex]'');
+
:or
+
    eqns.evaluateTypeField
+
    (
+
        ''resultScalarField'',
+
        ''dummyWord'',
+
        ''eqnNameOrIndex'',
+
        ''[geoIndex]''
+
    );
+
* for <tt>vectorFields</tt>:
+
    eqns.evaluateTypeField
+
    (
+
        ''resultVectorField'',
+
        "x", // this is the component name
+
        ''xEqnNameOrIndex'',
+
        ''[geoIndex]''
+
    ); // and so on for the "y" and "z" components
+
* and so on for other <tt>typeFields</tt>;
+
* for <tt>DimensionedScalarFields</tt>:
+
    eqns.evaluateDimensionedScalarField
+
    (
+
        ''resultDimensionedScalarField'',
+
        ''eqnNameOrIndex'',
+
        ''[geoIndex]''
+
    );
+
:do not use <tt>evaluateDimensionedTypeField</tt> - this will fail for scalars;
+
*for <tt>DimensionedVectorFields</tt>:
+
    eqns.evaluateDimensionedTypeField
+
    (
+
        ''resultDimensionedVectorField'',
+
        ''xEqnNameOrIndex'',
+
        "x",
+
        ''[geoIndex]''
+
    ); // and so on for the "y" and "z" components
+
* and so on for other <tt>DimensionedTypeFields</tt>;
+
* for <tt>GeometricScalarFields</tt>
+
    eqns.evaluateGeometricScalarField
+
    (
+
        ''resultGeometricScalarField'',
+
        ''eqnNameOrIndex''
+
    );
+
:do not use <tt>evaluateGeometricTypeField</tt> - this will fail for scalars;
+
* for <tt>GeometricVectorFields</tt>
+
    eqns.evaluateGeometricTypeField
+
    (
+
        ''resultGeometricTypeField'',
+
        "x",
+
        ''xEqnNameOrIndex''
+
    ); // and so on for the "y" and "z" components
+
* and so on for other <tt>GeometricTypeFields</tt>;
+

Latest revision as of 21:42, 6 September 2013

This project has migrated over to github.

Click here for the new website.

http://github.com/Marupio/equationReader/wiki