0% found this document useful (0 votes)
29 views94 pages

Fish Reference

Uploaded by

Guido Andreotti
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views94 pages

Fish Reference

Uploaded by

Guido Andreotti
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 94

FISH REFERENCE 2-1

2 FISH REFERENCE

2.1 Introduction and Overview

This section contains a detailed reference to the FISH language. Following the introduction, Sec-
tion 2.2 describes the rules of the language, and how variables and functions are used. Section 2.3
explains FISH statements, and Section 2.4 describes how the FISH language links with FLAC.
Predefined FISH variables, functions and arrays are described in Section 2.5.
FISH is a programming language embedded within FLAC that enables the user to define new
variables and functions. These functions may be used to extend FLAC ’s usefulness or add user-
defined features. For example, new variables may be plotted or printed, special grid generators
may be implemented, servo-control may be applied to a numerical test, unusual distributions of
properties may be specified, and parameter studies may be automated.
FISH is a “compiler” (rather than an “interpreter”). Programs entered via a FLAC data file are
translated into a list of instructions (in “pseudo-code”) stored in FLAC ’s memory space; the original
source program is not retained by FLAC. Whenever a FISH function is invoked, its compiled pseudo-
code is executed. The use of compiled code (rather than interpreted source code) enables programs
to run much faster. However, unlike a compiler, variable names and values are available for printing
at any time; values may be modified by the user by using FLAC ’s SET command.
FISH programs are simply embedded in a normal FLAC data file: lines following the word DEFINE
are processed as a FISH function; the function terminates when the word END is encountered.
Functions may invoke other functions, which may invoke others, and so on. The order in which
functions are defined does not matter as long as they are all defined before they are used (e.g.,
invoked by a FLAC command). Since the compiled form of a FISH function is stored in FLAC ’s
memory space, the SAVE command saves the function and the current values of associated variables.
Section 2.6 discusses extensions to FISH for file manipulation, and Section 2.7 describes the use
of socket communication to transfer data between FLAC and another Itasca code. The use of these
functions requires a reasonable understanding of programming techniques and constructs; FISH
can be used without reference to these extensions.
FISH can also be used to implement user-written constitutive models; the procedure is described in
Section 2.8. Finally, in Section 2.9, an execution-speed optimizer which can be applied to certain
FISH functions is discussed.

FLAC Version 8.0


2-2 FISH in FLAC

2.2 FISH Language Rules, Variables and Functions

2.2.1 Lines

FISH programs can be embedded in a normal FLAC data file or may be entered directly from the
keyboard. Lines following the word DEFINE are taken to be statements of a FISH function; the
function terminates when the word END is encountered. A valid line of FISH code must take one
of the following forms.
1. The line starts with a statement such as IF, LOOP, etc. (see Section 2.3).
2. The line contains one or more names of user-defined FISH functions, separated
by spaces – e.g.,
fun 1 fun 2 fun 3
where the names correspond to functions written by the user; these functions
are executed in order. The functions need not be defined prior to their reference
on a line of FISH code (i.e., forward references are allowed).
3. The line consists of an assignment statement (i.e., the expression on the right
of the = sign is evaluated, and the value is given to the variable or function
name on the left of the = sign).
4. The line consists of a FLAC command, provided that the line is embedded in a
section of FISH code delimited by the COMMAND – ENDCOMMAND statements
(see Section 2.3.3).
5. The line is blank or starts with a semicolon.
FISH variables, function names and statements must be spelled out in full; they cannot be truncated,
as in FLAC commands. No continuation lines are allowed; intermediate variables may be used to
split complex expressions. FISH is “case-insensitive” by default (i.e., it makes no distinction
between uppercase and lowercase letters); all names are converted to lowercase letters. Spaces
are significant (unlike in FORTRAN) and serve to separate variables, keywords, and so on; no
embedded blanks are allowed in variable or function names. Extra spaces may be used to improve
readability (for example, by indenting loops and conditional clauses). Any characters following a
semicolon ( ; ) are ignored; comments may be embedded in a FISH program by preceding them
with a semicolon. Blank lines may be embedded in a FISH program.

FLAC Version 8.0


FISH REFERENCE 2-3

2.2.2 Names for Functions and Variables; Potential Conflicts

Variable or function names must start with a non-number, and must not contain any of the following
symbols.
. , * / + - ˆ = < > # ( ) [ ] @ ; ’ "
User-defined names can be any length, but they are truncated in printout and in plot captions, due to
line-length limitations. In general, names may be chosen arbitrarily, although they must not be the
same as a FISH statement (see Section 2.3) or a predefined variable or function (see Section 2.5).
There are also many other words used in FLAC input that should be avoided. The list contained
in Table 2.1 shows all words that could give rise to a conflict if used to name a FISH variable or
function. However, the potential conflict depends on the way in which the chosen name is used.
For example, the word gravity could be used as a FISH variable, provided that it is simply referred
to inside a FISH function; a conflict would arise only if it is necessary to use the SET command to
set its value, since gravity is a valid argument to the SET command. Similarly, it may be impossible
to print the value of a FISH variable if its name is the same as a parameter for the PRINT command.
The list of property names for built-in models (see PROPERTY command in Section 1.2 in the
Command Reference) should also be consulted before choosing property names for a user-written
constitutive model (see Section 2.8.4). If in doubt, avoid any of the names listed in Table 2.1 or for
the PROPERTY command, or contractions of the names (since FLAC allows truncation of keywords
and commands).

FLAC Version 8.0


2-4 FISH in FLAC

Table 2.1 List of words in FLAC and FISH that may conflict with chosen names
a3 char dytime free jzones output
a4 clock ep friend large p stress
abs close echo fsi legend pac
acos cm max ega fsr lff pnt palette
and columns elastic fstring limits parse
angle command else ftens list pause
anisotropic config end g2flow lmul pfast
app pnt constitutive model end case gen ln pi
appgw pnt constitutivemodel end command get mem log plot
apply cos end if gflow loop pltangle
appth pnt cparse end loop gmsmul lose mem pltcohesion
area crdt end section gp copy mark pltfriction
array creep endcase gpp mat inverse plttension
asin crtdel endcommand grand mat transpose poro2
aspect crtime endif grid max power
asxx csc endloop gwdt maxdt pp
asxy csxx endsection gwtdel mechanical pre parse
asyy csxy error gwtime mem preparse
aszz csyy ev p hbm memory print
atan cszz ev tot hbs message prop
atan2 cycle ex 1, ex 2, etc. help min pslow
att pnt damp exit his mindt quit
attach damping exp hisfile mode r
back datum f prop ieb model r integrate
baud define f2mod ieb pnt mohr-coulomb range
bicoe degrad fc arg ierr monchrome rayleigh
bsxx density filcolor if movie read
bsxy disp fish iface ncontours reset
bsyy do update fish msg igp ncwrite restore
bszz dsxx fishcall imem nerr return
call dsxy fix implicit nerr fish rez exe
case dsyy flags in new rff pnt
case of dszz float information ngrwater rsat
caseof dt flow inimodel nmechanical s 3dd
cf axi dump flprop initial not s dyn
cf creep dy fmem int nstep s echo
cf dyn dy state fmod int pnt nthermal s flow
cf ext dydt fobl interface null s imp
cf gw dydt gpi fobu itasca nwgpp s log
cf ps dydt gpj force izones open s mech
cf therm dynamic fos jerr or s mess
cga dytdel fos f jgp out s movie

FLAC Version 8.0


FISH REFERENCE 2-5

Table 2.1 List of words in FLAC and FISH that may conflict with chosen names (cont.)
s tens tflow wdens zde11
s therm thdt while zde12
sat then while stepping zde22
save thermal whilestepping zde33
sclin theta window zdpp
sclose thtdel wipp zdrot
section thtime wk11 zmsmul
set title wk12 zporos
sgn tolerance wk22 zsub
sig1 trac pnt write zs11
sig2 track x zs12
sin type xacc zs22
sm max ubiquitous xbody zs33
small ucs xcen ztea
solve udcoe xdisp zteb
sopen udm pnt xflow ztec
sqrt umul xforce zted
sread unbal xform ztsa
ss unbflow xgrav ztsb
ssi unmark xnwflow ztsc
ssi3d urand xreaction ztsd
ssr v ngw xtable zvisc
ssr3d v nmech xvel zxbar
state v ntherm xywrite
step vector y
stop vga yacc
str pnt vgp0 ybody
string vgpcnw ycen
structure vgpcw ydisp
swrite viscous yflow
sxx visrat yforce
sxy vol strain ygrav
sys vs ynwflow
syy vsi yreaction
szz vsr ytable
tab pnt vsxx yvel
table vsxz z copy
table size vsyy z group
tan vszz z hyst
temperature water z model
tenflg wbiot z prop
tension wbulk zart

FLAC Version 8.0


2-6 FISH in FLAC

By default, user-defined variables represent single numbers or strings. Multi-dimensional arrays


of numbers or strings may be stored if the ARRAY statement is used. Section 2.3.1 defines the way
arrays are created and used. At present, there is no explicit printout or input facility for arrays, but
functions may be written in FISH to perform these operations. For example, the contents of a two
dimensional array (or matrix) may be initialized and printed, as shown in Example 2.1:

Example 2.1 Initializing and printing FISH arrays


def afill ; fill matrix with random numbers
array var(4,3)
loop m (1,4)
loop n (1,3)
var(m,n) = urand
end_loop
end_loop
end
def ashow ; display contents of matrix
loop m (1,4)
hed = ’ ’
msg = ’ ’+string(m)
loop n (1,3)
hed = hed + ’ ’+string(n)
msg = msg + ’ ’+string(var(m,n))
end_loop
if m = 1
dum = out(hed)
end_if
dum = out(msg)
end_loop
end
afill
ashow

Upon execution, the following output is produced.


1 2 3
1 5.7713E-001 6.2307E-001 7.6974E-001
2 8.3807E-001 3.3640E-001 8.5697E-001
3 6.3214E-001 5.4165E-002 1.8227E-001
4 8.5974E-001 9.2797E-001 9.6332E-001

FLAC Version 8.0


FISH REFERENCE 2-7

2.2.3 Scope of Variables

Variable and function names are recognized globally (as in the BASIC language), except for property
variables associated with user-defined constitutive models (see Section 2.8.4). As soon as a name
is mentioned in a valid FISH program line, it is thereafter recognized globally, both in FISH code
and in FLAC commands (for example, in place of a number); it also appears in the list of variables
displayed when the PRINT fish command is given. A variable may be given a value in one FISH
function and used in another function or in a FLAC command. The value is retained until it is
changed. The values of all variables are also saved by the SAVE command and restored by the
RESTORE command.

2.2.4 Functions: Structure, Evaluation and Calling Scheme

The only object in the FISH language that can be executed is the “function.” Functions have no
arguments; communication of parameters is through the setting of variables prior to invoking the
function. (Recall that variables have global scope.) The name of a function follows the DEFINE
statement, and its scope terminates with the END statement. The END statement also serves to return
control to the caller when the function is executed. (Note that the EXIT statement also returns control
– see Section 2.3.2.) Consider Example 2.2, which shows function construction and use.

Example 2.2 Construction of a function


new
def xxx
aa = 2 * 3
xxx = aa + bb
end

The value of xxx is changed when the function is executed. The variable aa is computed locally,
but the existing value of bb is used in the computation of xxx. If values are not explicitly given to
variables, they default to zero (integer). It is not necessary for a function to assign a value to the
variable corresponding to its name. The function xxx may be invoked in one of several ways:
(1) as a single word xxx on a FISH input line;
(2) as the variable xxx in a FISH formula – e.g.,
new var = (sqrt(xxx)/5.6)ˆ4;

(3) as a single word xxx on a FLAC input line;


(4) as a symbolic replacement for a number on an input line (see Section 2.4.1);
and
(5) as a parameter to the SET, PRINT or HISTORY command in FLAC.

FLAC Version 8.0


2-8 FISH in FLAC

A function may be referred to in another function before it is defined; the FISH compiler simply
creates a symbol at the time of first mention, and then links all references to the function when it is
defined by a DEFINE command. A function can be deleted or redefined.
Function calls may be nested to any level (i.e., functions may refer to other functions, which may
refer to others, ad infinitum). However, recursive function calls are not allowed (i.e., execution of a
function must not invoke that same function). Example 2.3 shows a recursive function call, which
is not allowed, because the name of the defining function is used in such a way that the function
will try to call itself. The example will produce an error on execution.

Example 2.3 A recursive function call


new
def stress_sum
stress_sum = 0.0
loop i (1,izones)
stress_sum = stress_sum + sxx(i,1)
end_loop
end

The same function should be coded as shown in Example 2.4:

Example 2.4 Removing recursion from the function shown in Example 2.3
new
def stress_sum
sum = 0.0
loop i (1,izones)
sum = sum + sxx(i,1)
end_loop
stress_sum = sum
end

The difference between variables and functions is that a function is always executed whenever
its name is mentioned; a variable simply conveys its current value. However, the execution of a
function may cause other variables (as opposed to functions) to be evaluated. This effect is useful,
for example, when several histories of FISH variables are required – only one function is necessary
in order to evaluate several quantities, as in Example 2.5.

FLAC Version 8.0


FISH REFERENCE 2-9

Example 2.5 Evaluation of variables


new
def h_var_1
h_var_1 = sxx(3,4) + fac
h_var_2 = syy(3,4) + fac
h_var_3 = sxy(3,4) + fac
end

The FLAC commands to request histories might be


hist h var 1
hist h var 2
hist h var 3

The function h var 1 would be executed by FLAC ’s history logic every few steps but, as a side
effect, the values of h var 2 and h var 3 would also be computed and used as history variables.

2.2.5 Data Types

There are three data types used for FISH variables or function values:
1. Integer (exact numbers in the range −2,147,483,648 to +2,147,483,647);
2. Floating-Point (approximate numbers with about six decimal digits of precision, with
a range of approximately ±10−308 to ±10308 ); and
3. String (packed sequence of any printable characters; the sequence may be any length,
but it will be truncated on the printout. Strings are denoted in FISH and FLAC by a
sequence of characters enclosed by single quotes – e.g., ‘Have a nice day’ – note
that the use of strings in FLAC is restricted to titles and file names. See Section 2.4.1.)
A variable in FISH can change its type dynamically, depending on the type of the expression to
which it is set. To make this clear, consider the assignment statement
var1 = var2

If var1 and var2 are of different types, then two things are done: first, var1’s type is converted to
var2’s type; second, var2’s data are transferred to var1. In other languages, such as FORTRAN
or C, the type of var1 is not changed, although data conversion is done. By default, all variables
in FISH start their life as integers; however, a statement such as
var1 = 3.4

causes var1 to become a floating-point variable when it is executed. The current type of all
variables may be determined by giving the FLAC command PRINT fish – the types will be denoted
in the printout.

FLAC Version 8.0


2 - 10 FISH in FLAC

The dynamic typing mechanism in FISH was devised to make programming easier for non-
programmers. In languages such as BASIC, numbers are stored in floating-point format, which can
cause difficulties when integers are needed for, say, loop counters. In FISH, the type of the variable
adjusts naturally to the context in which it is used. For example, in the code fragment
n = n + 2
xx = xx + 3.5

the variable n will be an integer and will be incremented by exactly 2, and the variable xx will
be a floating-point number, subject to the usual truncation error but capable of handling a much
bigger dynamic range. The rules governing type conversion in arithmetic operations are explained
in Section 2.2.6. The type of a variable is determined by the type of the object on the right-hand
side of an assignment statement; this applies both to FISH statements and to assignments done with
the FLAC SET command. Both types of assignment may be used to change the type of a variable
according to the value specified, as follows.
1. An integer assignment (digits 0-9 only) will cause the variable to become an
integer (e.g., var1 = 334).
2. If the assigned number has a decimal point or an exponent denoted by “e”
or “E,” then the variable will become a floating-point number (e.g., var1 =
3e5; var2 = -1.2).
3. If the assignment is delimited by single quotes, the variable becomes a string,
with the “value” taken to be the list of characters inside the quotes (e.g., var1
= ‘Have a nice day’).
Type conversion is also done in assignments involving predefined variables or functions; these rules
are presented in Section 2.5.
A variable’s type can be preassigned during the compilation phase if required: the FISH statements
INT, FLOAT and STRING cause the associated variable to be initialized to the given type. This is
discussed in Section 2.3.1. Normally, it is unnecessary to do preassignment, except for variables
used in constitutive models that will be optimized (see Sections 2.8 and 2.9).

2.2.6 Arithmetic: Expressions and Type Conversions

Arithmetic follows the conventions used in most languages. The symbols


ˆ / * - +
denote exponentiation, division, multiplication, subtraction and addition, respectively, and are ap-
plied in the order of precedence given. Arbitrary numbers of parentheses may be used to render
explicit the order of evaluation; expressions within parentheses are evaluated before anything else
(inner parentheses are evaluated first). As an example, FISH evaluates the following variable xx
as 133:
xx = 6/3*4ˆ3+5

FLAC Version 8.0


FISH REFERENCE 2 - 11

The expression is equivalent to


xx = ( (6/3) * (4ˆ3) ) + 5

If there is any doubt about the order in which arithmetic operators are applied, then parentheses
should be used for clarification.
If either of the two arguments in an arithmetic operation is of floating-point type, then the result
will be floating-point. If both of the arguments are integers, then the result will be integer. It is
important to note that the division of one integer by another causes truncation of the result (for
example, 5/2 produces the result 2, and 5/6 produces the result 0).

2.2.7 Strings

