FTD128
FTD128
FTD128
2 FISH REFERENCE
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 3D.
Pre-defined FISH variables, functions and arrays are described in Section 2.5. The FISH functions
that support the structural-element logic are described in Section 2.6.
FISH is a programming language embedded within FLAC 3D that enables the user to define new
variables and functions. These functions may be used to extend FLAC 3D’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 3D data file are
translated into a list of instructions (in “pseudo-code”) stored in FLAC 3D’s memory space; the
original source program is not retained by FLAC 3D. 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 3D’s
SET command.
FISH programs are simply embedded in a normal FLAC 3D 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 3D command). Since the compiled form of a FISH function is stored in FLAC 3D’s memory
space, the SAVE command saves the function and the current values of associated variables.
Section 2.7 discusses extensions to FISH for file manipulation, and Section 2.8 describes the use of
socket communication to transfer data between FLAC 3D 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.
A summary of FISH language and intrinsic names is provided in Section 2 in the Command and
FISH Reference Summary.
2.2.1 Lines
FISH programs can be embedded in a normal FLAC 3D 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 given to the variable or function name
on the left of the = sign).
4. The line consists of a FLAC 3D 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 3D 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. (Note that
this can be changed with the command SET case sensitivity on.) 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.
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 pre-defined variable or function (see Section 2.5).
There are also many other words used in FLAC 3D 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 will 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.
If in doubt, avoid any of the names listed in Table 2.1, or contractions of the names (since FLAC 3D
allows truncation of keywords and commands).
As an alternative strategy, the FLAC 3D command SET safe on can be used to force the explicit
recognition of FISH variables in a command-line instruction. The @ symbol pre-pended to any
FISH variable identifies the object as such, and forces the command-line parser to ignore any
other possible interpretation. For example, suppose that a FISH function initial, as shown in
Example 2.1, has been created. Attempting to run the function from the command prompt would
ordinarily produce an error, since the command INITIAL would take precedence over the FISH
initial. However, using the FISH identifier @ in front of the variable gives us an unambiguous,
correct interpretation.
Table 2.1 List of words in FLAC 3D and FISH that may conflict with chosen names
Name Name Name Name Name Name
above caption default end2 fobl gp ypos
abs case define endcase fobu gp yvel
add case of degrad endcommand force gp zdisp
age caseof delete endif foreground gp zfapp
alias center density endloop free gp zfunbal
and char destroy endsection friction gp zpos
angle cid dilation error friend gp zvel
anisotropic cleanup dim ex 1, ex 2, etc. front gpextra
annulus clear dip exit fsi gpp
any clock discharge exp fsr gradient
apply close displacement expand fstrength grand
area cm max do update expgrid ftable gravity
array cohesion down extrude ftens gray
aspect color dquiet eyedistance gap grid
atan columns drucker face gauss dev group
atan2 command dstress fap gen gui
attach conductivity dt fc generate gwdt
auto config dtable fc arg geom gwtdel
average continue dump fdensity get mem gwtime
axes contour dvelocity filcolor gflow hardcopy
axial convection dy file gmsmul hbm
b mod copy dydt fill gp hbs
b wipp cos dynamic final gp copy help
back cparse dytdel fish gp dynmul his
background crdt dytime fish msg gp extra hisfile
beam create e fishcall gp group hist rep
beamsel creep e dot star fix gp head history
begin crtime ep fl isotropic gp id i elem head
behind csc echo fl null gp mass i find
below cshell edge flags gp near i head
bfix ctable effective fldt gp next i id
biot c current elastic float gp pp i next
biot mod custom element flow gp region i node head
block cycle else flow ratio gp temp id
both cylinder emod flprop gp xdisp ie area
bottom cylint end fltime gp xfapp ie fhost
boundary d wipp end case fluid gp xfunbal ie id
brick damp end command flux gp xpos ie join
bulk damping end if fmem gp xvel ie norm
cable datum end loop fmod gp ydisp ie zhost
cablesel dbrick end section fmodulus gp yfapp ieb
call dd end1 fob gp yfunbal ieb pnt
Table 2.1 List of words in FLAC 3D and FISH that may conflict with chosen names (cont.)
Name Name Name Name Name Name
ierr iterate mainwin new p3 print
if izones mark ngp p4 prop
iface jcohesion mass ngrwater p5 property
igp jdd mat inverse nmechanical p6 pslow
image jdilation mat transpose node p7 psource
imem jdip max normal p8 purge
impgrid jerr max edge not p9 pwell
implicit jfriction maxdt nquiet pac pyramid
in jgp maximum nseg pagelength qdil
in area jnx mech ratio nstep pagination query
in ctol jny mechanical nstress palette quit
in disp jnz mem nthermal parse qvol
in fhost jtension memfree nu pause qx
in ftarget jzones memory null pcx qy
in hweight kbond memsize number pcxout r
in id kn merge nvelocity penetration r integrate
in nstr ks message nxx permeability radbrick
in nstr add kshear min nxy perspective radcylinder
in pen landscape mindt nyy pfast radius
in pos large minimum nzone pi radtunnel
in prop latency mode off pile range
in sdisp ldamp model on pilesel ratio
in sstr leakage modgradient open pinterval rayleigh
in tweight left modify or plane reactivate
in vel legend mohr origin plot read
in zhost lff pnt mohr-coulomb orthotropic pltangle red
in ztarget lfob moment ostrength pltcohesion reflect
inactive light monchrome out pltfriction regenerate
increment limits move outline plttension rename
info line movie output point reset
information link msafety overlay polygon restore
initial list mul p stress porosity return
initialize lmul mx p:4 portrait reverse
inrange ln mxx p1 position rgb
insert local mxy p10 positive right
int location my p11 post rigid
int pnt log myy p12 power rlist
interface logfile mz p13 pp rotation
internal loop name p14 ppressure rs 1
isotropic lose mem ncontours p15 preparse rs 2
itasca lsys ncwrite p16 pressure sat
item macro nerr p2 pretension save
Table 2.1 List of words in FLAC 3D and FISH that may conflict with chosen names (cont.)
Name Name Name Name Name Name
sbond sel thick small tension us letter xcen
scale sel type smax tet us tabloid xciy
sclin sel volume smid text v0 xciz
section sel xcarea smin th isotropic v1 xcj
segment sel xciy solve th null v2 xdirection
sel sel xciz sort thdt v3 xdisp
sel area sel xcpolmom source then v4 xflow
sel cen sel ycomp spec heat therm ratio v5 xfob
sel cid sel ypress sphere thermal vector xforce
sel csncoh sel ytens sqrt theta velocity xform
sel csnfric sel zpress squiet thexp vertex xgrav
sel csngap selcm depend ss thickness vfactor xmaximum
sel csnk selcm linear ssi thtdel vftol xminimum
sel csscoh selcm nyield ssoften thtime vga xmom
sel cssfric selcm pile ssr time view xpolygon
sel cssk selcm syield sstress title viscosity xpos
sel density sellink head state tolerance viscous xr
sel e sellk deform step top vmagnitude xrdirection
sel extra sellk free stop total vol strain xrdisp
sel grcoh sellk node string tr:3 volume xreaction
sel grfric sellk rigid structure tr:4 vs xrfob
sel grk sellk zone substep tr:5 vsi xrvel
sel grper selnode head subtract trac pnt vsource xtable
sel head seltype beam surface trace vsr xvel
sel id seltype cable surfarea track vstrength xvelocity
sel length seltype pile surfx translate vwell xywrite
sel locsys seltype shell svelocity triangle wait y
sel mark set sxx ttable water yacceleration
sel ndforce sgn sxy ttol wbulk ybody
sel next shade sxz tunint wdens ybodyforce
sel node shear sys type wedge ycen
sel nu shell system u thc while ycomp
sel numnd shellsel syy ubiquitous while stepping ycompression
sel ortho show syz ucs whilestepping ydirection
sel per sig1 szz udm pnt window ydisp
sel press sig2 tab pnt ufob wipp ydist
sel strglb sig3 table umul write yflow
sel strglbpos sin table size unbal x yfob
sel strres size tan uniform dev xacceleration yforce
sel strrespos sketch target unmark xbody ygrav
sel strsurf skip temperature up xbodyforce yield
sel strsurfpos sm max tenflg urand xcara ymaximum
Table 2.1 List of words in FLAC 3D and FISH that may conflict with chosen names (cont.)
Name Name Name Name Name Name
yminimum z sonplane zreaction
ypos z ssi zrfob
yr z ssr zrvel
yrdirection z state zs11
yrdisp z sxx zs12
yreaction z sxy zs22
yrfob z sxz zs33
yrvel z syy zsub
ytable z syz ztea
ytens z szz zteb
ytension z volume ztec
yvel z vsi zted
yvelocity z vsr ztsa
z code z xcen ztsb
z copy z ycen ztsc
z density z zcen ztsd
z dynmul zart zvel
z extra zbody zvelocity
z facegp zbodyforce zvisc
z facenorm zcen zxbar
z facesize zde11
z fri zde12
z frr zde22
z fsi zde33
z fsr zdirection
z gp zdisp
z group zdist
z id zdpp
z inimodel zdrot
z model zextra
z near zfob
z next zforce
z numgp zgrav
z pp zmom
z prop zmsmul
z pstress zone
z qx zone head
z qy zpoross
z qz zpos
z sig1 zr
z sig2 zrdirection
z sig3 zrdisp
Variable and function names are recognized globally (as in the BASIC language). 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 3D 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 3D 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.
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.3, which shows function construction and use.
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 the following
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;
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 cannot 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.4 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.5 Removing recursion from the function shown in Example 2.4
gen zone brick size 1 1 1
def stress_sum
sum = 0.0
pnt = zone_head
loop while pnt # null
sum = sum + z_sxx(pnt)
pnt=z_next(pnt)
end_loop
stress_sum = sum
end
stress_sum
The difference between variables and functions is that a function is always executed whenever its
name is mentioned; variables simply convey their current values. 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.6.
The function h var 1 would be executed by the FLAC 3D’s history logic every few steps but, as a
side effect, the values of h var 2 through h var 6 would also be computed and used as history
variables.
There are four 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 fifteen decimal digits of precision,
with a range of approximately 10−300 to 10300 );
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 3D by a
sequence of characters enclosed by single quotes — e.g., ‘Have a nice day’ — note
that the use of strings in FLAC 3D is restricted to titles and filenames. See Section 2.4.1.);
and
4. Pointer (machine address — used for scanning through linked lists. They have an
associated type from the object to which the pointer refers, except for the null pointer).
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 is 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 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 3D command PRINT fish — the types are denoted
in the printout.
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 following 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 3D 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 pre-defined variables or functions; these
rules are presented in Section 2.5. Note that pointer variables may not be converted to or from other
variable types.
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 are 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.
Arithmetic operations are not allowed for pointer variables, except for the addition of an integer
(see Section 2.5.5.2). However, two pointers may be tested for equality in an IF statement — e.g.,
if zp # null
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 has been
typed in that can be decoded as integer or floating point, respectively.
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 one if there is
an error in the argument (e.g., if s is not a string).
string(var) converts var to type string.
One use of these functions is to control interactive input and output. Example 2.7 demonstrates
this for user-supplied input parameters for Young’s modulus and Poisson’s ratio.
The only arithmetic operation that is valid for string variables is addition; as demonstrated in
Example 2.7, this causes two strings to be concatenated. Table 2.2 identifies special characters
available in string manipulation.
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.7). Also, note the use of intrinsic function type( ), which identifies the type of
argument (see Section 2.5.4).
A FISH function can be 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. The following are some notes of caution.
1. The variables that are used in a function still exist even if the function is
redefined; only the code is deleted. Since variables are global, it is likely that
they are used elsewhere.
2. If a function is replaced by another of the same name, all calls to the old function
from existing functions are removed. All fishcall links to the replaced function
are removed.
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.
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 the scalar variable (dim), 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.
Array variables take any type (integer, float, pointer 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
Some restrictions apply to the use of array names in FLAC 3D command lines:
(1) the command PRINT fish prints the legend — array — if the corresponding
symbol is an array, together with the array dimensions;
(2) PRINT name (where name is a FISH array name) simply prints out the maximum
array indices;
(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 grav =
name, where name is a FISH array name); and
(4) PRINT name index prints the value stored in name (index).
WHILESTEPPING
If this statement appears anywhere within a user-defined function, then the function
is always executed automatically at the start of every FLAC 3D step. The WHILESTEP-
PING attribute can later be disabled with the use of the SET fishcall 0 remove command
(see Section 2.4.3).
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
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 3D’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
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
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 signaled, 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 3D variables, and so on). 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 between 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 mixture). 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. Similarly, both expressions may evaluate to pointers, but only
= and # tests are valid.
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.
COMMAND
ENDCOMMAND
FLAC 3D 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 3D commands within a FISH func-
tion. 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 definition may appear within a COMMAND – ENDCOMMAND pair,
and may itself contain the COMMAND statement. However, recursive calling is not
allowed and will produce an error message. A function that contains the WHILESTEP-
PING statement, or a function that is the subject of a fishcall, may contain the
COMMAND statement. However, this construction should be used with caution, and
avoided if possible.
Comment lines (starting with ;) are taken as FLAC 3D 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 3D commands coming from the function are not displayed to the
screen or recorded to the log file.
Synonym: END COMMAND
The following list contains all of the FLAC 3D commands that refer directly to FISH variables
or entities. There are many other ways FLAC 3D and FISH may interact; these are described in
Section 2.4.2.
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. The history
may be plotted in the usual way.
PLOT fish name
Items that invoke FISH functions that perform plotting (see Section 2.7.1) can be
added to a plot view. In the example, function name is taken as a plot item.
PRINT var
prints out the value of the FISH variable var. var is also executed (as well as
everything else that it calls) if it is a FISH function.
PRINT fish
prints out a list of FISH symbols, and either their current values or an indication of
their type.
PRINT fishcall
prints the current associations between fishcall ID numbers and FISH functions (see
Section 2.4.3).
SET fishcall n <remove> name
The FISH function name will be called in FLAC 3D from a location determined by
the value of the fishcall ID number n. The currently assigned ID numbers are listed
in Table 2.3. The optional keyword remove causes the FISH function to be removed
from the list when placed before the FISH function name.
In general, FLAC 3D and FISH operate as separate entities — FISH statements cannot be given as
FLAC 3D commands, and FLAC 3D commands do not work directly as statements in a FISH program.
However, the two systems may interact in many ways; some of the more common ways are listed
below.
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 3D’s calculation cycle,
or whenever a particular event occurs. (See Section 2.4.3 for a discussion on
fishcall.)
4. Use of function to control a run — Since a FISH function may issue FLAC 3D
commands (via the COMMAND statement), the function can be used to “drive”
FLAC 3D 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.
The primary way of executing a FISH function from FLAC 3D is to give its name as FLAC 3D input. In
this way, FISH function names act just like regular commands in FLAC 3D. 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 3D : a FISH symbol (variable or function
name) may be substituted anywhere in a FLAC 3D 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 radially graded mesh around a cylindrical tunnel) can be set up for any number
of elements in the mesh simply by changing two numbers in the SET command.
Several of the points made above are illustrated in Example 2.9: 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 3D input — they are all replaced
by symbols.
String variables may be used in a similar way, but their use is much more restricted compared to the
use of numerical variables. A FISH string variable may be substituted (a) wherever a filename is
required, or (b) as a parameter to the TITLE command. In these cases, single quotes are not placed
around the string, so that FLAC 3D can distinguish between a literal name and a variable standing
for a name. Example 2.10 illustrates the syntax.
The intrinsic function string( ) is described in Sections 2.2.7 and 2.5.4; it converts a number to a
string.
Another important method of using a FISH function is to control a FLAC 3D run or a series of
FLAC 3D operations. FLAC 3D 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 3D
commands. This approach is illustrated in Example 2.11, in which 8 complete runs are done, each
with a different value of friction angle.
For each run (i.e., execution of the loop), all grid variables are reset and the friction angle is redefined.
The results are summarized in a table in which the log of incremental displacement is plotted against
friction angle (Figure 2.1). The stability limit is seen to be about 65◦ . The table functions xtable
and ytable are described in Section 2.5.5.1.
FLAC3D 3.00
Step 4791
12:39:30 Fri Mar 25 2005
-0.8
Table
1 UnNamed
Linestyle
-2.399e+000 <-> -6.567e-001
-1.0
-1.2
-1.4
-1.6
-1.8
-2.0
-2.2
2.4.3 FISHCALL
FISH functions may be called from several places in the FLAC 3D program while it is executing.
The form of the command is
SET fishcall n <remove> name
Setting a fishcall causes the FISH function name to be called from FLAC 3D from a location deter-
mined by the value of ID number n. Currently, the ID numbers shown in Table 2.3 are assigned
(at present, they are all in the calculation cycle). The numbers indicate the position where fish-
call is located in the program. Note that ID numbers (in Table 2.3) 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).
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.
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.
The numbers listed in Table 2.3 are given symbolic macro names in file “FISHCALL.FIS,” the
contents of which are listed in Example 2.12. The symbolic names should be used in preference
to actual numbers, so that assignments may be changed in the future without the need to change
existing FISH functions.
The data file in Example 2.13 illustrates the use of a fishcall. Function rotation is called just before
the motion calculation in FLAC 3D (ID = 4) in order to apply x- and z-velocity components to rotate
a grid. This example tests the stress calculation in the large-strain mode; the σxx and σzz stress
components return to their initial values following a cyclic rotation of 30◦ . For this example, it is
necessary for FLAC 3D to perform geometry updates in every cycle; hence the SET geom rep = 1
command.
gp_extra(pnt,2) = atan2((gp_xpos(pnt)-xc),(zc-gp_zpos(pnt)))
pnt = gp_next(pnt)
endloop
end
set xc=0 zc=0
ini_coord
def rotation ; rotate about y-axis
tt=tt+delta_t
theta=0.5*amplitude*(1.0-cos(2*pi*freq*tt))
pnt = gp_head
loop while pnt # null
length = gp_extra(pnt,1)
angle = gp_extra(pnt,2)
xt = xc + length * sin(angle+theta*degrad)
zt = zc - length * cos(angle+theta*degrad)
gp_xvel(pnt) = xt - gp_xpos(pnt)
gp_zvel(pnt) = zt - gp_zpos(pnt)
pnt = gp_next(pnt)
endloop
end
set fishcall FC_XSTRESS rotation ; ... just before MOTION
fix x y z
ini sxx 1
set freq=1 delta_t=1e-3 amplitude=30
set large
hist nstep 2
hist tt
hist theta
hist zone sxx 1 1 1
hist zone syy 1 1 1
hist zone szz 1 1 1
set geom_rep = 1
def series
loop nn (1,10)
command
step 100
plot grid vel red axes black
endcommand
endloop
end
plot set cent -.02 .50 .50 size 3.4 mag 0.64
series
plot his 3 4 5 vs 1
fishcall 14 and fishcall 15 are user-defined functions that can be invoked by double-clicking with
the mouse on the selected plot items: surface, block, contour, block contour, stress tensor and
structural element recover plot items. The mouse position on the model is identified by the scalar
variables, mclickx, mclicky and mclickz. Example 2.14 illustrates the application of fishcall 14 and
15 to change material models by double-clicking with the mouse.
zid = z_id(zpnt)
ii = out(’RCLICK ’ + ’ ’ + ’zId = ’ + ’ ’ + string(zid))
command
m mohr range id zid ; Assign a model
endcommand
endif
end
;
leftdblclick
rightdblclick
;
set fishcall FC_LEFT_DC leftdblclick
set fishcall FC_RIGHT_DC rightdblclick
; At this point users can double click on the model with left and right
; mouse buttons and see what happens.
There are certain functions and variables that are built into FISH — the names of these entities must
be avoided when naming user-defined variables or functions. This section describes all pre-defined
entities. The entities are organized in the following categories: scalars, general intrinsic functions,
table functions and memory-access functions. In some cases, an entity is listed under more than
one category, as appropriate.
The variables listed in this category have a single value and are specifically related to internal
FLAC 3D 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.
The variable is of floating-point type unless otherwise noted.
crdt * creep timestep
crtime * creep time
dim = 3 (number of spatial dimensions) (integer)
dydt * dynamic timestep
dytime * dynamic time
fldt * fluid flow timestep
fluid ratio current unbalanced fluid flow ratio
fltime * fluid flow time
fos f current value of multiplier, F , used in SOLVE fos; see Sec-
tion 2.5.1.1 for more details
gp head pointer to the top of the gridpoint list
i head pointer to the top of the list of interfaces
large * = zero if small-strain mode is in operation; otherwise, large
is nonzero (integer)
mclickx current x-coordinate†
mclicky current y-coordinate†
mclickz current z-coordinate†
The FISH scalar fos f is the current F used in the SOLVE fos calculation. fos f is only non-zero
during cycling which is done as part of the fos solution; therefore fos f can be tested against zero to
determine if 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 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 Example 2.15, which writes successive values of F to an ASCII file — see Example 2.16.
new
gen zone brick size 5 5 5
model mohr
prop dens 1000 she 1e8 bu 2e8 fric 30 coh 3.5e4 tens 1e10
fix x y z range z = 0
set grav 10
;
def setup ; Initialize results file ...
array arr(1)
filename = ’result.out’
oo = open(filename,1,1)
arr(1) = string(0)
oo = write(arr,1)
oo = close
end
setup
;
def qqq
array arrsav(500)
whilestepping ; 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(filename,0,1) ; Read in current results
oo = read(arr,1)
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(filename,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 file MyFoS.sav
return
The variables listed in this category have a single value and are not specifically related to FLAC 3D ;
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 state-
ment causes a complete update of all grid-related quantities.
The same update is done every 10 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 re-
turned number by a factor and adding an offset.
null link-list terminator; it is of type pointer
pi π
step current step (cycle) number
The variables listed in this category are specifically related to internal FLAC 3D data structures. The
variables are divided into three groups: gridpoint variables, zone variables and interface variables.
The reserved names in each group refer to variables that require the memory address of the associated
object to be specified in parentheses immediately following the name. Functions are provided for
each group to locate the appropriate memory address.
The variable names must be spelled out in full in FISH statements; they cannot be truncated as in
FLAC 3D commands. All model variables are of floating-point type unless declared otherwise. An
asterisk (*) denotes that the variable can be modified by a FISH function; otherwise, its value may
only be tested.
The memory address of a gridpoint or zone, located at or near a global coordinate (x, y, z) in space,
may be found using the following functions.
p gp = gp near(x, y, z) address of gridpoint closest to (x, y, z)
p z = z near(x, y, z) address of zone closest to (x, y, z)
p gp = gp nearall(x, y, z) address of gridpoint closest to (x, y, z), including null
zones
p z = z nearall(x, y, z) address of zone closest to (x, y, z), including null zones
These functions are time-consuming, as the entire grid must be scanned. Alternatively, the list of
gridpoints or zones may be scanned by using headers gp head or zone head, respectively, and the
next-item pointers, gp next( ) and z next( ).
The memory address of a gridpoint or zone can also be found given the ID number for the gridpoint
or zone. Note that these functions are time-consuming.
p gp = find gp(id) address of gridpoints with ID number id
p z = find zone(id) address of zone with ID number id
Note 1: The variables gp xfix, gp yfix and gp zfix can be set or re-
trieved by a user FISH function, and correspond to fix condi-
tions in the x-, y- or z-directions, respectively. Any nonzero
integer sets the fix condition, and zero removes the fix condi-
tion. On retrieval, a fix condition is signalled by the integer
1 (and 0 for a free condition). Note that APPLY commands
relating to motion override fix conditions set in a user FISH
function. For example, if a gridpoint is in the range of an AP-
PLY yvel command, then setting gp yfix to zero does nothing;
the implied fix condition is restored before cycling.
Note 2: Forces may be applied to gridpoints by user-written FISH
functions using the variables gp xload, gp yload and
gp zload. These loads are in addition to loads derived from
the APPLY command and other sources of body forces, such
as gravity. The variables may be both changed and inspected
by a FISH function. If not set by a user FISH function, these
additional loads default to zero. They are not changed by
FLAC 3D in any way, and retain indefinitely whatever values
are set by the user.
2.5.3.2 Zone Variables
Model String
Contents
transversely isotropic elastic model anisotropic
Burger-creep burger
Cam-clay model cam-clay
viscoplastic power cpower
Burger-creep viscoplastic cviscous
creep model for crushed salt cwipp
double yield doubleyield
Drucker-Prager model drucker
linear elastic model elastic
Finn liquefaction model finn
Mohr-Coulomb model mohr
null model null
orthotropic elastic model orthotropic
power law creep model power
plastic WIPP creep model pwipp
strain-hardening/softening model ssoftening
softening ubiquitous-joint model subiquitous
ubiquitous-joint model ubiquitous
viscous creep model viscous
WIPP creep model wipp
A zone in FLAC 3D is comprised of tetrahedral sub-zones, and each of them has a member variable
that maintains its failure state. The member variable has 16 bits that can be used to represent a
maximum of 15 distinct states. Some of the states that are used by built-in constitutive models in
FLAC 3D are given in Table 2.4.
These named states in Table 2.4 are used by these built-in models to update the tetrahedral sub-zone
state.
1. Drucker-Prager
2. Mohr-Coulomb
3. Strain-Hardening/Softening
4. Ubiquitous-Joint
5. Bilinear, Strain-Hardening/Softening Ubiquitous-Joint
6. Double-Yield
7. Cam-Clay (uses the first two named states only)
8. Finn
9. WIPP-Creep Viscoplastic model
The numbers listed in Table 2.4 are given symbolic FISH names in the file “FAILURESTATES.FIS,”
the contents of which are listed in Example 2.17. The symbolic names should be used in preference
to actual numbers, so that assignments can be changed in the future without the need to change
existing FISH functions.
The data file in Example 2.18 illustrates the process of determining failure state of zones in a model
using the FISH function z state.
The following FISH intrinsics allow state information (e.g., zone stresses, zones state flags, gridpoint
vectors, etc.) to be saved to a file and restored later. A notable use for the functions is to save and
restore the full sub-zone stress tensors when making multiple simulations starting from exactly
the same state (note that the regular stress intrinsics (e.g., z sxx) perform averaging of sub-zone
stresses).
z statesave(p z)
z staterest(p z)
gp statesave(p gp)
gp staterest(p gp)
These functions return an integer, where 0 denotes successful operation; otherwise, an error code is
returned, corresponding to a FISH I/O error. Other errors result in error messages being displayed
during execution.
The “save” versions of the functions write state information to a FISH I/O file, and the “rest” versions
read the information from a previously written FISH I/O file, and restore the state. Information for
either zones or gridpoints, or both, can be saved and restored, using the prefix z or gp , respectively.
Before executing any of these functions, a FISH binary file (i.e., a “FISH mode file”) must be
open, either for reading (for staterest) or for writing (for statesave). See Section 2.7.2 for more
information on FISH I/O. Information for any number of zones or gridpoints may be saved, but
exactly the corresponding numbers of zones and gridpoints must be addressed during the restore
operation.
Example 2.19 illustrates the use of the save/restore functions. Stress and velocity states are restored,
after being erased.
p_z = z_next(p_z)
endLoop
p_gp = gp_head
loop while p_gp # null
ret = gp_statesave(p_gp)
if ret # 0
oo = out(’ error in gp statesave = ’+string(ret))
exit
endif
p_gp = gp_next(p_gp)
endLoop
oo = close
end
def get
oo = open(’state.bin’,0,0)
p_z = zone_head
loop while p_z # null
ret = z_staterest(p_z)
if ret # 0
oo = out(’ error in staterest = ’+string(ret))
exit
endif
p_z = z_next(p_z)
endLoop
p_gp = gp_head
loop while p_gp # null
ret = gp_staterest(p_gp)
if ret # 0
oo = out(’ error in gp staterest = ’+string(ret))
exit
endif
p_gp = gp_next(p_gp)
endLoop
oo = close
end
model elas
ini sxx 0 grad 1 2 3
ini yvel 0 grad -1 -2 -3
put ; Remember the original state
pri zone str gp vel
ini sxx=0 yvel=0 ; Erase some variables
pri zone str gp vel ; Confirm zone & gp data erased
get ; Restore the original state
pri zone str gp vel ; Zone & gp data restored
There are eight FISH zone “variables” — ssr, ssi, vsr, vsi, fsr, fsi, fri, frr — that give user-written
functions access to zone strains, strain rates and rotation 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 of address p z:
z ssi(p z) maximum shear-strain increment
z ssr(p z) maximum shear-strain rate
z vsi(p z) volumetric strain increment
z vsr(p z) volumetric strain rate
The following two functions provide all the tensor components, rather than invariants, providing
six components in the array arr, which the user must declare beforehand, and which must have at
least six elements (the function itself returns a zero).
z fsi(p z, arr) full strain-increment tensor
z fsr(p z, arr) full strain-rate tensor
z fri(p z, arr) full rate of rotation increment tensor
z frr(p z, arr) full rate of rotation tensor
The components in arr are ordered in the following way, 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
index 5 yz
index 6 xz
The computation of strain rate is identical to that performed by FLAC 3D when it applies constitutive
relations to a zone (see Section 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; the
literature contains many different formulations for strain when large displacements are involved.
The conscientious user may wish to use only the function z 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 for the zones of interest only. Also, since each function takes
about the same time to execute, it is better to use z fsr or z fsi if more than one strain component is
needed for a zone.
Example 2.20 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 = z fsr(pnt,ar)
dum = z fsi(pnt,ai)
The second strain invariants for the strain-rate tensor and the strain-increment tensor are calculated
from the component values for each zone, and are stored in zone extra arrays 2 and 3, respectively.
The volumetric strains are also calculated for the two tensors and stored in zone extra arrays 4 and
5. These values are then shown to match those given with the PRINT zone strain command.
i next(p i) address of the pointer to the next interface in the list (pointer)
The following variables find the first memory address in the list of interface elements and interface
nodes.
i elem head(p i) address of the first element in the interface — the list pointer
is denoted by p ie below (pointer)
i node head(p i) address of the first node in the interface — the list pointer is
denoted by p in below (pointer)
Interface Element Variables
ie area(p ie) area of the interface element
ie fhost(p ie) face ID number (1-6) to which the interface element is at-
tached (integer) (see Section 1.1.4 in the Command Refer-
ence)
ie id(p ie) ID of the interface element (integer)
ie join(p ie, int) address of the adjacent interface joined across edge int,
where int = 1, 2 or 3 (pointer)
ie next(p ie) address of the next interface element in the list (pointer)
ie norm(p ie, dof) normal vector component in the direction specified by dof —
dof takes the value 1 for the x-direction, 2 for the y-direction
or 3 for the z-direction
ie vert(p ie, dof) address of vertex associated with interface element, where
int = 1, 2 or 3 (pointer)
ie zhost(p ie) address of the zone to which the interface element is attached
(pointer)
in sdisp(p in, dof) * interface node relative shear displacement vector in the
direction specified by dof — dof takes the value 1 for the
x-direction, 2 for the y-direction or 3 for the z-direction (the
shear stress is not changed)
in sstr(p in, dof) * shear-stress vector component in the direction specified
by dof — dof takes the value 1 for the x-direction, 2 for the
y-direction or 3 for the z-direction
in tweight(p in, int) weighting factor for vertex int (1-4) of the zone face with
which the node is in contact (see Section 1.1.4 in the Com-
mand Reference)
in vel(p in, dof) * velocity of node in the direction specified by dof — dof
takes the value 1 for the x-direction, 2 for the y-direction or
3 for the z-direction
in zhost(p in) address of the zone to which the interface node is attached
(pointer)
in ztarget(p in) address of the zone with which node is in contact (pointer);
returns null, if no contact
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 (except for error, which is placed on the left-hand
side), 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). NOTE: a must be greater
than 0.
and(a,b) bit-wise logical and of a and b
asin(a) arc-sin of a (result is in radians). NOTE: a must be greater
than 0.
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)
error string
This function causes an error condition if a value is assigned
to it. FISH function processing (and command processing)
stops immediately. The message reported is string. This
function must be used for assignment only (string = error is
not allowed).
exp(a) exponential of a
fc arg(n) passes arguments to FISH functions where n is an argument
number.
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.
get mem(nw) gets nw FISH-variable objects from FLAC 3D’s memory
space and returns the address of the start of the contiguous
array of objects (see Section 2.5.5.2).
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 may appear on either side of an assignment (= sign). They act partly as
functions and partly as arrays.
2.5.5.1 Tables
The functions table, xtable, ytable and table size allow FISH functions to create and manipulate
FLAC 3D tables, which are indexed arrays of number pairs used in several of FLAC 3D’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 3D 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 found by in-
terpolation, corresponding to the given value of x. The value
of x should lie between two consecutive stored x-values, if
the results are to be meaningful. An error is signaled if table
n does not exist.
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 3D 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 signaled if table n
does not exist, or if sequence number s does not exist.
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!
2.5.5.2 Special Functions to Access Memory Directly
The functions get mem( ), lose mem( ) and mem( ) manipulate user-defined structures made up of
blocks of FISH-type variables (i.e., variables that may be of type integer, floating point, string or
pointer). Although the addresses used to access these variables are similar to the addresses of the
built-in variables of the host, there is no way to convert between the two (since the host program
uses data structures of arbitrary size). Communication between the two structures is via the values
of the variables.
get mem(n) This function gets n FISH-variable objects from the host’s
memory space and returns the address of the start of the
contiguous array of objects.
lose mem(n,ad) This function returns n FISH-variable objects to the host.
The parameter ad is the address of the start of the array of
objects; there is no checking done to verify that ad is a valid
address. The returned value is undefined.
mem(ad) This function may be used either as a source or destination
(i.e., on the right- or left-hand side of an expression):
var = mem(ad) The value of the FISH-variable at address
ad is transmitted to the regular FISH vari-
able var (together with the type).
mem(ad)=var The value and type of the regular FISH
variable var is placed in the FISH-variable
at address ad.
It is the user’s responsibility to check that the addresses given
contain valid FISH variables. During execution, an error
message is given if ad is not of type pointer.
Access to elements of an array of FISH variables is via the addition operator; no other arithmetic
operation is allowed on a pointer. When an integer n is added to a pointer, the pointer then points
to a variable that is higher by n positions in the array. For example, suppose we create a 10-object
array:
head = get mem(10)
and so on. The minus operator is not allowed; we can add a negative integer if we want to go
backward in an array. The last item in a linked list is denoted by the intrinsic pointer variable null;
the integer zero should not be used.
All direct manipulation of FLAC 3D’s memory should be done with great caution; only experienced
programmers should use the memory functions. As an example in the use of direct memory
manipulation, Example 2.21 does an insertion sort on twenty random floating-point numbers stored
in a linked list. A structure of two FISH variable objects is created for each generated random
number, the number being stored in one of these variables. The other variable is given the address
of the next such structure, with the final structure containing a null value, thus forming a linked list.
Each new random number is compared against values in the list and inserted at the appropriate
point. This insertion consists in reassigning the address values contained in the previous item to
the address of the new item.
endif
mem(new+1) = number
endloop
;--- now scan list, and print out ---
count = 1
ad = head
loop while ad # null
if count < 10 ;a trick to line up
nn = string(count) ;numbers in columns
else
nn = string(count)
endif
ii = out(nn+’ ’+string(mem(ad+1)))
count = count + 1
ad = mem(ad)
endloop
end
inserter
The FISH functions that support the structural-element logic are described in this section. The
functions are described and listed in tables, the columns of which indicate, respectively:
1) “type” — the function return type (from Table 2.5);
2) “function name” — the function name and the type of any parameters; and
3) “modifiable” — the read/write status of the function. A “yes” in this column
means that the value may be modified. A blank entry means that it may only
be tested.
If all entries for a column of any table would be blank, then that column is not included in that table.
type description
FLT floating-point number
INT integer number
STR string
PTR pointer of any type
ANY any type, except array (unless otherwise noted in text)
S PTR pointer to any SEL type
SB PTR pointer to a beamSEL
SC PTR pointer to a cableSEL
SP PTR pointer to a pileSEL
SS PTR pointer to a shellSEL
SG PTR pointer to a geogridSEL
SL PTR pointer to a linerSEL
SST PTR pointer to a shell-type SEL (shell, geogrid, liner)
ND PTR pointer to a node
LK PTR pointer to a link
The functions are grouped into the following categories, each of which is described in its own
subsection: general, structural element, structural-element node and structural-element link. The
structural element functions are further subdivided into those that operate upon the various SEL types
and the stress-recovery functions that operate upon shell-type SELs. Most functions in each group
(except for the general group) require that the memory address of the associated data structure
be passed to them as a parameter. Support functions are provided for each group to locate the
appropriate memory address. Also, the entities of each group are stored in separate null-terminated
linked lists. All entities of these groups can be obtained by scanning through the appropriate linked
list. Support functions (linked-list header and next-item field of each entity) are provided for these
groups.
For example, the functions that operate upon nodes require that the memory address of a node be
passed to them as a parameter. The memory address of the node with an ID of id is returned
by the support function nd find(id); thus, the reference x-position of that node is returned by
nd pos(nd find(id),2,1). Also, all nodes are stored in a linked list with a header of nd head. The
data associated with each node contains the next-item field nd next. Example 2.22 shows how to
print out the ID and reference position of each node in the model by scanning through the linked
list of nodes. (Note that the node ID does not, in general, correspond with the order of the node in
the linked list.)
The general support functions provide appropriate memory addresses (in the form of linked-list
headers and address-finding functions) of the various structural-element data structures. All of the
structural-element general support functions are listed in Table 2.6.
The structural-element functions operate upon the SEL data structure. General support functions
that provide information pertinent to all SEL types are listed first in Table 2.7. Then, functions
for each SEL type are provided in their own section and grouped into the categories of proper-
ties and responses. Finally, functions supporting stress recovery for shell-type SELs are listed in
Section 2.6.2.7. SEL memory addresses can be obtained from the support functions in Table 2.6.
SEL Support Functions
var = s extra( sp ) The value and type of the FISH-variable in the s extra struc-
ture of SEL sp is assigned to the regular FISH variable var.
s extra( sp ) = var The value and type of the regular FISH variable var is as-
signed to the s extra variable of SEL sp.
s id( sp ) ID number of SEL sp. All SELs that comprise a particular
entity will possess the same ID number — e.g., all cableSELs
that comprise cable 6 will have an ID of 6.
s mark( sp ) mark flag. Note that the SEL logic may modify this flag
during command processing, cycling and plotting.
s next( sp ) address of next SEL in the global linked-list of SELs; last
SEL in the list returns null
s node( sp, i ) address of node i of the SEL (i in range 1 to s numnd) where
i is the order in nodal-connectivity list. Also see s conn.
s numnd( sp ) number of nodes (2 or 3) of the SEL
s type( sp ) SEL type. Return value {1, 2, . . . , 6} denotes: beamSEL,
cableSEL, pileSEL, shellSEL, geogridSEL or linerSEL, re-
spectively; returns 0 if type is unknown.
SEL Property Functions
s dens( sp ) density
s lsys( sp, v, dof ) local coordinate system of SEL (dof-component of unit vec-
tor in direction v; v ∈ {1, 2, 3}; dof ∈ {1, 2, 3})
Figure 2.2 Sign convention for forces and moments at the ends of a beam-
SEL or pileSEL (ends 1 and 2 correspond with order in nodal-
connectivity list, and all quantities are drawn acting in their pos-
itive sense)
sc length( cp ) length
sc volume( cp ) volume (cross-sectional area times length)
Cable Property Functions (2)
Stress-Recovery Functions
nd ssysx( np, x, y, z ) orients surface system of node np such that the x-direction
is aligned with the projection of the surfx vector (x, y, z)
onto the normal plane, which is defined by the z-direction.
This operation can only be performed upon nodes that have
a valid surface system (to ensure that the z-direction always
corresponds with the average normal direction of at least one
of the shell-type SELs using the node). Nonzero return value
indicates success.
nd svalid( np ) surface system validity flag; nonzero value denotes that the
surface system for node np is valid. The surface system can
be made valid by issuing a SEL recover surface command.
sst depfac( sp ) depth factor, F , at which stresses have been recovered. The
depth equals F t/2, where t is shell thickness. F equal to
+1/-1 corresponds with the outer/inner shell surface (outer
surface defined by positive shell z-direction), and F = 0
corresponds with the shell midsurface. The depth factor can
be modified by the SEL recover stress command.
sst pstr( sp, l, d ) principal stress at location l (l ∈ {0, 1, 2, 3} denotes cen-
troid, node-1, node-2 or node-3, respectively — see s conn
and s node; component d ∈ {1, 2, 3} denotes {σ1 , σ2 , σ3 }).
Compressive stresses are negative and σ1 ≤ σ2 ≤ σ3 . The
stresses correspond with a depth in the shell that is set by
the SEL recover stress command and can be queried by
sst depfac.
sst sres( sp, l, d ) stress resultant at location l (l ∈ {0, 1, 2, 3} denotes cen-
troid, node-1, node-2 or node-3, respectively — see s conn
and s node; component d ∈ {1, 2, . . . , 8} denotes {Mx , My ,
Mxy , Nx , Ny , Nxy , Qx , Qy }). Stress resultants are expressed
in the surface system — see the SEL recover surface com-
mand.
sst sresvalid( sp ) stress resultant validity flag; nonzero value denotes that
stress resultants are valid. Check this flag before querying
stress resultants.
sst str( sp, l, d ) stress at location l (l ∈ {0, 1, 2, 3} denotes centroid, node-1,
node-2 or node-3, respectively — see s conn and s node;
component d ∈ {1, 2, . . . , 6} denotes {σxx , σyy , σzz , σxy ,
σzy , σzx }). Stresses are expressed in the global system.
The stresses correspond with a depth in the shell that is set
by the SEL recover stress command and can be queried by
sst depfac.
The node functions operate upon the node data structure. The functions are grouped into the
categories of support, property and response. Node memory addresses can be obtained from the
support functions in Table 2.6.
Node Support Functions
var = nd extra( np ) The value and type of the FISH-variable in the nd extra struc-
ture of node np is assigned to the regular FISH variable var.
nd extra( np ) = var The value and type of the regular FISH variable var is as-
signed to the nd extra structure of node np.
nd id( np ) ID number of node np. Each node has a unique ID number.
nd link( np ) link associated with node np. Returns null, if no link is
associated with the node.
nd mark( np ) mark flag. Note that the SEL logic may modify this flag
during command processing, cycling and plotting.
nd next( np ) address of next node in the global linked-list of nodes; last
node in the list returns null
The link functions operate upon the link data structure. The functions are grouped into the categories
of support, property and response. Link memory addresses can be obtained from the support
function in Table 2.6 or from the nd link function in Table 2.33.
Link Support Functions
lk target( lp ) target ID. Returns the ID number of the link target. For a
node-to-node link, the target is a node; for a node-to-zone
link, the target is a zone — see lk type, nd find and find zone.
lk type( lp ) link type. Return value {1, 2} denotes: node-to-node or
node-to-zone link, respectively.
lk usedby( lp ) SEL entity using this link. Return value {1, 2, . . . , 6} de-
notes: beam, cable, pile, shell, geogrid or liner, respectively.
May also return 0 to indicate that link conditions have been
modified and no longer correspond with those set during
SEL creation and positioning. Returns 0 for node-to-node
links.
Link Property Functions
Properties are only available for directions with linear deformable or normal-yield deformable
attachment conditions — see functions starting with lk ld and lk nd, respectively. Other properties
stored at links must be obtained from the SEL that uses the link — for example, grout properties of
cables are accessed by the functions in Table 2.14.
This section covers extensions to FISH. While these extensions add to the power and capability
of FISH, they are not required for general operation. Each subsection describes the complete
functionality of the particular extension and includes examples.
The set of FISH functions described in this section may be used to create user-defined plot items.
Arguments denoted by v, v1 or v2 are user-defined arrays with at least 3 elements. Each array serves
as a 3D vector.
draw circle(v, rad)
A circle is drawn at the location given by the coordinate vector, v, with
radius, rad. The vector normal to the plane of the circle points towards the
viewer.
draw line(v1, v2)
A line is drawn from location vector v1 to location vector v2.
draw poly(arr2, count, closure)
This function draws an open or closed polygon, consisting of (integer) count
points, in space. The variable arr2 must be a 2-dimensional array, where
the first index corresponds to the number of spatial components, and the
second index to sequential points. For example, in a 3-dimensional code,
the statement
array fred(3, 10)
would allow 10 3D coordinates to be stored and then plotted with the state-
ment
status = draw poly(fred, 10, 1)
The third argument, closure, must be an integer: 0 denotes that the polygon
is open; 1 denotes that it is closed.
draw string(v, s)
A string, s, is written at the location corresponding to the coordinate vector,
v. If s is not of type string, then an error results.
would allow 10 3D coordinates to be stored and then plotted with the state-
ment
status = fill poly(fred, 10)
line to(v)
The graphics current point is moved to the coordinate specified by v, drawing
a line from its previous position.
move to(v)
The graphics current point is moved to the coordinate specified by v.
set color(i)
The color index for subsequent plot objects will be set to the integer i. The
actual color is set with the PLOT command as usual.
set dash pattern(i)
sets the dash pattern type to i, where i varies from 0 to 6, with 0 giving a
solid line.
set line width(i)
The width of any subsequent line is set to i; 0 gives the thinnest line.
set fontsize(x)
A multiplier x is applied to the default font size — e.g., x = 0.5 will result
in a smaller font.
set RGB(r, g, b)
This command sets the RED BLUE GREEN values — r, g, b are of type
float in the range 0.0 to 1.0.
The following notes apply to all plot functions.
1) Plotting coordinate units are the same as the model units, using the current transformations
from model to screen units.
2) A user-written FISH function that contains calls to the plot functions listed above may
be named as a regular plot item (using the PLOT add fish name command, where name
is the name of the user-written function). The new plot item may be used anywhere that
the built-in plot items are expected, provided it is preceded by the keyword fish.
The use of the various plot functions is illustrated in Example 2.23.
The set of FISH functions described in this section enable data to be written to, and read from, a
file. There are two modes: 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 the following values:
0 file opened for reading; file must exist
1 file opened for writing; existing file will be overwritten
2 file opened for writing; existing file will be appended to
Parameter mode must be an integer with one of the following 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 80 characters per line is allowed.
2 sets binary read mode, whereby any file is opened for reading
in binary mode.
The returned value denotes the following 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)
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 exactly match 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.
If a file is opened in mode = 2, then n bytes are read into the array ar. If
less than n bytes exist, then the actual number is returned. The array must
have at least n elements.
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 is derived from a file.
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.
pre parse(s, i)
This function scans the string s and returns an integer value according to
the type of the ith item, as follows.
0 missing item
1 integer
2 float
3 string missing (unable to interpret as int or float)
Example 2.24 illustrates the use of the FISH I/O functions.
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
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 3D Version 3.0, FLAC Version 5.0
and PFC 2D Version 3.1 and PFC 3D Version 3.1. It is possible to pass data between two or more
instances of the same code (e.g., two instances of FLAC 3D ), but the main use is anticipated to be
coupling of dissimilar codes such as FLAC 3D and PFC 3D. An example is provided in Section 2.8.1
of such a coupling.
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. 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.
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.
sclose(ID)
Channel ID is closed.
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 or 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.
Data have been passed both ways between the two code instances. A more useful example is given
below, in Section 2.8.1.
One way of adding the effects of fluid interaction to a granular assembly modeled with PFC 3D
(Itasca 1999) is to represent the assembly as an equivalent porous continuum, for the purpose of
calculating the flow and pressure fields. Accordingly, in this example, FLAC 3D is used to determine
the fluid flow field in a box containing a uniform, isotropic material, and saved on file “FF.SAV.”
Figure 2.3 shows the results of executing file “FF.DAT,” in which fluid under pressure enters along
the lower part of the left wall, and exits along the right part of the upper wall (specified by FIX pp
boundary conditions).
FLAC3D 3.00
Step 2000 Model Perspective
12:41:32 Fri Mar 25 2005
Center: Rotation:
X: 1.000e+001 X: 0.000
Y: 2.500e+000 Y: 0.000
Z: 5.000e+000 Z: 0.000
Dist: 5.780e+001 Mag.: 1
Ang.: 22.500
An assembly of 1000 spheres is created with PFC 3D, and packed within an identical box composed
of walls, using the data file “PF.DAT,” and saved on file “PF.SAV.”
Both models are restarted with FLAC 3D and PFC 3D, respectively, running both codes simultaneously
on the same processor, and the pressure gradients from FLAC 3D are passed via socket I/O to PFC 3D,
which converts them to body forces on appropriate particles. This operation is executed using the
following procedure. After starting both codes, file “FFR.DAT” is input to FLAC 3D, which then
waits for a connection. Then “PFR.DAT” is input to PFC 3D, and data is exchanged between codes,
and a few steps are executed in PFC 3D, resulting in the plot shown in Figure 2.4, which illustrates
that the particles are starting to move in response to the imposed fluid pressure field imported from
FLAC 3D.
PFC3D 3.10
Settings: ModelPerspective
Step 1510 12:53:43 Fri Mar 25 2005
Center: Rotation
X: 1.000e+001 X: 0.000
Y: 2.506e+000 Y: 0.000
Z: 4.999e+000 Z: 0.000
Dist: 6.418e+001 Mag.: 1
Ang.: 22.500
Ball
Velocity
Maximum = 2.662e-002
Linestyle
The initial problem setup performed by files “FF.DAT” and “PF.DAT” is quite straightforward, but
the subsequent operations may require some explanation. The file “FFR.DAT” opens channel 1,
and sends some basic data — the number of zones in each box dimension. Then — for each zone
— the centroid coordinates and the three components of the pressure gradient are sent, the latter
being computed from
∂P qi
= (2.1)
∂xi k
where qi is the specific discharge vector and k is the (uniform) permeability given in the initial data
input.
In PFC 3D, the file “PFR.DAT” initially reads the zone-number data from channel 1, and sets up
appropriately sized arrays for the pressure gradient data. Then these data are read from the channel,
and used to apply body forces to each particle, according to the following formula:
4 ∂P
Fi = π R3 (2.2)
3 ∂xi
Note that the example is incomplete, and involves simplifications, for the sake of clarity. In partic-
ular, the following changes are suggested if the approach is to be used in a realistic simulation.
1. The problem should be better parameterized (and these parameters exchanged
between codes), to avoid assumptions (such as box coordinates and boundary
conditions).
2. In the example, the data flow is in one direction. For a complete model,
porosity data should be passed back from PFC 3D to FLAC 3D, and the flow
solution repeated as the particle model deforms, using — for example — an
empirical relation to derive local permeability values from porosity.
3. The pressure gradient used in the PFC 3D model by each sphere is the nearest
zone value. A more accurate approach would be to interpolate the gradient
between several zones surrounding a given particle, if the particle’s centroid
is not located exactly at a zone’s centroid.
4. Parameter studies should be made on the effect of FLAC 3D zone sizes compared
to PFC 3D particle sizes, keeping in mind the intent of the flow calculation
to represent the average pressure gradient over several particles. Thus, the
assumption of homogeneity (in the flow calculation) is only valid when many
particles are represented within each zone.
2.9 Reference
Itasca Consulting Group, Inc. PFC3D (Particle Flow Code in 3 Dimensions), Version 3.1. Min-
neapolis: ICG, 2005.