I am new to FLAC 3D and to FISH and although my questions might sound dumb, they are getting me absolutelly stuck. I am trying to simulate a triaxial compression of a 10 x 10 x 10 zones brick. I would like to record stresses and strains for all zones through each calculation step. I am not being able to see the brick deform in the plot, nor generate histories with my code. Can anybody, please, help me? I am using two files, “Record.dat” and “Test.dat”.
Record.dat:
fish define record_quantities
global stress_xx = zone.stress.xx(::zone.list)
global stress_yy = zone.stress.yy(::zone.list)
global stress_zz = zone.stress.zz(::zone.list)
global stress_xy = zone.stress.xy(::zone.list)
global stress_xz = zone.stress.xz(::zone.list)
global stress_yz = zone.stress.yz(::zone.list)
global strain_xx = zone.strain.inc.xx(::zone.list)
global strain_yy = zone.strain.inc.yy(::zone.list)
global strain_zz = zone.strain.inc.zz(::zone.list)
global strain_xy = zone.strain.inc.xy(::zone.list)
global strain_xz = zone.strain.inc.xz(::zone.list)
global strain_yz = zone.strain.inc.yz(::zone.list)
end
fish history name "sig_xx" stress_xx
fish history name "sig_yy" stress_yy
fish history name "sig_zz" stress_zz
fish history name "sig_xy" stress_xy
fish history name "sig_xz" stress_xz
fish history name "sig_yz" stress_yz
fish history name "eps_xx" strain_xx
fish history name "eps_yy" strain_yy
fish history name "eps_zz" strain_zz
fish history name "eps_xy" strain_xy
fish history name "eps_xz" strain_xz
fish history name "eps_yz" strain_yz
Test.dat:
model new
model large-strain on
;zone geometry-update 1 ;For large strains
model title "Test"
zone create brick size 10, 10, 10 ...
group "Model"
zone face skin
zone cmodel assign mohr-coulomb range group "Model"
zone property density 1.8 young 50000 poisson 0.25 friction 30, ...
cohesion 15 range group "Model"
program call "Record"
[record_quantities]
zone gridpoint initialize velocity (0,0,0)
zone gridpoint initialize displacement (0,0,0)
zone initialize stress xx -100 yy -100 zz -100
zone face apply stress-normal -100 range group "South" or "North"...
or "West" or "East"
zone face apply velocity-z 0 range group 'Bottom'
;zone face apply velocity-z -1e-6 range group 'Top' ; not what I want to do
zone face apply stress-normal -200 range group "Top" or "Bottom"
; This part of the code represents the boundary conditions that would be applied
; to a centrifuge model
;zone face apply velocity-z = 0 range group "Bottom"
;zone face apply velocity-y = 0 range group "South"
;zone face apply velocity-y = 0 range group "North"
;zone face apply velocity-x = 0 range group "West"
;model gravity (0, 0, -9.807)
history interval 10
model solve
model save "Test"
history export 'sig_zz' vs 'eps_zz' table 'test'
You are attempting to assign a single global symbol (e.g. stress_xx) many different values with an iterative type / split argument (::). Essentially you are trying to assign 10x10x10=1000 values to one symbol and I think you are only going to get the last (probably the 1000th zone’s) value assigned to that symbol which might well be zero. You would need to create a unique global variable name for each zone and history (e.g. global stress_xx_1 = zone.stress.xx(zone.find(1)) …)
Then you need to add a fish callback to your “record_quantities” to instruct FLAC to actually run that function and update the values at a certain interval (in your case matching the history interval of 10). Otherwise it will not update the values and they will all stay zero or null.
Alternatively you can make the function reference itself by giving it the same name as one of the global symbols (e.g. fish define stress_xx). I think the examples in the manual use this approach without explaining it.
I think you should rethink your approach however. You’re going to end up with 12000 histories to store in memory. I think it would be more prudent to consider using contour plots of stress and displacement to check if your model is working as you expect.
You can also turn on the recording of results for your to record the evolution stress and displacements to separate files that can be restored after the model has been saved.
The best approach in my opinion is to avoid the use of histories altogether and rather use tables instead. Let us know if you need more help!
Thank you very much for answering. I still have a few questions, though. I know my questions are very basic, but they are really keeping me from progressing.
Wouldn’t it be possible to make this variable “stress_xx” a list of the stresses in each zone? I will need to operate the values in a different program after retrieving them to do the analysis I want to do.
What do you mean by having the function referencing itself? I don’t understand how that works.
Is there any example of the use of these contour plots you’re aware of? Also, how do I turn on recording of results? Will this allow me to retrieve stresses, strains, strain rates, displacements and velocities for each step and each zone?
I know this is a lot of questions. I really hope you can help me.
By the function referencing itself I mean that the name of the fish function, one of the global variables inside it, and one of the history references are the same.
Look at the example in the reference docs “Undrained Triaxial Test with NorSand Model” where the fish function is called q1, one of the global variables is also called q1 and the first history named “1” also refers to q1. This self-referential strategy ensures that all the variables q1, p1 and eps_a1 are updated each time the history is recorded.
; Undrained Triaxial Test with NorSand Model
[global _z1 = zone.near(0.5,0.5,0.5)]
fish define q1
local sxx = zone.stress.xx(_z1)
local syy = zone.stress.yy(_z1)
local szz = zone.stress.zz(_z1)
global q1 = sxx - szz
global p1 = -(sxx+syy+szz)/3. - zone.pp(_z1)
global eps_a1 = -gp.disp.z(gp.near(1,1,1))*100. ; axial strain (%)
end
;
fish history name '1' q1
fish history name '2' p1
fish history name '3' eps_a1
;
history interval 50
The example can be modified slightly to make it more explicit what is happening by using a fish callback as follows:
[global _z1 = zone.near(0.5,0.5,0.5)]
fish define results
local sxx = zone.stress.xx(_z1)
local syy = zone.stress.yy(_z1)
local szz = zone.stress.zz(_z1)
global q1 = sxx - szz
global p1 = -(sxx+syy+szz)/3. - zone.pp(_z1)
global eps_a1 = -gp.disp.z(gp.near(1,1,1))*100. ; axial strain (%)
end
;
fish callback add [results] -100 interval 50
;
fish history name '1' q1
fish history name '2' p1
fish history name '3' eps_a1
;
history interval 50
These two examples achieve the same result, but there are subtle differences as to when in the calculation sequence the values are updated.
The application above is really only suited to simpler applications. Your specific case is more intensive. I therefore recommend skipping this method and recording of results as well as this would lead to many many files to contend with. It is really only useful to me in troubleshooting.
I’m a Geotechnical Engineer, not a programmer, so I’m sure there are more efficient or elegant ways to do this. That said, creating a list for the stresses or strains in each zone is possible, but you’d still end up with 10x10x10x12 = 12000 lists to manage individually. See the ‘list utilities’ section in the reference docs for more details.
One approach is to write a FISH function that loops through each zone and records the values into tables, lists, or arrays. Arrays are efficient but require pre-defined dimensions, which isn’t ideal if the number of history points varies. Lists are more flexible since they allow appending values, but handling them can get tedious. My preference is using tables—they’re essentially 2D arrays, can be appended, and are directly chartable in FLAC like histories but with more control. Alternatively, you could write successive values to a CSV file without column constraints, but this method is slower because the file has to be written at each history interval.
The contour plots will not help you retrieve the data for each zone, but can show you visually what is happening to your model for troubleshooting and verification.
You can create a new plot and add a zone plot item, then select color by contour and set the zone value to displcement, stress or whatever you’d like to look at.