There are three main FISH intrinsic functions that are available to manipulate strings:
in(var) prints out variable var if it is a string, or the message “Input?” if
it is not, and then waits for input from the keyboard. (The returned
value depends on the characters that are typed. FISH tries to decode
the input first as an integer and then as a floating-point number; the
returned value will be of type int or float if a single number that can
be decoded as integer or floating-point, respectively, has been typed
in. The number should be the only thing on the line. However, if it is
followed by a space, comma or parenthesis, then any other characters
on the line are ignored. If the characters typed in by the user cannot be
interpreted as a single number, then the returned value will be a string
containing the sequence of characters. The user’s FISH function can
determine what has been returned by using the function type( ).)
out(s) prints out the message contained in s to the screen (and to the log file,
if it is open). The variable s must be of type string. The returned
value of the function is zero if no error is detected, and 1 if there is
an error in the argument (e.g., if s is not a string).
string(var) converts var to type string. If var is already of type string, then the
function simply returns var as its value. If var is int or float, then a
character string that corresponds to the number as it would be printed
out will be returned. However, no blanks are included in the string.
One use of these functions is to control interactive input and output. Example 2.6 demonstrates
this for user-supplied input parameters for Young’s modulus and Poisson’s ratio.

FLAC Version 8.0


2 - 12 FISH in FLAC

Example 2.6 Control of interactive input


def in_def
xx = in(msg+’(’+’default:’+string(default)+’):’)
if type(xx) = 3
in_def = default
else
in_def = xx
end_if
end
def moduli_data
default = 1.0e9
msg=’Input Young‘s modulus ’
y_mod = in_def
;
default = 0.25
msg=’Input Poisson‘s ratio ’
p_ratio = in_def
if p_ratio = 0.5 then
ii = out(’ Bulk mod is undefined at Poisson’s ratio = 0.5’)
ii = out(’ Select a different value --’)
p_ratio = in_def
end_if
;
s_mod = y_mod / (2.0 * (1.0 + p_ratio))
b_mod = y_mod / (3.0 * (1.0 - 2.0 * p_ratio))
end
moduli_data
;
grid 10,10
model elastic
prop bulk = b_mod shear = s_mod
print p_ratio y_mod b_mod s_mod
pause
print bulk
pause
print shear

The only arithmetic operation that is valid for string variables is addition; as demonstrated in
Example 2.6, this causes two strings to be concatenated.
It is invalid for only one argument in an arithmetic operation to be a string variable. The intrinsic
function string( ) must be used if a number is to be included as part of a string variable (see variable
xx in Example 2.6). Also, note the use of intrinsic function type( ), which identifies the type of

FLAC Version 8.0


FISH REFERENCE 2 - 13

argument (see Section 2.5.5). Further string manipulation may be performed with the intrinsic
functions parse, pre parse and cparse, as described in Section 2.6.

2.2.8 Deleting and Redefining FISH Functions

A FISH function can be deleted or redefined. If the same name as an existing function is given on a
DEFINE line, the code corresponding to the old function is first deleted (and a warning printed), and
the new code substituted. If an END immediately follows the DEFINE line, then no new function
is created (i.e., the old function is just deleted). Such a “null” function is also assumed to be
nonexistent, even if some declarative statements come between the DEFINE and END (e.g., float,
int, etc.). A few notes of caution:
1. A constitutive model function cannot be deleted or redefined (since existing
grid variables would be left as orphans).
2. The variables that are used in a function still exist even if the function is deleted;
only the code is deleted. Since variables are global, it is likely that they are
used elsewhere. The name of a deleted function will still exist as a variable.
3. If a function is replaced by another of the same name, all calls to the old function
will be replaced automatically by calls to the new one, as demonstrated in
Example 2.7:

Example 2.7 Replacing FISH functions with the same name


def joe
ii = out(’ a function’)
end
def fred
joe
end
fred ; ... old message will appear
def joe
ii = out(’ a new function’)
end
fred ; ... new message will appear

If joe is deleted, however, a message will be printed on execution of fred,


saying that joe is now only a variable and cannot be executed.

FLAC Version 8.0


2 - 14 FISH in FLAC

2.3 FISH Statements

There are a number of reserved words in the FISH language; they must not be used for user-
defined variable or function names. The reserved words, or statements, fall into three categories,
as explained below.

2.3.1 Specification Statements

The following words are normally placed at the beginning of a FISH function. They alter the
characteristics of the function or its variables, but do not affect the flow of control within the
function. They are only interpreted during compilation.
ARRAY var1(n1, n2 . . . ) <var2(m1, m2 . . . )> <var3(p1, p2 . . . )> . . .
This statement permits arrays of any dimension and size to be included in FISH code.
In the above specification, var1 is any valid variable name, and n1, n2 . . . are
either actual integers, or single user-defined variables (not expressions) that have
integer values at the time the ARRAY statement is processed. There may be several
arrays specified on the same line (e.g., var2, above); the number of dimensions may
be different for each array. The ARRAY statement is a specification and is acted
on during compilation, not execution (it is ignored during execution). Note the
following.
1. The given name may be an existing single variable. If so, it is converted to an
array and its value is lost. If the name does not already exist, it is created.
2. The given name may not be that of a function or the name of an existing array
(i.e., arrays cannot be redefined).
3. The given dimensions (n1, n2, . . . ) must be positive integers or evaluate to
positive integers (i.e., indices start at 1, not 0).
4. There is no limit to the number and size of the array dimensions, except memory
capacity and the maximum line length.
5. Arrays may be declared and used in optimized functions, limited as follows.
a) Only the first element of an array is checked for type; the re-
maining elements are assumed to be of the same type. It is the
user’s responsibility to ensure this; otherwise, the results will
be wrong. In particular, mixed-type arrays will fail.

FLAC Version 8.0


FISH REFERENCE 2 - 15

b) An array name may be given the type int or float prior to the
ARRAY statement, in order to initialize all elements to the given
type – e.g.,
float abc
array abc(3,3)

If not explicitly typed, the array elements will default to inte-


gers.
c) It is assumed that array indices are integers; the use of an array
with non-integer indices will cause the FISH function to fail or
give incorrect answers.
Array variables take any type (integer, float or string), according to the same rules
governing single variables. They are used exactly like single variables, except that
they are always followed by an argument (or index) list enclosed by parentheses. In
use (as opposed to in specification), array indices may be integer expressions – e.g.,
var1 = (abc(3,nn+3,max(5,6)) + qqq) / 3.4

is a valid statement if abc is the name of a three-dimensional array. Arrays may


appear on both sides of an assignment, and arrays may be used as indices of other
arrays.
Some restrictions apply to the use of array names in FLAC command lines:
(1) the command PRINT fish prints the legend – array – if the corresponding symbol
is an array;
(2) PRINT name (where name is a FISH array name) simply prints out the maximum
array indices; and
(3) the use of a FISH array name as the source or destination for a number in the
SET command is not allowed, and prompts an error message (e.g., SET gravity
= name, where name is a FISH array name).
CONSTITUTIVEMODEL <n>
If this statement appears at the beginning of a user-defined function, then the function
is taken to be a new constitutive model. It will be executed in exactly the same way as
a built-in constitutive model (i.e., called four times (once for each subzone) for each
FLAC zone at each calculation step). There are some precise rules that apply to the
structure of a constitutive function and the variables that are available at execution
time. Section 2.8 consists of a user’s guide to the writing of constitutive models.
Synonym: CONSTITUTIVE MODEL

FLAC Version 8.0


2 - 16 FISH in FLAC

INT ivar1 ivar2 ivar3 . . .


FLOAT fvar1 fvar2 fvar3 . . .
STRING svar1 svar2 svar3 . . .
These statements initialize the types of the variable(s) that follow either to integer,
floating-point or string, respectively; the variable names must be separated by spaces.
Section 2.2.5 explains the three data types supported by FISH. The action of INT,
FLOAT and STRING is to change the type of the associated variable immediately
(and to create the variable if it does not exist). Since FISH variables are global in
scope, the same variable can have its type set in several functions; in this case, the
latest declaration takes precedence. Furthermore, since a variable’s type can change
dynamically, the preset type can be overwritten during execution. The main use of
the type statements is in the optimization of constitutive model functions; otherwise,
there is no real need to use the statements.
FRIEND func1 func2 . . .
The FRIEND statement should only appear in a constitutive model function. It indi-
cates that all variables and code within the named function(s) are to be treated as if
they were embedded within the body of the constitutive function. In particular, state
variables are recognized within friend functions. See Section 2.8.7 for more details.
WHILESTEPPING
If this statement appears anywhere within a user-defined function, then the function is
always executed automatically at the start of every FLAC step. The WHILESTEPPING
attribute can later be disabled with the use of the SET fishcall 0 remove command
(see Section 2.4.4).
The fishcall (see the command SET fishcall) statement provides more flexibility and
control than the WHILESTEPPING command, and its use is preferred.
Synonym: WHILE STEPPING

FLAC Version 8.0


FISH REFERENCE 2 - 17

2.3.2 Control Statements

The following statements serve to direct the flow of control during execution of a FISH function.
Their position in the function is of critical importance, unlike the specification statements described
above.
DEFINE function-name
END The FISH program between the DEFINE and END commands is compiled and stored in
FLAC ’s memory space. The compiled version of the function is executed whenever
its name is mentioned, as explained in Section 2.2.4. The function name (which
should be chosen according to the rules in Section 2.2.2) does not need to be assigned
a value in the program section that follows.
CASEOF expr
CASE n
ENDCASE The action of these control statements is similar to the FORTRAN-computed GOTO,
or C’s SWITCH statement. It allows control to be passed rapidly to one of several
code segments, depending on the value of an index. The use of the keywords is
illustrated in Example 2.8.
Synonym: CASE OF END CASE

Example 2.8 Usage of the CASE construct


CASEOF expr
;............ default code here
CASE i1
;............ case i1 code here
CASE i2
;............ case i2 code here
CASE i3
;............ case i3 code here
ENDCASE

The object expr following CASEOF can be any valid algebraic expression; when
evaluated, it will be converted to an integer. The items i1, i2, i3, . . . must be integers
(not symbols) in the range 0 to 255. If the value of expr equals i1, then control jumps
to the statements following the CASE i1 statement; execution then continues until
the next CASE statement is encountered. Control then jumps to the code following
the ENDCASE statement; there is no “fall-through” as in the C language. Similar
jumps are executed if the value of expr equals i2, i3, and so on. If the value of
expr does not equal the numbers associated with any of the CASE statements, then
any code immediately following the CASEOF statement is executed, with a jump

FLAC Version 8.0


2 - 18 FISH in FLAC

to ENDCASE when the first CASE is encountered. If the value of expr is less than
zero or greater than the greatest number associated with any of the CASEs, then an
execution error is indicated, and processing stops. The numbers n (e.g., i1, i2, i3)
need not be sequential or contiguous, but no duplicate numbers may exist.
CASEOF . . . ENDCASE sections may be nested to any degree; there will be no conflict
between CASE numbers in the different levels of nesting (e.g., several instances of
CASE 5 may appear, provided that they are all associated with different nesting
levels). The use of CASE statements allows rapid decisions to be made (much
more quickly than for a series of IF . . . ENDIF statements). However, the penalty is
that some memory is consumed; the amount of memory depends on the maximum
numerical value associated with the CASE statements. The memory consumed is
one plus the maximum CASE number in double-words (four-byte units).
IF expr1 test expr2 THEN
ELSE
ENDIF These statements allow conditional execution of FISH code segments; ELSE is op-
tional and the word THEN may be omitted if desired. The item test consists of one
of the following symbols, or symbol pairs:
= # > < >= <=
The meanings are standard, except for #, which means “not equal.” The items expr1
and expr2 are any valid algebraic expressions (which can involve functions, FLAC
variables, etc.). If the test is true, then the statements immediately following IF are
executed until ELSE or ENDIF is encountered. If the test is false, the statements be-
tween ELSE and ENDIF are executed if the ELSE statement exists; otherwise, control
jumps to the first line after ENDIF. All the given test symbols may be applied when
expressions expr1 and expr2 evaluate to integers or floating-point values (or a mix-
ture). If both expressions evaluate to strings, then only two tests are valid: = and #;
all other operations are invalid for strings. Strings must match exactly for equality.
IF . . . ELSE . . . ENDIF clauses can be nested to any depth.
Synonym: END IF
EXIT This statement causes an unconditional jump to the end of the current function.
EXIT SECTION
This statement causes an unconditional jump to the end of a SECTION; FISH program
sections are explained below.

FLAC Version 8.0


FISH REFERENCE 2 - 19

LOOP var (expr1, expr2)


ENDLOOP or
LOOP WHILE expr1 test expr2
ENDLOOP
The FISH program lines between LOOP and ENDLOOP are executed repeatedly until
certain conditions are met. In the first form, which uses an integer counter, var is
given the value of expr1 initially, and is incremented by 1 at the end of each loop
execution until it obtains the value of expr2. Note that expr1 and expr2 (which may
be arbitrary algebraic expressions) are evaluated at the start of the loop; redefinition
of their component variables within the loop has no effect on the number of loop
executions. var is a single integer variable; it may be used in expressions within the
loop (even in functions called from within the loop), and may even be redefined.
In the second form of the LOOP structure, the loop body is executed while the
test condition is true; otherwise, control passes to the next line after the ENDLOOP
statement. The form of test is identical to that described for the IF statement. The
expressions may involve floating-point variables as well as integers; the use of strings
and pointers is also permitted under the same conditions that apply to the IF statement.
The two forms of the LOOP structure may be contrasted. In the first, the test is done
at the end of the loop (so there will be at least one pass through the loop); in the
second, the test is done at the start of the loop (so the loop will be bypassed if the
test is false initially). Loops may be nested to any depth.
Synonym: END LOOP
SECTION
ENDSECTION
The FISH language does not have a “GO TO” statement. The SECTION construct
allows control to jump forward in a controlled manner. The statements SECTION
. . . ENDSECTION may enclose any number of lines of FISH code; they do not affect
the operation in any way. However, an EXIT SECTION statement within the scope of
the section so defined will cause control to jump directly to the end of the section.
Any number of these jumps may be embedded within the section. The ENDSECTION
statement acts as a label, similar to the target of a GO TO statement in C or FOR-
TRAN. The logic is cleaner, however, because control may not pass to anywhere
outside the defined section, and flow is always “downward.” Sections may not be
nested; there may be many sections in a function, but they must not overlap or be
contained within each other.
Synonym: END SECTION

FLAC Version 8.0


2 - 20 FISH in FLAC

2.3.3 FLAC Command Execution

COMMAND
ENDCOMMAND
FLAC commands may be inserted between this pair of FISH statements; the com-
mands will be interpreted when the FISH function is executed. There are a number of
restrictions concerning the embedding of FLAC commands within a FISH function.
The NEW and RESTORE commands are not permitted to be invoked from within a
FISH function. The lines found between a COMMAND – ENDCOMMAND pair are
simply stored by FISH as a list of symbols; they are not checked at all, and the
function must be executed before any errors can be detected.
A FISH function may appear within a COMMAND – ENDCOMMAND pair, and may
not contain the COMMAND – ENDCOMMAND statements. A function that contains
the WHILESTEPPING statement, or a function that is the subject of a fishcall, may not
contain the COMMAND statement.
Comment lines (starting with ;) are taken as FLAC comments, rather than FISH
comments; it may be useful to embed an explanatory message within a function, to
be printed out when the function is invoked. If the echo mode is off (SET echo = off),
then any FLAC commands coming from the function are not displayed to the screen
or recorded to the log file.
Synonym: END COMMAND

FLAC Version 8.0


FISH REFERENCE 2 - 21

2.4 Linkages to FLAC

2.4.1 Modified FLAC Commands

The following list contains all of the FLAC commands that refer directly to FISH variables or entities.
There are many other ways FLAC and FISH may interact; these are described in Section 2.4.2.
CONFIG extra n
The extra keyword, given in the CONFIG command, causes space for extra grid
variables to be allocated; the value n specifies the number of extra variables. Such
variables may be used as “scratch-pad” space by a FISH function, or may be used
to store some grid-related quantities that are later printed or plotted. The extra grid
arrays are referred to in a FISH function as ex 1(i,j) . . . ex n(i,j), where
n is the number given in the CONFIG command. The extra grid variables are always
of the floating-point type.
HISTORY var
causes a history of the FISH variable or function to be taken during stepping. If var
is a function, then it will be evaluated every time histories are stored (controlled by
HISTORY nstep command); it is not necessary to register the function with a fishcall.
If var is a FISH variable, then its current value will be taken. Hence, caution should
be exercised when using variables (rather than functions) for histories. var may also
be a material property name; either of a built-in model or a user-defined model. In
both cases, the property name must be given in full, followed by the zone indices
(i, j). The history may be plotted in the usual way.
HISTORY ex n (i,j)
causes a history of the extra grid variable ex n (i, j) to be taken during stepping. n is
the numerical identifier for the extra grid variable, and i, j correspond to grid indices.
INITIAL ex n value
initializes the values of the extra grid variable, number n. The var keyword may also
be used, as explained in Section 1.2 in the Command Reference under the INITIAL
command.
MODEL var
sets the model (in a particular range of zones) to the user-defined constitutive model
var, written as a FISH function. If the model defines new properties, then the names
of these may be given as parameters to the PROPERTY, PRINT and PLOT commands.

FLAC Version 8.0


2 - 22 FISH in FLAC

PLOT ex n <zone>
plots contours of the extra grid variable n, treating it as a scalar quantity. FLAC will
assume the variable is associated with gridpoints unless the keyword zone is given,
which indicates that the extra grid variable is associated with zone centroids.
PLOT ex n,m <zone>
plots vectors of the extra grid variables n and m, where n corresponds to the x-
component of the vector, and m corresponds to the y-component. FLAC will assume
the variables are associated with gridpoints unless the keyword zone is given, which
indicates that the extra grid variables are associated with zone centroids.
PLOT ex n,m,l <zone>
plots tensors constructed from the extra grid variables n, m and l, where n corresponds
to the xx-component of the tensor, m corresponds to the yy-component, and l to
the xy-component. (The tensor is assumed to be symmetric.) FLAC assumes the
variables are associated with gridpoints unless the keyword zone is given, which
indicates that the extra grid variables are associated with zone centroids.
PRINT var
prints out the value of the FISH variable var. var (and everything else that it calls)
will be executed if it is a FISH function.
PRINT ex n <zone>
prints out the values of the extra grid variable, number n. The usual range limits may
be used, as with any other FLAC grid variable. The keyword zone inhibits printing
of the last row and column (which are only used for gridpoints).
PRINT fish
prints out a list of FISH symbols and either their current values or an indication of
their type. c m indicates a constitutive model function. Variables with names that
start with a dollar sign ($) are not printed with the above command, but they may be
printed with the PRINT $fish command.
PRINT fishcall
prints the current associations between fishcall ID numbers and FISH functions (see
Section 2.4.4).
SET fishcall n <remove> name
The FISH function name will be called in FLAC from a location determined by the
value of the fishcall ID number n. The currently assigned ID numbers are listed in
Table 2.2. The optional keyword remove causes the FISH function to be removed
from the list when placed before the FISH function name.

