[PREV]
[UP]
[NEXT]
[TOP]
[HOME]
C++ language use in plugins
C++ is a complex programming language - fortunately only a very small subset is required to construct even the most sophisticated plugin. The plugin is in fact a C++ function that is called by ViewGen; the vertex, connection and cell information is passed into the plugin function. ViewGen automatically adds the function call information to the plugin code: the user does not have to be concerned about the semantics of argument passing.
The following sections describe systematically the functionality of C++ that will most commonly be required in plugins.
The semi-colon
All declarations and statements in C++ must be terminated by a semi-colon `;'. The most likely reason for a plugin to fail to compile is that a semi-colon has been omitted. The compiler may issue many lines of errors because of this simple mistake!
Constants and temporary variables
Any constants or temporary variables used in a plugin should be declared as double precision floating point numbers. The easiest way of declaring constants is to use a single line, e.g.
double a = 0.005882;
but the same result could be obtained on two lines, e.g.
double a;
a = 0.005882;
It follows, therefore that 'a' does not have to be a constant, but can be a temporary variable. For instance, the code below sets two temporary variables as double precision numbers which are then calculated and used later in the code:-
double term1;
double term2;
term1 = 0.4 - 4.0*v.sgr;
term2 = pow(1 - v.sgr , 5.0);
v.perm = pow(10.0, term1 - 0.25*term2);
Once they have been calculated on the third and fourth lines, term1 and term2 are treated in exactly the same way as any other variable (e.g. v.sgr).
The `dir' symbol
The connection property c.dir differs from all other cell or fault properties in that it is a symbolic constant rather than a double precision number. It can have one of two values:-
'DIR_X' for a connection perpendicular to X - between grid-blocks (I, J, K1) and (I+1, J, K2) or
`DIR_Y' for a connection perpendicular to Y - between grid-blocks (I, J, K1) and (I, J+1, K2).
c.dir cannot be used in calculations and the only relational operators for which it is relevant are `==' and `!='.
A condition such as:-
if (c.dir == DIR_Y) {
is perfectly acceptable and will evaluate to either true or false, but the expressions:-
if (c.dir < 0.2) {
or
v.perm = 23.0*c.dir ;
are meaningless and the compiler will issue an error.
Brackets `( )'
Brackets are needed in the following situations:-
1. For defining the order of algebraic operations in a standard manner, e.g.
v.perm = a + b * c;
is not the same as:
v.perm = (a + b) * c;
The `*' operator takes precedence unless brackets are used.
2. In functions called from the Math library, e.g.
v.thick = a * pow(v.displ, b);
the brackets contain the arguments sent to the `pow' function.
3. To specify a relational operator, e.g.
if (a == b) {
A symmetrical set of brackets that open and close each other in a logical fashion must be used at all times.
Braces { }
Braces are used in conjunction with relational operators.
An opening brace is needed immediately after a conditional clause and a closing brace is needed to end the operation to be performed subject to this condition. Two pairs of braces were therefore used in the example given of the thickness plugin (one for the `if' and one for the `else' conditions).
If a pair of braces is not included in a conditional statement, C++ assumes that the condition lasts only for the next statement. Hence the code:-
if (a < 23.0)
b = 45.0;
c = 15.0;
would mean that b would be set to 45 only if a is less than 23, but c would be set to 15 whatever the value of a.
The correct way of writing this code is using braces:-
if (a < 23.0) {
b = 45.0;
c = 15.0;
}
Comments
Comments can be incorporated into the plugin code - any text on a line after the `//' symbol is considered a comment and is ignored by ViewGen and the C++ compiler, e.g.
// a and b are used later
double a = 0.005882; // 1/170 = 0.005882
double b = 1.0;
v.thick = pow(a, b); // v means the vertex
As far as the compiler is concerned, this is exactly the same as
double a = 0.005882;
double b = 1.0;
v.thick = pow(a, b);
Operators and Libraries
Mathematical operators
The mathematical operators are fairly obvious:-

The Math libraries
The pow function used in the example is drawn from the C++ Math library. The so-called prototype of the `pow' function in the library is:-
double pow(double base, double exponent);
The `double' before the `pow' indicates the function returns a double precision value, and the function takes two arguments, both double precision. If the function is called with constants as arguments they are automatically converted to doubles, e.g.
v.thick = pow(0.005882, 1.0);
The prototypes for all (potentially) useful math library functions are:-

Relational operators
C++ has a rich set of relational operators that are used to compare two values against each other. For instance, the `<' operator evaluates to true if the value to the left of the operator is less than the value to the right and false if not. Relational operators are typically used with `if' statements so the plugin author can determine what action to take based on a certain condition being true or false. For example, the following code calculating fault permeability as the harmonic average of the cell permeabilites if CSP is below a defined sealing threshold. Otherwise it sets fault permeability to zero.
double csp_cutoff = 5.0;
double perm1;
double perm2;
if (c.dir == DIR_X) {
perm1 = up.permx;
perm2 = down.permx;
}
else {
perm1 = up.permy;
perm2 = down.permy;
}
if (v.csp_measure < csp_cutoff)
{
v.perm = 1 / (0.5 / perm1 + 0.5 / perm2 );
}
else
{
v.perm = 0.0;
}
The terms inside the parenthesis i.e. `c.dir == DIR_X' and `v.csp_measure < csp_cutoff' evaluate to either true or false. If the condition is true the first clauses of the `if' statements are executed; if the condition is false the clauses following the `else' are executed.
The full set of relational operators are:-

NOTE:- x = y is not a relational operator but an assignment. If the following code is included in a plugin:-
if (v.fsp1 = -1.0) {
v.perm = 0.0 ;
}
else {
// more code here
}
the assignment (v.fsp1 = -1.0) will be made and the condition will then be evaluated as true. Hence v.perm will be set to 0.0 whatever the starting value of v.fsp1. The result of this bit of code, therefore, will be to overwrite the fsp1 values at every vertex in a model with undefined value (-1.0) and to set the permeability of every vertex in the model to be 0.0. The plugin will never call the bit of code written after the `else' statement.
This is unlikely to be what was intended and the first line of code should have been:-
if (v.fsp1 == -1.0) {
In this case, the permeability of vertices of connections undefined in fsp1 is set to 0.0, and all defined connections are dealt with in the code following the else statement.
Relational expressions (such as `a < b') may be grouped together logically within parentheses to test more than one condition at once. If expr1 and expr2 are two relational expressions:-
if (expr1 && expr2) {
// do this
} else {
// do that
}
means that both expr1 and expr2 must be true for the first statement (`do this') to be executed. The symbol `&&' is called the AND operator. Alternatively:-
if (expr1 || expr2) {
// do this
}
else {
// do that
}
means that if either expr1 or expr2 is true the first statement is executed. The symbol `||' is called the OR operator.
An example of using OR in a permeability plugin that uses CSP might be:-
if (v.csp > cutoff || v.csp == UNDEFINED_VALUE) {
v.perm = 0.0;
}
else {
// set permeability in some other way
}
NOTE:- The symbol `UNDEFINED_VALUE' takes the value -1.0; we have introduced it for use in plugins to make them easier to read.
Multiple conditional statements
The `if' statement can have one, two or many clauses. A clause can be one or more statements (a statement is defined by a line of code that is terminated by a semi-colon). If a clause consists of more than one statement the clause must be enclosed in braces `{ }'. To help reduce any compilation errors, it is suggested braces are always used to enclose the clauses in an `if' statement, even if the clause only contains one statement. For instance:-
if (up.ntg < 0.4)
{
up.my_property1 = 1.0;
up.my_property2 = 0.0;
}
else if (up.ntg < 0.7)
{
up.my_property1 = 0.5;
up.my_property2 = 0.5;
}
else
{
up.my_property1 = 0.0;
up.my_property2 = 1.0;
}
There can be many `else if' conditions between the first `if' and the final `else'. Indeed, there does not have to be a final `else' here. The braces group together the statements within a clause and make the plugin easier to read.
[PREV]
[UP]
[NEXT]
[TOP]
[HOME]