FLAC Version 8.0


FISH REFERENCE 2 - 23

SET var value


sets the value of a FISH variable var to the given value. The given number also
determines the type given to var, as explained in Section 2.2.5. Note that value
may itself be a FISH variable or function name; in this case, its value and type are
transferred to var. Neither var nor value may be a FISH array name.
TITLE @str
changes the stored title (used on plots, for example) to the value of the FISH string
variable str. Note that the variable name must be preceded by the @ sign.
Similarly, @str may appear anywhere that a file name is expected (for example, in
the SAVE, RESTORE, SET log and HISTORY commands). The FISH string stored in
str is used as the file name.

2.4.2 Execution of FISH Functions

In general, FLAC and FISH operate as separate entities; FISH statements cannot be given as FLAC
commands, and FLAC commands do not work directly as statements in a FISH program. However,
there are many ways the two systems may interact; some of the more common ways are listed:
1. Direct use of function – A FISH function is executed at the user’s request by
giving its name on an input line. Typical uses are to generate geometry, set up
a particular profile of material properties, or initialize stresses in some fashion.
2. Use as a history variable – When used as the parameter to a HISTORY com-
mand, a FISH function is executed at regular times throughout a run, whenever
histories are stored.
3. Automatic execution during stepping – If a FISH function makes use of the
generalized fishcall capability (or contains the WHILESTEPPING statement),
then it is executed automatically at every step in FLAC ’s calculation cycle,
or whenever a particular event occurs. (See Section 2.4.4 for a discussion on
fishcall.)
4. Use of function to control a run – Since a FISH function may issue FLAC
commands (via the COMMAND statement), the function can be used to “drive”
FLAC in a way that is similar to that of a controlling data file. However, the
use of a FISH function to control operation is much more powerful, since
parameters to commands may be changed by the function.
5. Use of constitutive model functions – A FISH function that can be used instead
of the built-in constitutive models may be written. This type of user-written
model is integrated into FLAC ’s calculation cycle at the deepest level (see
Section 2.8 for complete details).

FLAC Version 8.0


2 - 24 FISH in FLAC

The primary way of executing a FISH function from FLAC is to give its name as FLAC input. In
this way, FISH function names act just like regular commands in FLAC. However, no parameters
may follow the function name so given. If parameters are to be passed to the function, then they
must be set beforehand with the SET command (explained later).
There is another important link between FISH and FLAC: a FISH symbol (variable or function
name) may be substituted anywhere in a FLAC command that a number is expected. This is a very
powerful feature, because data files can be set up with symbols rather than with actual numbers.
Example 2.9 shows how a data file that is independent of the mesh density can be constructed; the
same geometry (a hole in the center of a block) can be set up for any number of elements in the
mesh simply by changing two numbers in the SET command.

Example 2.9 FISH function with generic mesh handling capability


new
def make_hole
right = 20.0 ; physical size of block & hole
top = 20.0
_xcen = 12.0
_ycen = 10.0
rad = 6.0
ihole = int(iright * _xcen / right)
jhole = int(jtop * _ycen / top)
end
; --- FLAC input ---
set iright=10 jtop=15 ; number of zones
make_hole ; for this example
grid iright, jtop
gen 0,0 0,top right,top right,0
model elas
gen circ _xcen, _ycen rad
model null reg=ihole,jhole

Example 2.9 illustrates several of the points made above: the function make hole is invoked by
giving its name on a line; the parameters controlling the function are given beforehand with the SET
command; there are no numerical values in the FLAC input (they are all replaced by symbols).
String variables may be used in a similar way, but their use is much more restricted than the use of
numerical variables. A FISH string variable may be substituted (a) wherever a file name is required,
or (b) as a parameter to the TITLE command. In these cases, the @ sign must be attached to the FISH
name of the variable, so that FLAC can distinguish between a literal name and a variable standing
for a name. Example 2.10 illustrates the syntax.

FLAC Version 8.0


FISH REFERENCE 2 - 25

Example 2.10 Using string variables


new
def xxx
name1 = ’abc.log’
name2 = ’This is run number ’ + string(n_run)
name3 = ’abc’ + string(n_run) + ’.sav’
end
set n_run = 3
xxx
set log = @name1
title @name2
save @name3

The intrinsic function string( ) is described in Sections 2.2.7 and 2.5.5; it converts a number to a
string.
Another important method of using a FISH function is to control a FLAC run or a series of FLAC
operations. FLAC commands are placed within a COMMAND . . . ENDCOMMAND section in the
function. The whole section may be within a loop, and parameters may be passed to FLAC com-
mands.
This approach is illustrated in Example 2.11, in which 14 complete runs are done, each with a
different value of Poisson’s ratio. The results are summarized by a movie which displays the
exaggerated grid distortion for each case in sequence.

Example 2.11 Controlling a series of FLAC runs


def series
p_rat = -0.9
loop nn (1,14)
s_mod = youngs / (2.0 * (1.0 + p_rat))
b_mod = youngs / (3.0 * (1.0 - 2.0 * p_rat))
t_var = ’ Poisson‘s ratio = ’ + string(p_rat)
command
ini sxx = 0.0 syy = 0.0 sxy = 0.0
ini xvel = 0.0 yvel 0.0 xdis = 0.0 ydis = 0.0
prop shear=s_mod bulk=b_mod
step 200
title @t_var
plot hold grid mag 800
end_command
p_rat = p_rat + 0.1
end_loop

FLAC Version 8.0


2 - 26 FISH in FLAC

end
grid 5 5
mod elas
prop dens=2000
set grav 10
fix x y j=1
set youngs 1e8
movie file s.mov on
window -2 7 -2 7
series

For each run (i.e., execution of the loop), all grid variables are reset and properties redefined.
The title is also redefined, so that the current value of Poisson’s ratio is displayed on each plotted
screen. For successful movies, it is usually necessary to specify a fixed window and fixed scales (e.g.,
magnification, vector scales or contour intervals) so that comparison between frames is meaningful.

2.4.3 Error Handling

FLAC has a built-in error-handling facility that is invoked when some part of the program detects an
error. There is a scheme for returning control to the user in an orderly fashion, no matter where the
error may have been detected. The same logic may be accessed by a user-written FISH function, by
using the predefined scalars error, nerr, ierr and jerr (see Section 2.5.1 for a complete list of scalars).
If a FISH function sets error to a nonzero value (e.g., 1), then the error-handling facility of FLAC
is invoked immediately, and a message is printed. For example, stepping and FISH processing stop
as soon as error is set. The message that is printed depends on the value of nerr that is set:
nerr
0 no message
>0 FLAC ’s internally defined message is displayed.
<0 The value of the FISH variable fish msg is displayed if it contains a string;
otherwise, nothing is printed. The FISH function that sets nerr should assign
a string to fish msg, which should not be a function name. If fish msg
does not exist as a FISH variable, then a generic message is indicated.
The value of nerr may also be tested. It will contain the last error number to be processed by FLAC.
The variables ierr and jerr correspond to the grid (i, j) numbers that are displayed by some messages.
If nerr is tested in an optimized function, the value of zero will always be returned.
It is important to note that execution of a FISH function is terminated immediately after the statement
error = 1 is encountered; all required assignments (e.g., setting nerr and fish msg) should be
done before setting error. Note that error can also be tested, but it always returns a value of zero.

FLAC Version 8.0


FISH REFERENCE 2 - 27

The error-handling mechanism may also be used in situations that do not involve “errors.” For
example, stepping may be halted when a certain condition is detected, as illustrated in Example 2.12:

Example 2.12 Using the Error Handler to control a run


new
def ww
while_stepping
if unbal < 1e2 then
if step > 5 then
nerr = -1
fish_msg=’ Unbalanced force is now: ’+string(unbal)
error=1
end_if
end_if
end
grid 5 5
m e
pro d 1000 sh 1e8 bu 2e8
fix x y j=1
set grav 10
step 1000

The run will stop when the unbalanced force is less than the set value. Note that in this example
the test of step is necessary because the unbalanced force is zero at the start of stepping.

2.4.4 FISHCALL

FISH functions may be called from several places in the FLAC program. The form of the command
is
SET fishcall n <remove> name
Setting a fishcall causes the FISH function name to be called from FLAC from a location determined
by the value of ID number n. Currently, the ID numbers shown in Table 2.2 are assigned (at present,
they are all in the calculation cycle). The numbers indicate the position where fishcall is located in
the program. Note that ID numbers (in Table 2.2) are placed between specific components of the
calculation cycle. This indicates the stage at which the corresponding FISH function is called. For
example, a function associated with ID 1 would be called just before the stress calculation (stresses
from velocities); ID 4 functions would be called just after.
The ID number 0 also corresponds to functions that contain the WHILE STEPPING statement (i.e.,
these functions are automatically mapped to ID 0). Any number of functions may be associated
with the same ID number (although the order in which they are called is undefined; if the order is
important, then one master function should be called, which then calls a series of sub-functions).

FLAC Version 8.0


2 - 28 FISH in FLAC

Also, any number of ID numbers may be associated with one FISH function. In this case, the same
function will be invoked from several places in the host code.
Parameters may be passed to FISH functions called by using the intrinsic function fc arg(n), where
n is an argument number. The meanings of the parameters (if any) are listed in Table 2.2.
In addition to the fishcall ID numbers shown in Table 2.2, there is also a fishcall 20 which can be
called before the calculation cycle. This fishcall provides control over the convergence criterion
used in the SOLVE fos command. Arguments available for this fishcall are
fc arg(1) input: lower FOS bracket
fc arg(2) input: upper FOS bracket
fc arg(3) output: set 0 to continue, or 1 to stop solve process
There is a printout keyword fishcall (the abbreviation is fishc) that lists the current associations
between ID numbers and FISH functions (i.e., PRINT fishcall).
The SET fishcall command normally adds the given name to the list already associated with the
given ID number. However, the keyword remove, placed before the FISH name, causes the FISH
function to be removed from the list. For example,
set fishcall 2 remove xxx

will remove the association between function xxx and ID number 2. Note that a FISH function
may be associated twice (or more) with the same ID number. In this case, it will be called twice
(or more). The remove keyword will remove only one instance of the function name.

FLAC Version 8.0


FISH REFERENCE 2 - 29

Table 2.2 Assigned fishcall IDs


Location in Calculation Cycle CONFIG Mode

top of main cycle loop


fishcall 0 all modes
begin groundwater sub-loop (SET ngw = n)
fishcall 1 only for flow on
flows from pressure gradients
fishcall 2 only for flow on
pressure changes at gridpoint due to unbalanced flows
fishcall 3 only for flow on
free field pressure and flow calculations
particle tracking
end of groundwater sub-loop
begin mechanical sub-loop (SET nmech = n)
fishcall 4 only for CONFIG thermal
thermal stress calculation
fishcall 5 only for CONFIG thermal
fishcall 6 all modes
stress calculation: stresses from velocities and coordinates
fishcall 7 all modes
fishcall 8 only for CONFIG gwflow
pore pressure generation due to mech. volume change
fishcall 9 only for CONFIG gwflow
fishcall 10 all modes
interface calculations
fishcall 11 all modes
fishcall 12 only if structures exist
structural calculations
fishcall 13 only if structures exist
free-field calculations
IEB calculations
fishcall 14 all modes
motion calculations (velocity, coordinates from force-sums)
fishcall 15 all modes
ATTACH calculation, TRACK calculation
end of mechanical sub-loop, begin thermal sub-loop
fishcall 16 only for thermal on
all thermal calculations
fishcall 17 only for thermal on
end thermal sub-loop
just before large-strain update
fishcall 19 all modes
large-strain update
fishcall 18 all modes
end of main cycle loop

FLAC Version 8.0


2 - 30 FISH in FLAC

The data file in Example 2.13 illustrates the use of a fishcall. The function rotation is called just
before the motion calculation in FLAC (ID = 14) in order to apply x- and y-velocity components
to rotate a grid. This example tests the stress calculation in the large-strain mode; the σxx and σyy
stress components return to their initial values following a cyclic rotation of 30 degrees.

Example 2.13 Illustration of fishcall use


;--- test of stress rotation ---
config extra 4
g 1 1
mo el
def ini_coord
loop i (1,igp)
loop j(1,jgp)
ex_1(i,j)=x(i,j)
ex_2(i,j)=y(i,j)
ex_3(i,j)=sqrt((ex_1(i,j)-xc)ˆ2+(ex_2(i,j)-yc)ˆ2)
ex_4(i,j)=atan2((x(i,j)-xc),(yc-y(i,j)))
end_loop
end_loop
end
set xc=0 yc=0
ini_coord
def rotation
tt=tt+delta_t
theta=0.5*amplitude*(1.0-cos(2*pi*freq*tt))
z_area=area(1,1)-1.0
loop i (1,igp)
loop j (1,jgp)
xt=xc+ex_3(i,j)*sin(ex_4(i,j)+theta*degrad)
yt=yc-ex_3(i,j)*cos(ex_4(i,j)+theta*degrad)
xvel(i,j)=xt-x(i,j)
yvel(i,j)=yt-y(i,j)
end_loop
end_loop
end
set fishcall 14 rotation ; ... just before MOTION
fix x y
ini sxx 1
set freq=1 delta_t=1e-3 amplitude=30
set large
pro den 1 she 300 bu 300
hist nstep 2
hist tt
hist theta

FLAC Version 8.0


FISH REFERENCE 2 - 31

hist sxx i 1 j 1
hist syy i 1 j 1
hist z_area
def series
loop nn (1,10)
command
step 100
plot grid vel stres
end_command
end_loop
end
movie file rotate.mov on
window -1 2 -1 2
series
movie off
plot hold his 3 4 vs 1

FLAC Version 8.0


2 - 32 FISH in FLAC

2.5 Predefined Functions, Variables and Arrays

There are certain functions, variables and arrays that are built into FISH – the names of these
entities must be avoided when naming user-defined variables or functions. This section describes
all predefined entities, except those pertaining to user-defined constitutive models (which are listed
in Section 2.8). The entities are organized into several categories: scalars (single variables), grid
variables, constitutive model variables, general intrinsic functions, table functions and variables
that give access to FLAC ’s data structure. In some cases, an entity is listed under more than one
category, as appropriate.

2.5.1 FLAC-Specific Scalar Variables

The variables listed in this category have a single value, and are specifically related to internal FLAC
data structures or the solution process. An asterisk (*) denotes that the variable may be assigned a
value within a user-written function; otherwise, the variable’s value may only be tested, not set.
app pnt pointer to APPLY list structure (integer); see Section 2.5.7
appgw pnt pointer to the data structure representing applied groundwa-
ter items (integer); see Section 2.5.7
appth pnt pointer to the data structure representing applied thermal
items (integer); see Section 2.5.7
att pnt pointer to ATTACH list structure (integer); see Section 2.5.7
cf axi axisymmetry option (CONFIG axisymmetry) = 1 if config-
ured, else 0
cf creep creep option (CONFIG creep) = 1 if configured, else 0
cf dyn dynamic option (CONFIG dynamic) = 1 if configured, else 0
cf ext extra grid variables (CONFIG extra) returns the number of
grid variables
cf gw groundwater option (CONFIG gwflow) = 1 if configured, else
0
cf ps plane-stress option (CONFIG p stress) = 1 if configured, else
0
cf therm thermal option (CONFIG thermal) = 1 if configured, else 0
cm max * only defined within a constitutive model; the model must
return cm max as the maximum confined modulus; see Sec-
tion 2.8

FLAC Version 8.0


FISH REFERENCE 2 - 33

crtdel timestep for creep calculation (as set by the SET crdt com-
mand)
crtime “creep time”
dydt gpi returns critical gridpoint i value resulting from dynamic
timestep
dydt gpj returns critical gridpoint j value resulting from dynamic
timestep
dytdel timestep for dynamic calculation (as set by the SET dydt
command)
dytime “dynamic time” – real time used in a fully dynamic simula-
tion
error * If error (an integer) is set by a FISH function to a nonzero
value, then control immediately passes to FLAC ’s error pro-
cessor; see Section 2.4.3. error always returns zero if it is
tested.
fos final value of fos
fos f current value of multiplier, F , used in SOLVE fos; see Sec-
tion 2.5.1.1 for more details
gwtdel timestep for groundwater calculation (as set by SET gwdt
command)
gwtime “groundwater time” (consolidation time)
ieb pnt pointer to IEB list structure (integer); see Section 2.5.7
ierr * zone or gridpoint number printed out in some error mes-
sages (integer). It can be set or tested; see Section 2.4.3 for
details.
igp total number of gridpoints in i-direction (integer)
int pnt pointer to interface list structure (integer); see Section 2.5.7
izones total number of zones in i-direction (integer)
jerr * zone or gridpoint number printed out in some error mes-
sages (integer). It can be set or tested; see Section 2.4.3 for
details.
jgp total number of gridpoints in j -direction (integer)

FLAC Version 8.0


2 - 34 FISH in FLAC

jzones total number of zones in j -direction (integer)


large = zero if small-strain mode is in operation; otherwise, large
is nonzero (integer)
mode (integer) only defined within a constitutive model to denote
the type of calculation that should be done; see Section 2.8
nerr * error number that can be set or tested; see Section 2.4.3
for details
nerr fish last FISH error number
s 3dd 3D damping (SET 3d damping) = 1 if on, = 0 if off
s dyn dynamic calculation (SET dyn) = 1 if on, = 0 if off
s echo echo flag (SET echo) = 1 if on, = 0 if off
s flow flow calculation (SET flow) = 1 if on, = 0 if off
s imp implicit option (SET implicit) = 1 if on, = 0 if off
s log log flag (SET log) = 1 if on, = 0 if off
s mech mechanical calculation (SET mech) = 1 if on, = 0 if off
s mess message flag (SET message) = 1 if on, = 0 if off
s movie movie active (MOVIE on/off) = 1 if on, = 0 if off
s therm thermal calculation (SET thermal) = 1 if on, = 0 if off
sm max * only defined within a constitutive model. The model must
return sm max as the maximum shear modulus; see Sec-
tion 2.8
sratio maximum unbalanced force ratio in grid
step current step number (integer)
str pnt pointer to a structural element data structure (integer); see
Section 2.5.7
tab pnt pointer to TABLE list structure (integer); see Section 2.5.7
tenflg = zero if tension cutoff is to be inhibited; otherwise, tension
cutoff is allowed (integer)
thtdel timestep for thermal calculation (as set by the SET thdt com-
mand)

FLAC Version 8.0


FISH REFERENCE 2 - 35

thtime “thermal time”


trac pnt pointer to TRACK list structure (integer); see Section 2.5.7
udm pnt pointer to a user-defined model list structure (integer); see
Section 2.5.7
unbal maximum unbalanced force in grid
unbflow returns unbalanced flow in fast flow mode
v ngw number of groundwater sub-steps (SET ngw) (positive inte-
ger)
v nmech number of mechanical sub-steps (SET nmech) (positive in-
teger)
v ntherm number of thermal sub-steps (SET nther) (positive integer)
wbiot Biot coefficient of effective stress. Note that this variable
corresponds to the value given in the WATER biot c com-
mand.
wbulk * bulk modulus of water. Note that this variable corresponds
to the value given in the WATER bulk command; the local bulk
modulus of water may be changed independently by using
the INITIAL fmodulus command. In other words, the returned
value of wbulk may have no relation to the bulk modulus used
in the grid; similarly, setting wbulk may have no effect if the
INITIAL command is subsequently used to override it.
wdens * density of water
xgrav * x-component of gravity (positive is to the right)
ygrav * y-component of gravity (positive is upward). Note that
the STEP command must be given for gravity to take effect;
body forces are computed from the given gravity components
when STEP is given.

There is also a group of scalar variables (not listed above) that are only for use in a user-defined
constitutive model (see Section 2.8).

FLAC Version 8.0


2 - 36 FISH in FLAC

2.5.1.1 Use of Variable fos f

The FISH scalar fos f is the current F used in the SOLVE fos calculation. fos f is only nonzero
during cycling that is done as part of the fos solution; therefore fos f can be tested against zero
to determine whether fos is active. At the start of a fos solution, an elastic simulation is done to
determine the characteristic time for the system. During cycling in this phase, fos f has the value
1 × 1020 . The user-written FISH code may test for this value, to set non-failing conditions, for
example.
Note that SOLVE fos executes multiple save/restore cycles, so that a user-written FISH function will
not retain variable values between cycles. Any information to be passed between cycles can be
written to file. See the following example, which writes successive values of F to an ASCII file.
In general, a binary file can be used to speed communication between successive incarnations of a
user-written FISH function.

Example 2.14 Example use of fos f


; This performs a SOLVE FOS on a simple system. After the complete
; run finishes, the file RESULT.OUT contains a list of F values used
; to divide material properties. This is for illustration. In a real
; case, the value of F could be used to change the properties of some
; user-defined object.
grid 15 15
model mohr
prop dens 1000 she 1e8 bu 2e8 fric 30 coh 3.5e4 tens 1e10
fix x y j=1
set grav 10
def setup ; Initialize results file ...
array arr(1)
oo = open(’result.out’,1,1)
arr(1) = string(0)
oo = write(arr,1)
oo = close
end
setup
def qqq
array arrsav(500)
while_stepping ; Called on restore, for first cycle episode
if fflag = 0
fflag = 1
if fos_f = 0.0 ; Only write record if solve fos active
exit
endif
oo = open(’result.out’,0,1) ; Read in current results
oo = read(arr,1)

FLAC Version 8.0


FISH REFERENCE 2 - 37

nlines = parse(arr(1),1)
if nlines > 0
loop n (1,nlines)
oo = read(arr,1)
arrsav(n) = arr(1)
endLoop
endif
nlines = nlines + 1
oo = close
oo = open(’result.out’,1,1) ; Write out old results + new one
arr(1) = string(nlines)
oo = write(arr,1)
if nlines > 1
loop n (1,nlines-1)
arr(1) = arrsav(n)
oo = write(arr,1)
endLoop
endif
arr(1) = string(fos_f)
oo = write(arr,1)
oo = close
endif
end
set fflag=0
solve fos

The contents of RESULT.OUT are

11
1.0000E+20
1.0000E+00
2.0000E+00
1.5000E+00
1.2500E+00
1.3750E+00
1.4375E+00
1.4063E+00
1.3906E+00
1.3984E+00
1.3945E+00

FLAC Version 8.0


2 - 38 FISH in FLAC

2.5.2 General Scalar Variables

The variables listed in this category have a single value and are not specifically related to FLAC;
they are general-purpose scalars. An asterisk (*) denotes that a variable may be assigned a value
within a user-written function; otherwise, the variable’s value may only be tested, not set. The
variables listed below are of floating-point type unless declared otherwise.
clock number of hundredths-of-a-second from midnight
cycle current cycle (step) number
degrad π/180 (used to convert degrees to radians – for example,
a = cos(30*degrad) gives the cosine of 30◦ )

do update This “function” returns zero, but its use in an assignment


statement causes a complete update of all grid-related quan-
tities; the same update is done every ten steps in large-strain
mode. Note that this operation is slow.
grand random number drawn from normal distribution, with a mean
of 0.0 and standard deviation of 1.0. The mean and standard
deviation may be modified by multiplying the returned num-
ber by a factor and adding an offset.
pi π
step current step (cycle) number
unbal maximum unbalanced force
urand random number drawn from uniform distribution between
0.0 and 1.0

2.5.3 FLAC-Specific Model Variables

The following reserved names refer to gridpoint or zone variables that require the row and column
numbers to be specified in parentheses immediately following the name. For example, the xx-stress
in zone (i,j) would be referred to as sxx(i,j), where i and j evaluate to legal integers that
correspond to grid indices; an error will be indicated during execution if the indices are out of the
range of the grid. Both i and j may be arbitrarily complex expressions involving functions or
even other FLAC array names. The following variable names must be spelled out in full in FISH
statements; they cannot be truncated, as in FLAC commands. An asterisk (*) denotes that the
variable (or individual bit) can be modified by a FISH function; otherwise, its value may only be
tested. All grid variables are of floating point type except for flags and model, which are integers,
and damp, which depends on its arguments.
Zone variables evaluate to zero if the zone is null, and gridpoint variables evaluate to zero if the
gridpoint is surrounded by null zones.

FLAC Version 8.0


FISH REFERENCE 2 - 39

2.5.3.1 Gridpoint Variables

damp * grid-based damping parameters. Note that damp takes a


third argument: damp(i, j, code) = value or value = damp(i,
j, code). It either sets or retrieves grid-based damping infor-
mation for gridpoint (i,j), according to the value of code:

code Description value


1 static damping local 1
type (integer) combined 2
2 static damping constant (float) value
3 dynamic damping local 1
type (integer) combined 2
Rayleigh 3
4 dynamic damping local and value
constant (float) combined
5 dynamic Rayleigh fraction (float) value
6 dynamic Rayleigh frequency (float) value
7 dynamic Rayleigh full 0
switch (integer) mass term only 1
stiffness only 2

All damping variables may be changed dynamically during


cycling, but for changes to Rayleigh parameters to take ef-
fect, the function do update must be called, preferably after
all of the grid has been scanned (the function is very time-
consuming, and operates on global data).
disp * total displacement
ex n * extra (floating-point) variables, where n ranges from 1 to
the number specified on the CONFIG extra = n command
f2mod * non-wetting gridpoint fluid modulus (only for CONFIG
tpflow mode)

FLAC Version 8.0


2 - 40 FISH in FLAC

flags condition flags – logical or of several bits:


* fixed in x 2
* fixed in y 4
null gridpoint 8
structural connection 64
* marked gridpoint 128
attached gridpoint 256
* PP fixed 512
null groundwater gridpoint 1024
* fixed temperature 2048
null thermal gridpoint 4096
absorbing boundary in x 8192
absorbing boundary in y 16384
* fixed saturation 65536
* fixed pore pressure of the non-wetting phase 131072
* fixed seepage (two-phase flow) 262144
fmod * gridpoint fluid modulus. Be careful if this variable is
changed, since critical fluid timesteps will be altered, and
numerical instability may occur. If in doubt, issue a STEP
command, which causes the timestep to be recomputed.
ftens * fluid tensile strength. This is a gridpoint variable.
g2flow non-wetting gridpoint flow sum (only for CONFIG tpflow
mode)
gflow gridpoint flow sum. This is the fluid flow, in volume per
unit groundwater time, flowing into a gridpoint. In steady-
state conditions, the flow sums will be almost zero at interior
gridpoints, since the inflow will balance the outflow. At fixed
pore-pressure gridpoints, gflow will be the flow into or out
of the grid (positive flow denotes “into the grid”). Note
that, when in CONFIG axisymmetry mode, the flow volume
is associated with a unit angle, which is 1 radian.
gmsmul gridpoint multiplier assigned by multi-stepping option
gpp * gridpoint pore pressure
nwgpp * non-wetting gridpoint pore pressure (only for CONFIG
tpflow mode)
rsat * residual saturation (only for CONFIG tpflow mode)
sat * saturation. This is a gridpoint variable which ranges from
0 to 1.

FLAC Version 8.0


FISH REFERENCE 2 - 41

temp * temperature (only for CONFIG thermal mode)


tflow thermal energy sum at a gridpoint. At a fixed temperature
gridpoint, a positive energy sum denotes energy entering
the grid, while a negative sum denotes energy leaving the
grid. A nonzero energy sum at a free gridpoint indicates
that the temperature is unsteady at the gridpoint. A zero (or
close to zero) energy sum indicates steady conditions. Note
that when in CONFIG axisymmetry mode, the energy sum is
associated with a unit angle, which is 1 radian.
vga * van Genuchten coefficient a (only for CONFIG tpflow
mode)
vgp0 * van Genuchten reference pressure (only for CONFIG tpflow
mode)
vgpcnw * van Genuchten non-wetting exponent (only for CONFIG
tpflow mode)
vgpcw * van Genuchten wetting exponent (only for CONFIG tpflow
mode)
x * x-coordinate
xacc * x-acceleration (only for CONFIG dynamic mode)
xbody x-component of body force (summation of gravity and ap-
plied forces)
xdisp * x-displacement
xforce unbalanced gridpoint force in x-direction; if the gridpoint is
fixed, then this force is the reaction force on the “support.”
xvel * x-velocity
y * y-coordinate
yacc * y-acceleration (only for CONFIG dynamic mode)
ybody y-component of body force (summation of gravity and ap-
plied forces)
ydisp * y-displacement
yforce unbalanced gridpoint force in y-direction; if the gridpoint is
fixed, then this force is the reaction force on the “support.”
yvel * y-velocity

FLAC Version 8.0


2 - 42 FISH in FLAC

2.5.3.2 Zone Variables

area zone area


Area is computed every time it is used. If it is required
frequently, then it should be stored locally, either as a scalar
(inside a loop) or in an ex n array.
density * zone density
dy state * special indicator codes for double-yield model (see Sec-
tion 1 in Constitutive Models):
(1) currently at yield in shear
(2) currently at yield in volume
(4) shear yield criterion involves out-of-plane stress (does
not mean at yield)
(8) currently at yield in tension
NOTE: The codes may be added together in the case of mul-
tiple yielding; for example, both shear and volumetric yield
would produce an indicator of (3), obtained by adding (1)
for shear yield, and (2) for volumetric yield.
e plastic * accumulated plastic shear strain (only for strain-softening,
double-yield and bilinear models)
et plastic * accumulated plastic tensile strain (only for strain-soften-
ing, double-yield and bilinear models)
ev plastic * accumulated plastic volumetric strain (only for double-
yield and Cam-clay models)
ev tot * accumulated total volumetric strain (only for Cam-clay
model)
ex n * extra (floating-point) variables, where n ranges from 1 to
the number specified on the CONFIG extra = n command
flags condition flags – logical or of several bits:
* A-B triangle pair absent 16
* C-D triangle pair absent 32
inimodel causes initialization of derived model properties to be done
for zone (i, j); changes in properties will cause immediate
changes in the model response.

FLAC Version 8.0


FISH REFERENCE 2 - 43

k11 fluid mobility coefficient (only for CONFIG gwflow mode)


k12 fluid mobility coefficient (only for CONFIG gwflow mode)
k22 fluid mobility coefficient (only for CONFIG gwflow mode)
model constitutive model number:
1 null model
2 elastic, isotropic
3 Mohr-Coulomb
4 elastic, anisotropic
5 ubiquitous-joint
6 strain-hardening/softening
7 elastic/viscous
8 power law creep
9 WIPP creep
10 double-yield
11 modified Cam-clay
12 Drucker-Prager
13 crushed-salt viscoplastic
14 WIPP-creep viscoplastic
15 Burgers-creep viscoplastic
16 bilinear strain-hardening/softening
ubiquitous-joint
-100 CPP (CPP built-in and CPPUDM) models
DLL models written in C++ are identifiable by their names,
accessible via z model. Note that FISH user-written consti-
tutive models may also return a number (as given in the CON-
STITUTIVE MODEL statement in the corresponding FISH
function).

FLAC Version 8.0


2 - 44 FISH in FLAC

poro2 * porosity (only for CONFIG tpflow mode)


pp * zone pore pressure
state plastic state (for all plasticity models, except Finn and Hoek-
Brown models):
0 elastic
1 currently at yield in shear and/or volume
2 currently not at yield but has been in the past, either
in shear or tension (in matrix) or volume
3 currently at yield in tension
6 ubiquitous-joints at yield in shear
7 ubiquitous-joints currently not at yield but have
been in the past, either in shear or tension
8 ubiquitous-joints at yield in tension
sxx * xx-stress
sxy * xy-stress
syy * yy-stress
szz * zz-stress
udcoe * coefficient of volume strain in pore pressure formula (only
for CONFIG tpflow mode)
visrat * viscosity ratio (wet/non-wet) (only for CONFIG tpflow
mode)
vol strain accumulated volumetric strain (only for CONFIG gwflow
mode)
vsxx xx-component of stress, including stiffness-proportional
Rayleigh damping term (only for dynamic analysis)
vsxy xy-component of stress, including stiffness-proportional
Rayleigh damping term (only for dynamic analysis)
vsyy yy-component of stress, including stiffness-proportional
Rayleigh damping term (only for dynamic analysis)
vszz zz-component of stress, including stiffness-proportional
Rayleigh damping term (only for dynamic analysis)

FLAC Version 8.0


FISH REFERENCE 2 - 45

wk11 * wetting fluid mobility coefficient for full saturation (only


for CONFIG tpflow mode)
wk12 * wetting fluid mobility coefficient for full saturation (only
for CONFIG tpflow mode)
wk22 * wetting fluid mobility coefficient for full saturation (only
for CONFIG tpflow mode)
xcen * x-component of zone center
xflow x-component of the zone flow vector – actually, specific
discharge in units of velocity. This quantity is not stored by
FLAC, and must be computed when needed: the calculation
is time-consuming.
xnwflow x-component of non-wetting zone flow vector
ycen * y-component of zone center
yflow y-component of the zone flow vector – actually, specific
discharge in units of velocity. This quantity is not stored by
FLAC, and must be computed when needed: the calculation
is time-consuming.
ynwflow y-component of non-wetting zone flow vector

FLAC Version 8.0


2 - 46 FISH in FLAC

z group * returns a string corresponding to the group name of zone


(i,j ).†
z hyst returns a value corresponding to the hysteretic damping vari-
ables Mt , γ1 and γ2 . z hyst requires three arguments:
var = z hyst(i,j,vname)

where i,j are the zone indices and vname is a string denoting
the variable:
‘modfac’ Mt
‘e1’ γ1
‘e2’ γ2

† If the zone is not associated with a group name, then var will contain the integer zero. Thus, before
printing out a string, var should be tested, using the type () function – e.g.,
loop i (1, izones)
loop j (1, jzones)
var = z group(i,j)
if type(var) = 3
oo = out(string(i) +’,’+string(j)+’ Group = ’+var)
else
oo = out(string(i)+’,’+string(j)+’ No group’)
endif
endLoop
endLoop

When z group(i,j) is used as the destination in an expression, the source variable is used as the group
name to be associated with the zone (i,j ). If the zone is already associated with a group name, the
association is replaced with the new one. If the group name does not already exist, it is created. If
the source variable is not a valid string, nothing is done, and no error is indicated. For example:
grid 10 10
model elas
def qqq
z group(2,2) = ’fred’
z group(3,3) = 33
end
qqq

In this case, zone (2,2) receives the group name “fred,” but zone (3,3) receives nothing. The
command PRINT group lists “fred” as a valid group name. A group name can be associated with a
zone even if the zone contains the null model. Note that the group name must contain at least two
characters.

FLAC Version 8.0


FISH REFERENCE 2 - 47

z model returns a string denoting the name of a DLL model, or the


integer zero if the zone does not contain a DLL model.
z prop * returns or assigns a property value for a DLL model. z prop
requires three arguments:
var = z prop(i,j,pname)
z prop(i,j,pname)

when i,j are the zone indices, and pname is a string denoting
the property name. Refer to the model description for a list of
property names. Note that the Finn and Hoek-Brown models
are DLLs; their property names are listed in Section 1 in the
Command Reference.
z prop also returns the plasticity state number for the Finn
and Hoek-Brown models:
num = z prop(i,j,‘state’)

num is 0, 1 or 2 as defined for the state zone variable.


zmsmul zone multiplier assigned by multi-stepping option

2.5.3.3 Strain Calculations

There are eight FISH zone “variables” (ssr, ssi, ssr3d, ssi3d, vsr, vsi, fsr, fsi) that give user-written
functions access to zone strains and strain rates. Note that “shear strain rate” in this context means
the square root of the second invariant of the deviatoric strain rate. The following four (read-only)
functions return only single values for the zone identified by index i, j:
ssi(i, j) maximum shear strain increment (in the 2D plane)
ssr(i, j) maximum shear strain rate (in the 2D plane)
ssi3d(i, j) maximum shear strain increment (3D formulation)
ssr3d(i, j) maximum shear strain rate (3D formulation)
vsi(i, j) volumetric strain increment
vsr(i, j) volumetric strain rate
The following two functions provide all the tensor components, rather than invariants, providing
four components in the array arr, which the user must declare beforehand, and which must have at
least four elements (the function itself returns a zero).
fsi(i, j, arr) full strain increment tensor
fsr(i, j, arr) full strain rate tensor

FLAC Version 8.0


2 - 48 FISH in FLAC

The components in arr are ordered according to the array index (given as the first number in the
following table):
index 1 xx
index 2 yy
index 3 zz
index 4 xy
The computation of strain rate is identical to that performed by FLAC when it applies constitutive
relations to a zone (see Section 1.3.3.1 in Theory and Background) – i.e., strain rates are based on
gridpoint velocities and the current coordinates. “Strain increments” are computed with the same
equations, but with displacements substituted for velocities. There are two potential problems with
the latter calculation. First, gridpoint displacements may be reset or changed at any time by the
user; they are not used in the calculation process. It is the user’s responsibility to ensure that
displacements are accumulated over a meaningful interval. Second, the strain increments are based
on the geometry at the time of measurement. If the geometry changes significantly during a large-
strain simulation, the measured strain will depend on the assumption made about the reference state
for geometry; there are many different formulations for strain to be found in the literature when
large displacements are involved. The conscientious user may wish to use only the function fsr,
and derive strain increments by accumulation, using some formula of choice.
Note that the functions described take a long time to execute. It is rather inefficient to compute the
values for each zone at each timestep, if strains are only needed for certain zones (e.g., for histories);
the recording logic should be done only for the zones of interest. Further, since each function takes
about the same time to execute, it is better to use fsr or fsi if more than one strain component is
needed for a zone.
Example 2.15 illustrates the application of these functions to calculate strain components. Note
that the arrays must be defined first. The strain increment and strain rate tensors are then calculated
and the arrays are filled with the statements
dum = fsr(i,j,ar)
dum = fsi(i,j,ai)

Example 2.15 Strain calculations


;--- Test of FISH strain measures ---
conf ext 10
grid 5 5
m e
pro d 1000 s 1e8 b 2e8
set grav 10
fix y j=1
solve

FLAC Version 8.0


FISH REFERENCE 2 - 49

def qqq
array ar(4) ai(4)
loop i (1,izones)
loop j (1,jzones)
dum = fsr(i,j,ar)
dum = fsi(i,j,ai)
ex_1(i,j) = sqrt((ar(1)-ar(2))ˆ 2 + 4.0 * ar(4)ˆ 2) / 2.0
ex_2(i,j) = sqrt((ai(1)-ai(2))ˆ 2 + 4.0 * ai(4)ˆ 2) / 2.0
ex_3(i,j) = ar(1) + ar(2) + ar(3)
ex_4(i,j) = ai(1) + ai(2) + ai(3)
ex_5(i,j) = ai(1)
ex_6(i,j) = ai(2)
endLoop
endLoop
end
qqq
;--- to test, give the following commands, line by line, & compare
print ssr ex_1 zon
print ssi ex_2 zon
print vsr ex_3 zon
print vsi ex_4 zon
pause
plot hold ex_6 zone fil bou

2.5.4 FLAC Constitutive Model Variables

Property values for all constitutive models may be accessed (changed, as well as tested) in any
general FISH function (i.e., any function that is not a constitutive model itself). As with the general
grid variables, indices must immediately follow the name of the property, enclosed in parentheses.
Property names must be spelled out in full, followed by zone indices (which may be single numbers,
symbols, or complicated expressions); for example, a valid FISH statement would be
cohesion(2,3) = 3.4e5

If you write a function that tries to change a property variable, but the associated model does not
exist at the specified grid location (i,j), then no error will be given; however, no change will be
made to the grid. Similarly, if you try to obtain the value of a property for which no corresponding
model exists at the specified grid location, the value will be returned as zero; no error will be
detected. Consult Section 1.2 in the Command Reference and Section 1 in Constitutive Models
for further information on the meanings and usage of the following variables.

FLAC Version 8.0


2 - 50 FISH in FLAC

a 1∗ bulk ctable e primary∗ ff c3‡ g thexp†


a 2∗ bulk mod cy p E50 ref ff c4‡ gas c∗
a1 bulk ref cy q econduct† ff count‡ hb aac
a3 c1 d f∗ ej plastic ff evd‡ hb cohesion
a wipp∗ c2table d wipp∗ Eoed ref ff latency‡ hb dilation
act energy∗ c3 d2table es plastic ff switch‡ hb doption
alpha cam p density especc heat† fj2table hb e3plas
angle cam q di2 et plastic fjtable hb friction
atable cap flag dilation etj plastic flag ini hb ind
b f∗ cap pressure dilation flag Eur ref fr2 hb len
b wipp∗ citable dilation mob ev plastic frac d∗ hb mmc
b0∗ cj2table dilaw ev tot fricf hb plas
b1∗ cjtable dilf f qx† friction hb poption
b2∗ co2 dj2table f qy† fric0 hb scc
beta cohesion djtable f rho friction cv hb soption
bijoint conductivity† dtable f t0† friction mob hb ssc
bimatrix con1† dy state f thexp† fricv hb tension
biot c con2† e dot star∗ ff c1‡ f2table hba
bulk current cptable e plastic ff c2‡ ftable hbmb
∗ available only for creep model option — see Section 1 in Creep Material
Models
† available only for thermal model option — see Section 1 in Thermal Analysis
‡available only for dynamic option — see Section 1 in Dynamic Analysis

FLAC Version 8.0


FISH REFERENCE 2 - 51

List of material properties of constitutive models (continued).

hbpsi k11 multable porosity shear upper void current


hbs k12 mv 1 pressure sig1 void initial
hbs3cv k22 mv0 qdil sig2 void max
hbsigci kappa n 1∗ qvol sig3 Volume hardening
Hc Knc n 2∗ rf spec heat† vol strain
jangle kshear n cond† rf stable xconduct†
jc2 lambda ng rho∗ state xmod
jcohesion lconduct† n wipp∗ rs1∗ sv xyconduct†
jd2 lspec heat† ninc rs2∗ sv0 yconduct†
jdilation m nuyx s f∗ swsxx ymod
jf2 m1 nuzx s g1∗ swsxy young ref
jfriction m3 ocr s k1∗ swsyy
jtension mk p ini shear swszz
k exx∗ mm p ref shear current temp∗
k eyy∗ modnum per table shear flag tension
k ezz∗ mp1 permeability shear hardening thexp†
k exy∗ mpc Pc shear lower tjtable
k shear mod∗ mtable poiss shear mod ttable
k viscosity∗ multiplier por table shear ref viscosity∗

∗ available only for creep model option — see Section 1 in Creep Material
Models
† available only for thermal model option — see Section 1 in Thermal Analysis

FLAC Version 8.0


2 - 52 FISH in FLAC

Note that properties for the CPP built-in models are accessed with the z prop function rather than
directly by name.
In addition to the above set of names corresponding to built-in models, the properties of user-written
models may be addressed in a similar manner. Again, the names must be spelled in full, and zone
indices must follow the name if the property is referred to outside of the function in which it is
defined. See Section 2.8 for a discussion on properties for user-written models. Properties of DLL
models are set and retrieved with the z prop function (Section 2.5.3.2).

2.5.5 Intrinsic Functions

All functions return floating-point values except for and, or, not, int and type, which return integers,
and get mem, which returns a pointer. The functions max, min, abs and sgn return integers if their
argument(s) are all integer; otherwise, they return as floating-point. All functions must be placed on
the right-hand side of an assignment statement, even if the function’s return value is of no interest.
For example,
ii = out(’ Hi there!’)

is a valid way to use the out function. In this case, ii is not used.
abs(a) absolute value of a
acos(a) arc cosine of a (result is in radians)
and(a,b) bit-wise logical and of a and b
asin(a) arc sine of a (result is in radians)
atan(a) arc-tangent of a (result is in radians)
atan2(a,b) arc-tangent of a/b (result is in radians) (NOTE: b may be
zero.)
cos(a) cosine of a (a is in radians)
cparse(s, nc1, nc2) see Section 2.6
error string
This function causes an error condition. FISH function pro-
cessing (and command processing) stops immediately. The
message reported is string. This function can be used for
assignment only. (string = error is not allowed.)
exp(a) exponential of a

FLAC Version 8.0


FISH REFERENCE 2 - 53

fc arg(n) passes arguments to FISH functions where n is any FISH


variable or expression that evaluates to an integer in the range
1 to 20.
float(a) converts a to a floating-point number. If it cannot be con-
verted (e.g., if a is a string), then 0.0 is returned.
fstring(a, isig) This function works like string if isig = 0. Otherwise, the
number of “significant figures” (converted to string form) for
floating-point numbers in a is set to isig. Significant figures
in this context means the number of digits after the decimal
point. The maximum for isig is 7, and the minimum is 1. If
isig is given values outside of this range, it is truncated. The
action of fstring is the same as string for integer or string
variables (i.e., isig is ignored).
get mem(nw) gets nw integers or floating point variables from FLAC ’s
memory space, and returns an integer pointer to the start of
the contiguous array of objects. See Section 2.5.6.3 for more
details.
grand random number drawn from normal distribution: mean =
0.0; standard deviation = 1.0
in(s) prints out the message contained in string variable s, and then
waits for input from the keyboard. The returned value will be
of type int or float if a single number that can be decoded as
integer or floating-point, respectively, has been typed in. The
number should be the only thing on the line; however, if it is
followed by a space, comma or parenthesis, then any other
characters on the line are ignored. If the characters typed in
by the user cannot be interpreted as a single number, then
the returned value will be a string containing the sequence
of characters.
int(a) converts a to integer. If it cannot be converted (e.g., if a is a
string), then zero is returned.
ln(a) natural logarithm of a
log(a) base-ten logarithm of a
lose mem(nw,ia) returns nw previously allocated variables to FLAC. The pa-
rameter ia is the pointer of the start of the array of objects;
there is no checking done to ensure that ia is a valid address.
The return value is undefined. See Section 2.5.6.3 for more
details.

FLAC Version 8.0


2 - 54 FISH in FLAC

max(a,b) returns maximum of a, b


min(a,b) returns minimum of a, b
not(a) bit-wise logical not of a
or(a,b) bit-wise logical inclusive or of a, b
out(s) prints out the message contained in s to the screen (and to
the log file, if it is open). The variable s must be of type
string. The returned value of the function is zero if no error
is detected, and 1 if there is an error in the argument (e.g., if
s is not a string).
parse(s, i) see Section 2.6
pre parse(s, i) see Section 2.6
rez exe(s) The intrinsic function rez exe (which always returns zero)
causes the command contained in the given string, s, to be
executed. Note that COMMAND . . . END COMMAND must not
be used in a FISH function invoked within the rezoning logic
(i.e., a function specified by the REZONE set method com-
mand). The commands that may be executed by
rez exe( ) are limited to INITIAL, GENERATE, MODEL, PROP-
ERTY and APPLY. If the string cannot fit on one line of FISH
code, then it must be composed of separate concatenated
sub-strings stored as a symbol (which is then given as the
argument to rez exe( ) instead of being given directly as a
quoted string).
sgn(a) sign of a (returns -1 if a < 0; else, 1)
sin(a) sine of a (a is in radians)
sqrt(a) square root of a
string(a) converts a to a string. If a is already of type string, then
the function simply returns a as its value. If a is int or float,
then a character string will be returned that corresponds to
the number as it would be printed out. However, no blanks
are included in the string.
tan(a) tangent of a (a is in radians)
type(e) the variable type of e is returned as an integer with value 1,
2, 3, 4 or 5, according to the type of the argument: int, float,
string, pointer or array, respectively.

FLAC Version 8.0


FISH REFERENCE 2 - 55

urand random number drawn from uniform distribution between


0.0 and 1.0

2.5.6 Special Functions – Tables, Arrays and Memory Access

The functions described in the previous section are conventional in the sense that they simply return
a value, given some parameter(s), or they are executed for some effect. In other words, they always
appear on the right-hand side of any assignment statement. In contrast, the functions described in
this section (except the array functions in Section 2.5.6.2) may appear on either side of an assignment
(= sign). They act partly as functions and partly as arrays.

2.5.6.1 Tables

The functions table, xtable, ytable and table size allow FISH functions to create and manipulate
FLAC tables, which are indexed arrays of number pairs used in several of FLAC ’s commands and
operations. However, tables are different from arrays in other programming languages. Tables are
dynamic data structures; items may be inserted and appended, and interpolation between values may
be done automatically. Consequently, the manipulation of tables by FISH is time-consuming. Use
them with caution! The action of each function depends on whether it is the source or destination
for a given data item; hence, each function is described twice.
A table is a list of pairs of floating-point numbers, denoted for convenience as x and y, although the
numbers may stand for any variables, not necessarily coordinates. Each table entry (or (x,y) pair)
also has a sequence number in the table. However, the sequence number of a given (x,y) pair may
change if a new item is inserted in the table. Sequence numbers are integers that start from 1 and
go up to the number of items in the table. Each table has a unique identification number, which
may be any integer except zero.
There are two distinct ways that tables may be used in a FISH function. The table function behaves
in the same way as the regular FLAC TABLE command (i.e., insertion and interpolation is done
automatically). The other functions, xtable and ytable, allow items to be added or updated by
reference to the sequence numbers; no interpolation or insertion is done.
y = table(n,x) The existing table n is consulted, and a y-value is found by in-
terpolation, corresponding to the given value of x. The value
of x should lie between two consecutive stored x-values, for
the results to be meaningful. An error is indicated if table n
does not exist.

FLAC Version 8.0


2 - 56 FISH in FLAC

table(n,x) = y An (x,y) pair is inserted into the first appropriate place in


table n (i.e., the new item is inserted between two existing
items with x-values that bracket the given x-value). The new
item is placed at the beginning of the table, or appended to
the end if the given x is lower than the lowest x or greater than
the greatest x, respectively. The number of items in the table
is increased by one, following execution of this statement.
If table n does not exist, it is created, and the given item is
taken as the first entry. The given statement is equivalent to
the FLAC command TABLE n insert x y. If the given x is
identical to the stored x of an (x,y) pair, then the y-value is
updated, rather than inserted.
x = xtable(n,s) The x-value of the pair of numbers that have sequence num-
ber s in table n is returned. An error is indicated if table n
does not exist, or if sequence number s does not exist.
xtable(n,s) = x The given value of x is substituted for the stored value of
x in the (x,y) pair having sequence number s in table n. If
sequence number s does not exist, then sufficient entries
are appended to table n to encompass the given sequence
number; the given x is then installed. If the given table does
not exist, it is created. An error is indicated if n is given as
zero, or if s is given as zero or negative.
y = ytable(n,s) The action of this statement is identical to the corresponding
xtable statement, except that the y-value of the (x,y) pair,
rather than x, is retrieved.
ytable(n,s) = y The action of this statement is identical to the corresponding
xtable statement, except that the y-value of the (x,y) pair,
rather than x, is installed.
i = table size(n) The number of entries in table n is returned in value i.
Since the xtable and ytable functions can create tables of arbitrary length, they should be used with
caution. It is suggested that the table function be used in constitutive models where interpolated
values are needed from tables. The xtable and ytable functions are more useful when generating
tables.
The following notes may be of use for the FISH table functions.
1. In large tables, for efficiency, sequence numbers should be scanned in the di-
rection of ascending numbers. FLAC keeps track of the last-accessed sequence
number for each table; this is used to start the search for the next requested
number. If the requested number is less than the previous one, the whole table
may need to be searched.

FLAC Version 8.0


FISH REFERENCE 2 - 57

2. The functions xtable and ytable, rather than table, should be used to update
values in an existing table. Although table will update an (x,y) pair if the given
x is identical to the stored x, there may be slight numerical errors, which can
result in insertion rather than updating.
3. In a FISH function that replaces old table values with new values, it is necessary
to create the table first, since the action of retrieving old values will produce
an error. A complete table may be created (and its entries all set to zero) by a
single statement, as illustrated:
xtable(4,100) = 0.0

If table 4 does not exist, then it is created. 100 entries are also created, each
containing (0.0,0.0). Subsequent statements, such as
xtable(4,32) = xtable(4,32) + 1.0
ytable(4,32) = ytable(4,32) + 4.5

will update table values, but will not alter the length of the table. If the latter
statements are executed before table 4 exists, then an error will be detected.
4. Stored values (both x and y) in tables are always floating-point numbers. Given
integers are converted to floating-point type before storing. Be careful about
precision!
As an example in the use of table functions, the input sequence in Example 2.16 produces a smooth-
pointed, star-shaped hole in a FLAC grid.

Example 2.16 Use of table functions


g 50 50
m e
def star
ntab = 1
npts = 100
d_theta = 2.0 * pi / npts
loop n (1,npts)
z = sin(3.0*theta)ˆ4 + 1.2
xtable(ntab,n) = z * cos(theta)
ytable(ntab,n) = z * sin(theta)
theta = theta + d_theta
end_loop
end
star
gen -3 -3 -3 3 3 3 3 -3
plot hold grid
gen table 1

FLAC Version 8.0


2 - 58 FISH in FLAC

plot hold grid


mod null reg 20 20
plot hold grid

2.5.6.2 Special Array Functions

Two intrinsic functions are defined:


mat inverse (A, B)
returns matrix B as the inverse of matrix A, where A and
B are square matrices of equal size. The operation causes
the (internal) allocation of 8*N*(N+1) bytes of memory, but
if called more than once, the same memory is reused. The
arithmetic is double-precision and it is assumed that all el-
ements of A are floating-point numbers. (No checking is
done!) The function returns 0 or 1, denoting success or fail-
ure, respectively.
mat transpose (A, B)
returns matrix B as the transpose of matrix A. Both A and B
must be 2D, user-defined arrays with opposite dimensions
(e.g., A(5,3) and B(3,5)). The same matrix must not be used
for both source and destination. The matrices can contain
any variable types. The function returns 0 or 1, denoting
success or failure, respectively.
Notes and cautions:
a) The functions operate on existing user-declared arrays in FISH. The number
and sizes of the array dimensions must correspond to the desired matrix oper-
ation. For example, to invert a matrix, the array must be two-dimensional and
square.
b) The matrix size is assumed to be identical to the array size. This may not be
a limitation, because arrays can be declared at compile time, based on a size
computed from a previously executed function. Example 2.17 illustrates this:

Example 2.17 Setting array size


def xxx
.
.
nn = ...
end

FLAC Version 8.0


FISH REFERENCE 2 - 59

xxx
def set_mat
array aa(nn,nn) bb(nn,nn)
end

Example 2.18 contains an example and validation of the matrix inversion function, mat inverse().

Example 2.18 Using the matrix inversion function


def size
nn = 20
end
size
def gg
float abc xyz xx bb tot
int i j nn
array abc(nn,nn) xyz(nn,nn) xx(nn) bb(nn)
loop j (1,nn)
loop i (1,nn)
abc(i,j) = urand ; random A coefficients
endLoop
xx(j) = float(j) ; X values
endLoop
loop i (1,nn) ; pre-compute b = A.x
bb(i) = 0.0
loop j (1,nn)
bb(i) = bb(i) + abc(i,j) * xx(j)
endLoop
endLoop
if mat_inverse(abc,xyz) = 1
oo = out(’ Inversion failed!’)
exit
endif
loop i (1,nn) ; now "solve" ... x = inv(A) . b
tot = 0.0
loop j (1,nn)
tot = tot + xyz(i,j) * bb(j)
endLoop
printout
endLoop
end
def printout
if i > 9
oo = out(’ i = ’+string(i)+’ x = ’+string(tot))
else

FLAC Version 8.0


2 - 60 FISH in FLAC

oo = out(’ i = ’+string(i)+’ x = ’+string(tot))


endif
end
opt gg
gg
;--- Note - x value should be (approximately) integers from 1 to nn

2.5.6.3 Special Functions to Access Memory Directly

Warning! This section is intended for experienced programmers who are familiar with the use of
linked lists. The techniques described here are powerful because they provide access to most of the
internal data in FLAC, but they are dangerous if used without full understanding.
Most of FLAC ’s data are stored in a single, one-dimensional array. A FISH program has access to
this array via imem and fmem, which act like array names for integer and floating-point numbers,
respectively. Given index iad (which must be an integer), floating-point (f) or integer (i) values can
be found from
f = fmem(iad)
i = imem(iad)
Values can also be inserted in the array:
fmem(iad) = f
imem(iad) = i
These functions are potentially very dangerous, as any data can be changed in FLAC ’s main array.
Only experienced programmers should use them. No checking is done to verify that iad is an
integer, so the user must be very careful. The use of these functions is explained in Section 2.5.7.

2.5.6.4 Special Functions to Communicate Parameters

In some cases (notably, when using structural piles) it is possible to replace FLAC ’s built-in logic
with the same user-defined logic embodied in a FISH function. In order to communicate parameters
between the FISH function and FLAC ’s internal logic, the special function fc arg is provided. The
function may appear as the source or destination (right- or left-hand side of an expression), and is
used as follows.
aa = fc arg(n)
fc arg(m) = bb

The arguments n and m can be any FISH variable or expression that evaluates to an integer in the range
1 to 20, inclusive (i.e., there are 20 separate parameters that can be used to pass information). The
parameters may be integers or floating-point values (but not strings). For an example application
of fc arg, see the user-defined normal coupling-spring function, cs nfunction, described in
Section 1.11.4 in Structural Elements.

FLAC Version 8.0


FISH REFERENCE 2 - 61

2.5.7 Access to FLAC’s Data Structures

Warning! This section is intended for experienced programmers who are familiar with the use of
linked lists. The techniques described here are powerful because they provide access to most of the
internal data in FLAC, but they are dangerous if used without full understanding.
Most of FLAC ’s data are stored in a single, one-dimensional array. A FISH program has access to
this array via imem and fmem (described in Section 2.5.6.3), which act like array names for integers
and floating-point numbers, respectively. Note that imem(n) and fmem(n) map into the same location
in memory; it is the responsibility of the programmer to access the correct type of data. Pointers
to the main data structures are listed in Section 2.5.1. Each data structure consists of one or more
linked lists, with offsets to individual data items listed in Section 4. Memory can also be allocated
from a FISH program, and used to store whatever the programmer wishes. In many cases, FLAC ’s
data blocks contain one or more spare words that can be used as pointers to extension arrays that can
be allocated as needed. Although tables can be used to store data, it is much faster to use allocated
memory directly via imem and fmem.
To illustrate the use of the concepts outlined above, let us write a FISH program (see Example 2.19)
to record the maximum normal force that acts within an interface, and the step number and gridpoint
at which the maximum occurred. After setting up the problem, we allocate a block of memory to
contain the recorded data, and set up a pointer to it from the interface. The logic should work for
any number of interfaces, although Example 2.19 only involves one interface.

Example 2.19 Accessing FLAC’s data structures


g 10 11
m e
prop dens 2000 sh 1e8 bu 2e8
m n j=6
ini x add 2.5 y add -0.9 j=7,12
int 4 aside from 1,6 to 11,6 bside from 1,7 to 11,7
int 4 kn 5e8 ks 2.5e8 fric 10
set grav 10,5 large
fix x y j=1
step 1
def make_list
ip = int_pnt
loop while ip # 0
imem (ip+1) = get_mem(3) ; get storage buffer
ip = imem(ip)
endloop
end
make_list
def save_data
while_stepping

FLAC Version 8.0


2 - 62 FISH in FLAC

ip = int_pnt
loop while ip # o ;scan interfaces
ii = imem(ip+1)
loop nside (2,3) ;scan 2 sides
ispt = imem(ip+nside)
loop while ispt # 0 ; scan nodes on one side
if abs(fmem(ispt+5)) > fmem(ii) then
fmem(ii) = abs(fmem(ispt+5))
imem(ii+1) = ispt
imem(ii+2) = step
end_if
ispt = imem(ispt)
end_loop
end_loop
ip = imem(ip)
end_loop
end
def sho_data
ip = int_pnt
loop while ip # 0
ii = imem(ip+1)
s1 = ’ max-Fn = ’+string(fmem(ii))+’, ’
ig = imem(imem(ii+1)+2)
jg = imem(imem(ii+1)+3)
s2 = ’ g.p.(’+string(ig)+’,’+string(jg)+’)’
s3 = ’ at step ’+string(imem(ii+2))
xx = out(s1+s2+s3)
ip = imem(ip)
end_loop
end
step 500
sho_data

The resulting output is


max-Fn = 2.6127E+05, g.p.(7,7) at step 367

FLAC Version 8.0


FISH REFERENCE 2 - 63

2.6 FISH I/O Routines

The set of FISH functions described in this section enable data to be written to, and read from, a
file. There are two modes, namely an “ASCII” mode that allows a FISH program to exchange data
with other programs, and a “FISH” mode that enables data to be passed between FISH functions.
In FISH mode, the data are written in binary, without loss of precision, whereas numbers written
out in ASCII form may lose precision when read back into a FISH program. In FISH mode, the
value of the FISH variable is written to the file, not the name of the variable. Only one file may be
open at any one time.
close The currently open file is closed; 0 is returned for a successful operation.
open(filename, wr, mode)
This function opens a file, named filename, for writing or reading. The
variable filename can be a quoted string or a FISH string variable.
Parameter wr must be an integer with one of two values:
0 file opened for reading; file must exist
1 file opened for writing; existing file will be overwritten
Parameter mode must be an integer with one of two values:
0 read/write of FISH variables; only the data corresponding to the
FISH variable (integer, float or string) are transferred, not the
name of the variable.
1 read/write of ASCII data; on a read operation the data are
expected to be organized in lines, with CR/LF between lines. A
maximum of 200 characters per line is allowed.
The returned value denotes one of several conditions:
0 file opened successfully
1 filename is not a string
2 filename is a string, but is empty
3 wr or mode (not integers)
4 bad mode (not 0 or 1)
5 bad wr (not 0 or 1)
6 cannot open file for reading (e.g., file does not exist)
7 file already open
8 not a FISH mode file (for read access in FISH mode)

FLAC Version 8.0


2 - 64 FISH in FLAC

read(ar, n)
reads n records into the array ar. Each record is either a line of ASCII
data or a single FISH variable. The array ar must be an array of at least n
elements. The returned value is
0 requested number of lines were input without error
−1 error on read (except end-of-file)
n positive value indicates that end-of-file was encountered after
reading n lines
In FISH mode, the number and type of records must match exactly the
number and type of records written. It is up to the user to control this. If
an arbitrary number of variables is to be written, the first record could be
made to contain this number, so that the correct number could subsequently
be read.
write(ar, n)
writes n records from the first n elements of the array ar. Each record is
either a line of ASCII data, or a single FISH variable. For ASCII mode,
each element written must be of type string. The array ar must be an array
of at least n elements. The returned value is
0 requested number of lines were output without error
−1 error on write
n positive value (in ASCII mode) indicates that the nth element
was not a string (hence only n−1 lines were written). An error
message is also displayed on the screen.
The following intrinsic functions do not perform file operations, but can be used to extract items
from ASCII data that are derived from a file.
cparse(s, nc1, nc2)
This function scans the string s and decodes the characters between columns
nc1 and nc2 (inclusive) as integer, float or string.
parse(s, i)
This function scans the string s and decodes the ith item, which it returns.
Integers, floats and strings are recognized. Delimiters are the same as for
general commands (i.e., spaces, commas, parentheses, tabs and equal signs).
If the ith item is missing, zero is returned. An error message is displayed,
and zero is returned if the variable s is not a string.

FLAC Version 8.0


FISH REFERENCE 2 - 65

pre parse(s, i)
This function scans the string s and returns an integer value according to
the type of the ith item:
0 missing item
1 integer
2 float
3 string missing (unable to interpret as int or float)
Example 2.20 illustrates the use of the FISH I/O functions:

Example 2.20 Using the FISH I/O functions


def setup
a_size = 20
IO_READ = 0
IO_WRITE = 1
IO_FISH = 0
IO_ASCII = 1
filename = ’junk.dat’
end
setup
;
def io
array aa(a_size) bb(a_size)
;
; ASCII I/O TEST ------------------
status = open(filename, IO_WRITE, IO_ASCII)
aa(1) = ’Line 1 ... Fred’
aa(2) = ’Line 2 ... Joe’
aa(3) = ’Line 3 ... Roger’
status = write(aa,3)
status = close
status = open(filename, IO_READ, IO_ASCII)
status = read(bb, a_size)
if status # 3 then
oo = out(’ Bad number of lines’)
endif
status = close
;
; now check results...
loop n (1,3)
if parse(bb(n), 2) # n then
oo = out(’ Bad 2nd item in loop ’ + string(n))
exit

FLAC Version 8.0


2 - 66 FISH in FLAC

endif
endloop
;
if pre_parse(bb(3), 4) # 3 then
oo = out(’ Not a string’)
exit
endif
;
; FISH I/O TEST -----------------
status = open(filename, IO_WRITE, IO_FISH)
funny_int = 1234567
funny_float = 1.2345e6
aa(1) = ’---> All tests passed OK’
aa(2) = funny_int
aa(3) = funny_float
;
status = write(aa,3)
status = close
status = open(filename, IO_READ, IO_FISH)
status = read(bb, 3)
status = close
;
; now check results...
if type(bb(1)) # 3 then
oo = out(’ Bad FISH string read/write’)
exit
endif
if bb(2) # funny_int then
oo = out(’ Bad FISH integer read/write’)
exit
endif
if bb(3) # funny_float then
oo = out(’ Bad FISH float read/write’)
exit
endif
oo = out(bb(1)) ; (should be a good message)
command
sys del junk.dat
endcommand
end
;
io

FLAC Version 8.0


FISH REFERENCE 2 - 67

2.7 Socket I/O Routines

FISH contains the option to allow data to be exchanged between two or more Itasca codes running
as separate processes, using socket connections (as used for TCP/IP transmission over the Internet).
At present, socket I/O connections can be made between FLAC and PFC 2D or PFC 3D. FLAC 3D also
allows socket connections at this time. It is possible to pass data between two or more instances
of the same code (e.g., two instances of FLAC), but the main use is anticipated to be coupling
of dissimilar codes such as FLAC and PFC 2D. An example of such a coupling is provided in
Section 2.7.1.
The data contained in FISH arrays may be passed in either direction between two codes. The data
are transmitted in binary with no loss of precision. Up to six data channels may be open at any
one time; these may exist between two codes, or may connect several codes simultaneously. The
following FISH intrinsics are provided in FLAC . The word process denotes the instance of the code
that is currently running. All functions return a value of 10 if the ID number is invalid.
sclose(ID)
Channel ID is closed.
Note: The corresponding FISH intrinsics in PFC 2D / PFC 3D 5.0 is
socket.close(ID). See PFC documentation for details.
sopen(mode, ID)
The integer mode takes the value 0 or 1. A value of 1 causes the data channel
of number ID to be initiated, with the process acting as a server. Another
process can link to the server, with the same ID, by invoking sopen, with
mode = 0, which denotes the process as a client. The ID number must
be in the range 0 to 5 inclusive, giving a total of six possible channels
of communication. The server sopen function must be issued before the
client sopen function, for a given ID. While waiting for a connection, the
server process is unresponsive. The sopen function returns 0 when a good
connection has been made, and nonzero if an error has been detected.
Note: The corresponding FISH intrinsics in PFC 2D / PFC 3D 5.0 is
socket.open(mode, ID). See PFC documentation for details.

FLAC Version 8.0


2 - 68 FISH in FLAC

sread(arr, num, ID)


num FISH variables are received from channel ID, and placed in array arr,
which is overwritten, and which must be at least num elements in size.
The returned value is zero if data are received without error, and nonzero
if an error has occurred. Note that the function sread does not return until
the requested number of items has been received. Therefore, a process
will appear to “lock up” if insufficient data have been sent by the sending
process.
Note: The corresponding FISH intrinsics in PFC 2D / PFC 3D 5.0 is
socket.read(arr, num, ID). See PFC documentation for details.
swrite(arr, num, ID)
num FISH variables are sent on channel ID from array arr. The data in arr
may consist of a mixture of integers, reals and strings. Zero is returned for
a good data transmission, and nonzero if an error is detected. In addition,
error messages may be issued for various problems, such as incorrect array
size, etc.
Note: The corresponding FISH intrinsics in PFC 2D / PFC 3D 5.0 is
socket.write(arr, num, ID). See PFC documentation for details.
In order to achieve socket communication between two processes, codes must be started separately
from separate directories. To illustrate the procedure, we can send messages between two instances
of FLAC, and record the log files, as follows. The server log file is as follows.

Example 2.21 Server log file


def serve
array arr(3)
arr(1)=1234
arr(2)=57.89
arr(3)=’hello from the server’
oo=sopen(1,1)
oo=swrite(arr,3,1)
oo=sread(arr,1,1)
oo=sclose(1)
oo=arr(arr(1))
end
serve

The client log file is as follows.

FLAC Version 8.0


FISH REFERENCE 2 - 69

Example 2.22 Client log file


def client
array arr(3)
oo=sopen(0,1)
oo=sread(arr,3,1)
oo=out(’ Received values ...’)
oo=out(’ ’+string(arr(1)))
oo=out(’ ’+string(arr(2)))
oo=out(’ ’+string(arr(3)))
arr(1)=’greetings from the client’
oo=swrite(arr,1,1)
oo=sclose(1)
end
client

Data have been passed both ways between the two code instances. A more useful example is given
in Section 2.7.1.

2.7.1 Coupled FLAC and PFC 2D Simulation

This example demonstrates the use of the socket I/O functions to transfer data between two codes
executing separately. A deformable punch (modeled with FLAC) is driven into an assembly of
particles (modeled with PFC 2D 5.0). Initially, a series of walls is created in PFC 2D, with each
wall corresponding to a single surface segment of a FLAC zone. As the FLAC zones deform in
large-strain, gridpoint velocities are transferred to PFC 2D, so that the walls move in exactly the
same way as the boundary segments of the FLAC grid. The resulting wall forces, due to particles
interacting with the walls, are transferred to FLAC as applied gridpoint forces. In this way, a fully
coupled simulation is performed.
Three data files are used in the simulation. The file in Example 2.23 must first be executed by PFC 2D
to create an assembly of particles within a container, and bring the assembly to equilibrium under
gravity. The files in Examples 2.24 and 2.25 may then be used by FLAC and PFC 2D, respectively,
to execute the simulation. In order for the system to operate correctly, both codes should be started
as separate processes. Then, Example 2.24 should be called first from FLAC as the server, which
waits (indefinitely) for a connection from another process. The file Example 2.25 may then be
called from PFC 2D (operating as a client process) to establish contact. Initially, FLAC sends a
series of wall coordinates to PFC 2D, and both codes set up arrays of pointers to eliminate searching
during cycling. Once the setup process is complete, cycling begins in both codes, with forces being
sent by PFC 2D to FLAC, and velocities being sent by FLAC to PFC 2D. Cycling in both codes is
synchronized, using a timestep of unity, so that the same displacements are calculated in each step
in each code.

FLAC Version 8.0


2 - 70 FISH in FLAC

Example 2.23 PFC 2D initialization file for coupled FLAC/PFC 2D example


;fname: fi_02_23.dat
new
set random 10001
domain extent -2.5 2.5 -0.5 2.5
cmat default model linear
wall create id 1 vertices -2,2 -2,0
wall create id 2 vertices -2,0 2,0
wall create id 3 vertices 2,0 2,2
ball gen id=1,200 rad=.05 .09 box -2 2 0 2
ball attribute density 2000 damp 0.7
ball property kn 1e8 ks 1e8
wall property kn 1e8
set grav 0 -10

cyc 15000
ball prop fric 1.0
set timestep scale
cyc 15000
save pex0.p2sav

Example 2.24 FLAC initialization and run file for coupled FLAC/PFC 2D example
;fname: fi_02_24.dat
grid 20 10
gen -0.5 1.5 -0.5 2.0 0.5 2.0 0.5 1.5
model elas
prop dens 1000 shear 2.5e7 bulk 5e7
fix x y j=11
def setLimits ; Array limits ... must be changed for bigger problem
nbuff = 1000 ; general buffer size
nList = 200 ; max number of walls generated
igpf = igp
jgpf = jgp
end
setLimits
def iniComms ; initialize communications, & send wall data
array buff(nbuff) numrec(1)
array i1List(nList) j1List(nList) i2List(nList) j2List(nList)
array appnt(igpf,jgpf)
oo = sopen(1,1) ; channel 1 ... server
numWalls = 0
loop j (1,jzones) ; left side

FLAC Version 8.0


FISH REFERENCE 2 - 71

numWalls = numWalls + 1
i1List(numWalls) = 1
j1List(numWalls) = j
i2List(numWalls) = 1
j2List(numWalls) = j+1
endLoop
loop i (1,izones) ; bottom
numWalls = numWalls + 1
i1List(numWalls) = i+1
j1List(numWalls) = 1
i2List(numWalls) = i
j2List(numWalls) = 1
endLoop
loop j (1,jzones) ; right side
numWalls = numWalls + 1
i1List(numWalls) = igp
j1List(numWalls) = j+1
i2List(numWalls) = igp
j2List(numWalls) = j
endLoop
ibuf = 0
loop nn (1,numWalls)
setIJ
ibuf = ibuf + 1
buff(ibuf) = x(i1,j1)
ibuf = ibuf + 1
buff(ibuf) = y(i1,j1)
ibuf = ibuf + 1
buff(ibuf) = x(i2,j2)
ibuf = ibuf + 1
buff(ibuf) = y(i2,j2)
command
apply xforce=1e-10 yforce=1e-10 i=i1 j=j1
endCommand
endLoop
numrec(1) = numWalls
oo = out(’ Sending ’+string(numWalls)+’ wall segments to PFC ...’)
oo = swrite(numrec,1,1)
oo = swrite(buff,ibuf,1)
ap = app_pnt ; set up easy access to apply-list pointers
loop while ap # 0
ii = imem(ap+$kapi1)
jj = imem(ap+$kapj1)
appnt(ii,jj) = ap
ap = imem(ap)

FLAC Version 8.0


2 - 72 FISH in FLAC

endLoop
end
def setIJ ; set i,j values, given index nn
i1 = i1List(nn)
j1 = j1List(nn)
i2 = i2List(nn)
j2 = j2List(nn)
end
def endComms ; Close communications
oo = sclose(1)
end
def sendVelocities
ibuf = 0
loop nn (1,numWalls)
setIJ
buff(ibuf+1) = xvel(i1,j1)
buff(ibuf+2) = yvel(i1,j1)
buff(ibuf+3) = xvel(i2,j2)
buff(ibuf+4) = yvel(i2,j2)
ibuf = ibuf + 4
endLoop
ibuf = numWalls * 4
oo = swrite(buff,ibuf,1)
getForces
end
def getForces
loop nn (1,numWalls) ; reset applied forces
setIJ
ap1 = appnt(i1,j1)
ap2 = appnt(i2,j2)
fmem(ap1+$kapv3) = 0.0
fmem(ap1+$kapv4) = 0.0
fmem(ap2+$kapv3) = 0.0
fmem(ap2+$kapv4) = 0.0
endLoop
ibuf = numWalls * 3
oo = sread(buff,ibuf,1)
ibuf = 0
loop nn (1,numWalls)
setIJ
FxW = buff(ibuf+1)
FyW = buff(ibuf+2)
MomW = buff(ibuf+3)
denom = FyW * (x(i1,j1)-x(i2,j2)) - FxW * (y(i1,j1)-y(i2,j2))
if denom # 0.0

FLAC Version 8.0


FISH REFERENCE 2 - 73

rat = (MomW - FyW * x(i2,j2) + FxW * y(i2,j2)) / denom


rat = max(0.0,min(1.0,rat))
ap1 = appnt(i1,j1)
ap2 = appnt(i2,j2)
fmem(ap1+$kapv3) = fmem(ap1+$kapv3) + rat * FxW
fmem(ap2+$kapv3) = fmem(ap2+$kapv3) + (1.0-rat) * FxW
fmem(ap1+$kapv4) = fmem(ap1+$kapv4) + rat * FyW
fmem(ap2+$kapv4) = fmem(ap2+$kapv4) + (1.0-rat) * FyW
endif
ibuf = ibuf + 3
endLoop
end
call app.fin
set echo off
iniComms
set echo on
ini yvel=-0.5e-3
set fishcall 15 sendVelocities
win -2 2 -1 3
set large
cycle 1300
endComms

Example 2.25 PFC 2D run file for coupled FLAC/PFC 2D example


;fname: fi_02_25.dat
restore pex0.p2sav
define setLimits ; Array limits ... must be changed for bigger problems
global nbuff = 1000 ; general buffer size
global nList = 200 ; max number of walls generated
end
@setLimits
define iniComms
global buff = array.create(nbuff)
global numrec = array.create(1)
global Wpoint = array.create(nList)
socket.open(0,1)
socket.read(numrec,1,1)
global numWalls = numrec(1)
global ibuf = numWalls * 4 ; (4 values per wall)
socket.read(buff,ibuf,1)
global ibuf = 0
global IDmake = 100 ; starting created wall number
loop nn (1,numWalls)

FLAC Version 8.0


2 - 74 FISH in FLAC

getSeg
command
wall create id=@IDmake vertices (@x1,@y1) (@x2,@y2)
wall property kn=1e8 ks=1e8 range id @IDmake by wall
endCommand
section
loop foreach local wp wall.list
if wall.id(wp) = IDmake
exit section
endif
endLoop
io.out(’ ** error in finding wall pointer’)
Exit
EndSection
Wpoint(nn) = wp ; save wall pointer
IDmake = IDmake + 1
endLoop
end
define getSeg
global ibuf = ibuf + 1
global x1 = buff(ibuf)
ibuf = ibuf + 1
global y1 = buff(ibuf)
ibuf = ibuf + 1
global x2 = buff(ibuf)
ibuf = ibuf + 1
global y2 = buff(ibuf)
end
define endComms
socket.close(1)
end
define getVelocities
global ibuf = numWalls * 4
socket.read(buff,ibuf,1)
local ibuf = 0
loop local nn (1,numWalls)
ibuf = ibuf + 1
local xv1 = buff(ibuf)
ibuf = ibuf + 1
local yv1 = buff(ibuf)
ibuf = ibuf + 1
local xv2 = buff(ibuf)
ibuf = ibuf + 1
local yv2 = buff(ibuf)
local wp = Wpoint(nn)

FLAC Version 8.0


FISH REFERENCE 2 - 75

loop foreach facet wall.facetlist(wp)


local fv1 = wall.facet.vertex(facet,1)
local fv2 = wall.facet.vertex(facet,2)
wall.vertex.vel(fv1) = vector(xv1,yv1)
wall.vertex.vel(fv2) = vector(xv2,yv2)
endloop
endLoop
end
define sendForces
local ibuf = 0
loop local nn (1,numWalls)
local wp = Wpoint(nn)
ibuf = ibuf + 1
buff(ibuf) = wall.force.contact.x(wp)
ibuf = ibuf + 1
buff(ibuf) = wall.force.contact.y(wp)
ibuf = ibuf + 1
buff(ibuf) = wall.moment.contact(wp)
endLoop
ibuf = numWalls * 3
socket.write(buff,ibuf,1)
end
set fish callback 5.0 @getVelocities
set fish callback 50.0 @sendForces
@iniComms
save pex1.p2sav
wall tolerance ctolerance 1e-3; to make sure the timestep remains unity
set timestep scale
cycle 1300
@endComms
save pex2.p2sav
return

Figure 2.1 shows the initial particle assembly and the 40 walls that form the deformable punch,
corresponding to three sides of a 200-zone FLAC grid. Figure 2.2 shows the final state from PFC 2D,
in which the active surfaces of the punch exhibit large deformation in response to the forces exerted
by the particles. Figure 2.3 shows the corresponding state from FLAC, in which the same surface
deformation is evident, as well as contours of major principal stresses. Note that FLAC will halt
with a “bad geometry” error if the simulation is continued much further.

FLAC Version 8.0


2 - 76 FISH in FLAC

C
pGrb00   0 u0 i

l
lFrnnc

l
 lFihc

 l  l
 lFhnc
 

Figure 2.1 Initial particle assembly and walls that form deformable punch

C
pGrb00   0 u0 i

l
lFrnnc

l
 lFihc

 l  l
 lFhfnc
 

Figure 2.2 Final state from PFC 2D

FLAC Version 8.0


FISH REFERENCE 2 - 77

JOB TITLE : FLAC-PFC2D Coupling

FLAC (Version 8.00)


1.600

LEGEND

6-Nov-15 13:49
step 1300
1.400
-6.134E-01 <x< 5.974E-01
5.106E-01 <y< 1.721E+00

Boundary plot

0 2E -1 1.200

Minimum principal stress


-1.75E+08
-1.25E+08
-7.50E+07
1.000
-2.50E+07
2.50E+07
7.50E+07
Contour interval= 2.50E+07
Extrap. by averaging
0.800
Grid plot

0 2E -1

0.600

Itasca Consulting Group, Inc.


Minneapolis, MN
-0.500 -0.300 -0.100 0.100 0.300 0.500

Figure 2.3 Final state from FLAC

The physical process is quite straightforward, but there are some important points to note:
1. Large-strain mode should be used in FLAC, because PFC 2D cannot operate
in any other way, and it is necessary for wall movement to keep track with
zone-boundary movement.
2. In a simulation that is closely coupled, data should be exchanged at every
cycle, at the appropriate points in the calculation cycles for both codes.
3. The timestep in both codes should be identical. This is achieved here by
running FLAC in static mode, and PFC 2D with timestep scaling. Thus, the
timestep is unity for both processes*. Alternatively, both codes could be run
in dynamic mode with the same timestep.
Some manipulation of forces sent from PFC 2D must be done, because each wall produces forces
and moments relative to its center of rotation. FLAC gridpoint forces are derived from this data by
using equations of moment equilibrium, to determine the line of action of the resultant force. To
avoid giving many APPLY commands at each step, the data in an APPLY list are modified directly
by a FISH function, using a single APPLY list that is set up at the beginning of the run.

* The kinematic constraints for the walls take precedence, and the timestep may end up being smaller
than unity. To make sure the kinematic constraints in this example do not modify the timestep, the
following line is added in Example 2.24: wall tolerance ctolerance 1e-3. This effectively increases
the wall cell extents and relieves the kinematic constraints.

FLAC Version 8.0


2 - 78 FISH in FLAC

The example is contrived and simplified, but it illustrates that closely coupled interaction may be
achieved between a continuum region and a region that contains discrete bodies.

FLAC Version 8.0


FISH REFERENCE 2 - 79

2.8 User-Defined Constitutive Models

2.8.1 Introduction and Overview

New constitutive models may be written in the FISH language. Once compiled successfully, a new
model behaves just like a built-in model as far as the user is concerned (i.e., it can be installed and
removed by using the MODEL command). A user-defined model can also use properties that are
defined and given names by the model’s author; these names act just like built-in properties (i.e.,
they can be set with the PROPERTY command, printed with the PRINT command and plotted with
the PLOT command).
User-written models execute more slowly than built-in models. After optimization (described in
Section 2.9), a FISH model will typically run somewhere between one-quarter and one-third the
speed of a built-in model. However, quite often, a user-written model needs only to be installed in
a small part of the FLAC grid, since the particular behavior that it is designed to reproduce may
only occur locally (e.g., cracking around a tunnel); the material elsewhere can be represented by a
standard model. In any case, the increased runtimes of the special model may be compensated for
by decreased human time and effort, since less work may be done trying to force-fit an inappropriate
model.
A user-written constitutive model is simply a FISH function containing some special statements
and references to special variables that correspond to local entities within a single zone. The user-
defined model (referred to as “UDM”) is called by FLAC four times per zone (once per triangular
subzone) for every solution step. It is the task of the UDM to supply a new set of stress components,
given strain increments and the old set of stress components. However, certain other tasks must be
performed, and certain conventions observed. These are described in the following sections.
When a new model has been developed, it should be exercised thoroughly on a one-zone grid with
all gridpoints fixed. Given strain paths should be applied to the zone, and histories made of the
stress response. The proposed model may be “debugged” very effectively in this way.

The Following Sections Should Only Be


Read By Experienced Programmers.

FLAC Version 8.0


2 - 80 FISH in FLAC

2.8.2 Model Definition and Use

The following statement must appear at the beginning of a FISH function for it to be recognized as
a user-defined model (UDM).
CONSTITUTIVE MODEL <n>
where n is an optional identification number. The preceding statement is incompatible with the
WHILE STEPPING and COMMAND statements, which must not appear in the same function. Once
a function containing the statement CONSTITUTIVE MODEL has been successfully compiled, the
FLAC command MODEL can be used to install the UDM in the grid, just like a built-in model (see
Example 2.26).

Example 2.26 Installing a user-defined constitutive model


def test_model
constitutive_model
zs11 = 0.0
zs22 = 0.0
end
.
.
model test_model i=2,3 j=4,5

The optional ID number that follows the word CONSTITUTIVE MODEL must be a positive integer,
and must not conflict with the ID numbers of any of FLAC ’s internal models (see Section 2.5.3
for a list of built-in model numbers, under variable name model). If the ID number is omitted or
is inappropriate, then an ID number of zero is taken. The given number is not necessary, but it
is useful when using a FISH function to perform some operation that requires a knowledge of the
model installed in a particular zone (the grid variable model will return the given ID number). Note
that the ID number can only be set by means of the CONSTITUTIVE MODEL statement; it cannot be
assigned anywhere else. The code fragment in Example 2.27 illustrates the use of an ID number.

FLAC Version 8.0


FISH REFERENCE 2 - 81

Example 2.27 Assigning model numbers to user-defined constitutive models


def test_model
constitutive_model 88
.
.
end
def put_stresses
loop i (1,izones)
loop j (1,jzones)
if model(i,j) = 88 then
sxx(i,j) = syy(i,j) * fac_1
else
.

The name for a UDM should not conflict with that of any of the built-in models (see Section 1.2 in
the Command Reference, under the MODEL command). Section 2.2.2 should also be consulted
to avoid conflicts with other predefined names.

2.8.3 User-Defined Local Property Variables

Named variables may be used by the UDM, as with any other FISH function, but since regular
FISH variables are of global scope, they cannot be used to store things that are different for each
zone. However, variables that are local to each zone may be defined by declaring them in advance
with the f prop statement,
f prop var1 var2 var3 ...
This statement is followed by a list of names separated by space(s). Several such statements may
be given, but they should precede any executable code. The names must be unique, and must not
conflict with FISH statements or any built-in property name (see Section 2.5.4). Any length of
name is allowed, but only the first 12 characters are displayed on plots or print headings.
During compilation of the FISH function, the number of user-defined local variables is counted and
used by FLAC to allocate that number of extra words of memory per zone. The names mentioned
in the f prop statement(s) are completely equivalent to FLAC properties; they may be set with the
PROPERTY command, printed with the PRINT command, and plotted with the PLOT command (as
contours). The variables are of type float; they are normally used to store material properties, but
they can be used to store any state variables at the individual zone level. The names of the local
variables are used just like any other scalar variable within the function that defines them (i.e., they
are referred to without zone indices).
Local “property” variables are also available in other FISH functions (apart from the defining
function), but there they act like other property variables (i.e., zone subscripts are needed).

FLAC Version 8.0


2 - 82 FISH in FLAC

Some program fragments in Example 2.28 illustrate the use of local property variables:

Example 2.28 Using local property variables


def my_model
constitutive_model 102
f_prop apples plums prunes bananas
f_prop grapes pears
case_of mode
case 1
;--- do initialization & checking here
case 2
zs11 = grapes * zde11 + 2.0 * zde22 / prunes
.
.
end
;
def ini_prop
loop i (1,izones)
loop j (1,jzones)
if model(i,j) = 102 then
grapes(i,j) = 34.5
prunes(i,j) = 66.6
else
.
end
;
grid 10 10
model my_model
ini_prop
.
.

In this example, the newly defined properties are used (as scalars) in the calculation of zone stresses
(discussed later). The same names are used in another function as indexed grid variables.
In general, note that indexed zone or gridpoint variables must not be used in a UDM function; the
function is already being called for a particular zone, so indices are irrelevant (and forbidden).

FLAC Version 8.0


FISH REFERENCE 2 - 83

2.8.4 State Variables

During stepping, the UDM function is called four times per zone per timestep (once for each
triangular subzone). When the function is called, the following local variables (all of type float)
are available within the function as scalars. The variables are undefined in functions that are not
constitutive model functions.
zart area or triangular subzone (input)
zde11 e11 strain increment (input)
zde12 e12 strain increment (input)
zde22 e22 strain increment (input)
zde33 e33 strain increment (input)
zdpp increment in pore pressure (output)
zdrot incremental zone rotation in SET large mode only (input)
zporos porosity of zone (in CONFIG gwflow mode only) (input)
zs11 σ11 effective stress (input and output)
zs12 σ12 effective stress (input and output)
zs22 σ22 effective stress (input and output)
zs33 σ33 effective stress (input and output)
zsub indicator for subzone averaging (input)
ztea thermal a-zone strain increment (input)
zteb thermal b-zone strain increment (input)
ztec thermal c-zone strain increment (input)
zted thermal d-zone strain increment (input)
ztsa thermal a-zone stress increment (output)
ztsb thermal b-zone stress increment (output)
ztsc thermal c-zone stress increment (output)
ztsd thermal d-zone stress increment (output)
zvisc dynamic viscosity inhibit flag (output)

FLAC Version 8.0


2 - 84 FISH in FLAC

zxbar mean distance of triangular subzone from axis of symmetry


(in CONFIG axisymmetry mode), such that the volume of the
subzone is given by zart * zxbar (input)
The notations (input) or (output) indicate, respectively, that the variable should be used (and not
modified) by the UDM, or that it may be modified by the UDM.
It is the main task of the UDM function to update the four stress components, given the current
stresses and the four strain increments. Note that the strain components are given; they cannot
be changed by the function. The process of mixed discretization (see Section 1.3.2 in Theory
and Background) has already been applied to the strains before the UDM is called; after the
four subzones are processed by the UDM, the stresses are adjusted externally, as described in
Section 1.3.3 in Theory and Background.
If a state variable that applies to the whole quadrilateral zone (e.g., accumulated plastic strain) is
required, then appropriate averaging must be done within the UDM. The variable zsub indicates to
the function when averaging of quantities in the 4 subzones may be performed (see Section 2.8.6
for details).
The variable zdpp is an increment of pore pressure that may be generated by the constitutive model.
It is important to note that the increment in pore pressure due to the change in the volume of the zone
is already calculated before the UDM is called. The variable zdpp is only to be used by models
that produce pore pressure changes in addition to those associated with zone volume changes (e.g.,
if the grains are compressible). Note that zdpp is ignored in axisymmetric mode (i.e., pore pressure
generation cannot be done by a UDM in an axisymmetric model).
In dynamic simulations, zvisc should be set to 0.0 if it is required that stiffness-proportional damping
be inhibited; for example, this type of damping may be “switched off” if plastic flow is occurring.
If zvisc is set to 1.0, then stiffness-proportional damping will be done normally (if it has been
requested by a FLAC command).
For thermal/mechanical calculations, the bulk modulus of the model should be used to provide
increments in stresses from increments of strains. This allows the thermal expansion/contraction
to be modeled properly.

2.8.5 Operations to Be Performed by the UDM: Use of mode Variable

In addition to the action during stepping (mentioned above), the UDM function must perform other
tasks. The scalar variable mode is defined whenever the function is called by FLAC. The UDM
should test the value of mode (an integer) and perform the appropriate tasks according to its value,
as follows.
mode
1 This mode is set when the function is called prior to stepping; the UDM
may perform any initialization or checking of material properties, or it may

FLAC Version 8.0


FISH REFERENCE 2 - 85

do nothing. In mode 1, the function is called only once per zone per STEP
command.
2 Mode 2 corresponds to the main task of the function, as described in Sec-
tion 2.8.4 (i.e., new stresses should be computed from old stresses and strain
increments). In this mode, the function is called up to 4 times per zone (once
for each subzone).
3 The UDM must return values for the scalars cm max and sm max: these should
be set to the maximum confined modulus and the shear modulus, respectively,
as estimated for this zone. The value of cm max is used by FLAC to compute
a stable timestep; it is essential that a value is returned for this variable. For
an elastic model, this variable is given by K + (4G/3). Both variables are
used by the absorbing boundary logic in dynamic mode (estimates of tangent
moduli should be provided). The UDM is called once per zone for mode 3; it
is called at the beginning of stepping and every ten steps in large-strain mode.
It may also be called more often if FLAC determines that it needs to recompute
the internal timestep.
4 A set of 4 thermally induced stresses must be computed from a given set of 4
fictitious strains. This calculation is only required if thermal calculations are
being done. Normally, the action consists of multiplying each strain by the
current tangent bulk modulus, to give stresses. The UDM is called once per
zone for mode 4.
Note that mode 3 is called before mode 1 for constitutive models; also, zone stresses are undefined
in mode 1, mode 3 and mode 4.
As an example of a simple constitutive model written in FISH, the function in Example 2.29 performs
an operation identical to the built-in isotropic elastic model of FLAC.

Example 2.29 FISH constitutive model for isotropic elastic behavior


def m_elas
constitutive_model
f_prop m_shear m_bulk
f_prop m_e1 m_e2 m_g2
case_of mode
; --- initialization ---
case 1
m_e1 = m_bulk + 4.0 * m_shear / 3.0
m_e2 = m_bulk - 2.0 * m_shear / 3.0
m_g2 = 2.0 * m_shear
; --- running section ---
case 2
zs11 = zs11 + zde11 * m_e1 + (zde22+zde33) * m_e2

FLAC Version 8.0


2 - 86 FISH in FLAC

zs22 = zs22 + (zde11+zde33) * m_e2 + zde22 * m_e1


zs33 = zs33 + (zde11+zde22) * m_e2 + zde33 * m_e1
zs12 = zs12 + zde12 * m_g2
; --- max modulus ---
case 3
cm_max = m_bulk + 4.0 * m_shear / 3.0
sm_max = m_shear
; --- thermal stresses ---
case 4
ztsa = ztea * m_bulk
ztsb = zteb * m_bulk
ztsc = ztec * m_bulk
ztsd = zted * m_bulk
end_case
end

The “properties” m e1, m e2 and m g2 are evaluated in the initialization section, to save time
during stepping. We may store the preceding FISH code in a file (e.g., “ELAS.FIS”) and call it
from a FLAC data file, as shown in Example 2.30:

Example 2.30 Applying the FISH elastic model


g 5 5
set grav 10
fix x y j=1
call elas.fis
mod m_elas
prop m_bulk=2e8 m_shear=1e8 dens=1000
step 100
print ydisp m_bulk m_shear m_e1
ret

The results should be identical to those using FLAC ’s built-in elastic law. However, the execution
time will be slower, as explained in Section 2.8.1. The speed may be increased considerably by
using the command OPT m elas (see Section 2.9).

FLAC Version 8.0


FISH REFERENCE 2 - 87

2.8.6 Averaging of Subzone Variables: Use of zsub Variable

Some “property” variables (declared with the f prop statement) may be used to record or accumulate
state variables for the constitutive model. For example, plastic strain may be accumulated for use in
a strain-hardening law. However, properties are stored for the whole quadrilateral zone, whereas the
user-written function is called for each triangular subzone (either 2 or 4, depending on geometry).
The computed “property” (e.g., plastic strain) should be the average for the 2 or 4 subzones.
Parameter zsub (which is of type float) allows the function to know when to accumulate values and
when to store them, according to the following prescription.
zsub = 0 The function should accumulate the desired quantity in some unique
global variable. Since the function is called sequentially for all
subzones in the quadrilateral, there is no danger that the global
variable will conflict with its use by other zones and other models.
However, the global variable must not be overwritten by other (non-
constitutive) functions.
zsub > 0 The function should now divide the accumulated quantity by zsub
and store it in the appropriate property location. Since zsub will
have the value 2.0 or 4.0, the stored property will be the average
quantity. The variable used for accumulation must now be set to
zero. This is very important; otherwise, the next zone calculation
will be in error, since its accumulator will not start from zero.
The elastic model given as an example in Section 2.8.5 may be modified to illustrate the use
of parameter zsub to save average state variables. For example, suppose we want to save the
accumulated volume strain for each zone. We introduce a new property name m dvol, and a new
global variable m vol, which should not be used elsewhere. The following modified part of the
FISH code in Example 2.31 will store the average volumetric strain in the property variable m dvol.

Example 2.31 Storing average volumetric strain


.
.
f_prop m_dvol
case_of mode
.
.
;--- running section ---
case 2
zs11 = zs11 + zde11 * m_e1 + (zde22+zde33) * m_e2
zs22 = zs22 + (zde11+zde33) * m_e2 + zde22 * m_e1
zs33 = zs33 + (zde11+zde22) * m_e2 + zde33 * m_e1
zs12 = zs12 + zde12 * m_g2
m_vol = m_vol + zde11 + zde22 + zde33
if zsub > 0.0 then

FLAC Version 8.0


2 - 88 FISH in FLAC

m_dvol = m_dvol + m_vol / zsub


m_vol = 0.0
end_if
.
.

After running FLAC, the correctness may be verified by printing out both the newly defined volume
strain and FLAC ’s built-in volume strain measure:
print m dvol vsi

The two results should be identical.

2.8.7 FRIEND Functions for Constitutive Models

The FRIEND statement may be used in a user-defined model (UDM) to allow other functions (without
the CONSTITUTIVE MODEL declaration) to have access to the local zone variables of the calling
function. The format is
friend func1 func2 ...

where func1 and func2 are names of FISH functions. Within such functions (when called from the
UDM), the intrinsic zone variables (e.g., zde11, mode, etc.) and property names are treated exactly
as they are in the calling UDM. The FRIEND declaration is only necessary if zone properties and
variables are to be accessed by the associated function. Three restrictions apply:
a) Each function may only be declared as the friend of one UDM; otherwise,
there would be a conflict in zone variable names. However, each UDM may
declare any number of friends.
b) The function referred to by the FRIEND statement must be defined after the orig-
inating UDM; otherwise, the compiler cannot know that the property names
(used in the FRIEND function) are not just global variables.
c) If a FRIEND function is optimized, the associated UDM function must also be
optimized.
Example 2.32 demonstrates and validates the FRIEND logic:

FLAC Version 8.0


FISH REFERENCE 2 - 89

Example 2.32 Demonstration of FRIEND logic


;--- Test of friend logic ... all computation is done in other
; functions
def m_elas
constitutive_model
friend aaa bbb ccc bbb_sub
f_prop m_shear m_bulk m_e1 m_e2 m_g2
case_of mode
case 1
aaa
case 2
bbb
case 3
ccc
case 4
end_case
end
def aaa
m_e1 = m_bulk + 4.0 * m_shear / 3.0
m_e2 = m_bulk - 2.0 * m_shear / 3.0
m_g2 = 2.0 * m_shear
end
def bbb
zs11 = zs11 + (zde22 + zde33) * m_e2 + zde11 * m_e1
zs22 = zs22 + (zde11 + zde33) * m_e2 + zde22 * m_e1
bbb_sub
end
def bbb_sub
zs12 = zs12 + zde12 * m_g2
zs33 = zs33 + (zde11 + zde22) * m_e2 + zde33 * m_e1
end
def ccc
cm_max = m_bulk + 4.0 * m_shear / 3.0
sm_max = m_shear
end
grid 6 6
mod m_elas i=1,3 ; left-hand side in UDM
prop m_shear 1e8 m_bulk 2e8 dens 1000 i=1,3
mod elas i=4,6 ; right-hand side is built-in model
prop shear 1e8 bulk 2e8 dens 1000 i=4,6
set grav 10
fix x y j=1
opt
cyc 100

FLAC Version 8.0


2 - 90 FISH in FLAC

pr xdisp
; ---> Note that results should be symmetric, but of opposite sign.

2.8.8 Hints and Suggestions

Section 3 contains FISH versions of a number of FLAC ’s built-in models; the FISH programs are
also available on file to FLAC users. It is useful to consult these programs to get some ideas before
writing a new constitutive model. The following suggestions may also be useful.
1. After defining a constitutive function, type PRINT fish to make sure that
(a) local properties do not appear in the list; and
(b) misspelled state variables (e.g., zed22) do not appear.
2. If a constitutive program uses many global variables, it may be worthwhile to
include a $ sign as the first character in their names, since the command PRINT
fish will not print these variables (and will cause confusion by listing many
names that may be irrelevant to the user). The “$” variables may be listed
separately with the command PRINT $fish.
3. If a user-defined property is given a value for mode 2 operation of a constitutive
function, then the conditions will correspond to the last-computed subzone
(usually D) unless steps are taken to store the average value (see Section 2.8.6).
4. If you have some user-written models that you use frequently, they can be
pre-compiled and stored in a save file; this will eliminate the time delay for
compilation of complicated models. The following file fragments illustrate
the technique.
call elas.fis ;compile required models
call mohr.fis
call my model.fis
save defmod.sav ;now save compiled versions

The compiled models can now be retrieved rapidly (from some other data file):
res defmod.sav
grid 20 20
model my model
.
.

Alternatively, the command res defmod.sav could be placed in the file


“FLAC.INI” if the user-written models are always required to be available on
start-up.

FLAC Version 8.0


FISH REFERENCE 2 - 91

5. The names of the new properties defined in a user-written constitutive model


must be spelled out in full in the PRINT, PLOT and PROPERTY commands
(unlike the names of built-in properties, which may be truncated).
6. Some checking of input properties should be done in the mode 1 section of a
user-written model; error messages may be printed out by using the variables
error and nerr (see Section 2.4.3).

FLAC Version 8.0


2 - 92 FISH in FLAC

2.9 The Optimizer

The execution speed of user-written FISH functions can be increased in certain cases by using the
OPT command; a speed increase of four to eight times is typical. However, there are a number
of restrictions that limit the usefulness of the command, and may actually lead to errors if the
optimized code is used incorrectly. The optimizer was designed primarily to improve the speed of
user-written constitutive models; there is less advantage in using it for general functions.

2.9.1 Principles of Operation

In a normal FISH function, every reference to a variable necessitates a call to a “librarian” that
determines where the information is to be found. Since there are many types and variations of
variables (e.g., grid variables, intrinsic functions, local properties, etc.), the process of retrieval is
complicated and time-consuming. The optimizer attempts to go through this process beforehand
and store a machine address for each variable (or an index that gives rapid access to a machine
address). It also determines the types (integer, float or string) of variables and propagates them
through the arithmetic expressions in order to determine the types of the results in advance; this
eliminates another step at runtime.
The result of invoking the optimizer on a function is to create a new list of instructions (the “o-
code”), which consists of basic operations (arithmetic and jumps) using machine addresses. Any
references or operations that cannot be translated into simple instructions cause a temporary jump
from the o-code to the regular FISH code (the “p-code”) when the function is executed. The printout
“% optimized” indicates the proportion of instructions that were translated into o-code. Some
operations cannot be translated, in which case the optimization of the whole function fails, and an
error message is displayed.
The use of optimized and non-optimized functions during execution is automatic and transparent
to the user; if an optimized version of a function exists, then it is used instead of the non-optimized
version.

2.9.2 Use of the OPT Command

The optimizer is applied to FISH functions that are already defined:


OPT <fun1 fun2 fun3. . . >
where fun1, fun2 and fun3 are existing FISH functions. Alternatively, the OPT
command may be given with no parameters, in which case, all functions are opti-
mized. An informative message is provided for each function, indicating whether
optimization was successful. The OPT command may be given several times (the
old optimized version is erased, and a new one is created).

FLAC Version 8.0


FISH REFERENCE 2 - 93

2.9.3 Restrictions

The following rules must be observed when writing a function that can be successfully optimized.
1. The function may call other functions, but such functions must have already
been defined prior to optimization. The called functions may or may not have
been optimized themselves.
2. COMMAND sections may not be executed while an optimized function is active.
For example, an error will occur if an optimized function calls a non-optimized
function that contains a COMMAND section. An optimized function may not
contain the COMMAND statement.
3. No mixed-mode arithmetic is allowed (i.e., all variables (and functions) in
an arithmetic expression must be of the same type (all integer or all floating-
point)). Furthermore, the destination type must be the same as the source type
in an assignment statement. If type conversion is required, then the functions
int( ), float( ) and string( ) should be used. The specification statements INT,
FLOAT and STRING should be used at the beginning of the function to predefine
the types of all variables that will be used. The exponentiation operation is
exempted from the mixed-mode restriction. For example, 3.4ˆ2 is allowed.
4. The following scalar variables (see Section 2.5.2) will not work in optimized
code: clock, imem, fmem, urand and grand. All other variables and functions
work correctly.

2.9.4 Suggestions

The following suggestions are designed to improve the speed of an optimized function, but it is not
necessary to follow them in order to achieve a working program.
1. The use of property variables within a constitutive model function should be
minimized; if possible, work with regular FISH variables, which are accessed
more rapidly.
2. The following variables or functions involve extra computational overheads:
tables, all grid-indexed variables (e.g., sxx(i,j), ex 3(i,j),
shear mod(i,j), etc.) and intrinsic functions (e.g., sin(x), sqrt(x)).
Also included in the list are user-defined constitutive properties used outside
of the constitutive model in which they are defined.
3. If possible, replace exponentiation (ˆ) with repeated multiplications (e.g.,
xdifˆ2 should be replaced with xdif*xdif).

FLAC Version 8.0


2 - 94 FISH in FLAC

2.9.5 Warning

Variable types (integer, float or string) are built into the optimized code at the time of optimization.
If the variable types subsequently change, then the results of arithmetic operations will be wrong.
For example, integer arithmetic might be used to multiply two floating-point numbers. It is the
responsibility of the user to ensure that variable types do not change.

FLAC Version 8.0

You might also like