FISH vs Python scripts


I read from Itasca docs that Python scripts can be much faster with respect to FISH scripts.

As I usually used FISH to modify the behavior of some constitutive built-in laws in FLAC3D I would like to achieve a faster cycling execution to lower the overall running time of the models.

Together with FISH functions I use fish callback command to execute the function at a specific position during cycling and, I was wondering if there is the possibility to fully replace FISH functions which handle with material model parameters (cohesion, frictin angle, shear strain, etc.) and the callback command with Python scripts and, in case, if you have an example of such script.

Disregarding Python scripts, are there some tips or tricks to speed up FISH scripts?

Finally, which is the command or FISH function to record the total running time of a model?


Have you tried multithreaded FISH?

Hi Huy,
thank you for your suggestion.
I’m trying to implement splitting using fish callback function as follows:

fish callback add test_MC_BG(::zone.list) -1

The fish function test_MC_BG(z) operates on all zones. However, I’m getting the following error:


It seems that the used syntax is not permitted.
Can you help me?

Thank you in advance.


Use square brackets around [::zone.list] to indicate that it is fish intrinsic. Also make sure that the argument received by your function is used as a zone pointer.

Here’s simple example:

fish define test(zp)
    if zone.pos(zp)->z < 0
        zone.prop(zp,'density') = 5
fish callback add test([::zone.list]) -1
model solve

Dear apyatigorets
thanks a lot for the suggestion. It works fine.
Do you have the same example in Python?
Thank you in advance.


Dear apyatigorets,
an update from my side regarding the splitting and multithreading.
I used FISH to implement some changes in the behavior of a built-in FLAC model. The logic is as follows:

  1. in a FISH function, looping on the all zones to change friction angle and stiffness as per model equations
  2. use zone.force.update() to force the update of the stiffness used for timestep calculation
  3. use fish callback to call the FISH function at -1
  4. set automatic on and servo on (for creep analysis)

This sequence seems to work fine and the timestep is updated constantly starting from 1E-20 and then increased during the cycling.
When I try to use splitting and multithreading, the results obtained (in terms of displacement, expected friction angle and stiffness) are exactly the same but, unexpectedly, the analysis runs much more slower than without splitting. I think the reason is that with splitting, the timestep is not adjusted during the cycling but is kept constant at 1E-20.
I didn’t understand the reason(s) of such behavior.
Could you help me?

Thank you in advance.


Dear apyatigorets,
sorry for asking you another question. Is the following call correct? The purpose is to filter out the zones which have not “burgers-mohr” model.

fish callback add test_MC_BG([::zone.list(zone.model(::zone.list)==‘burgers-mohr’)]) -1

Thank you.


I don’t have a similar example in Python, I just created this one to illustrate list splitting. I think it should be relatively straightforward to create a similar Python example. Please refer to the documentation (e.g.,: Using Python with FLAC3D — FLAC3D 7.0 documentation).
There’s this example for setting zone properties (and you can find other examples):

lower_zones, upper_zones = 0, 0

for z in
    if"default") == "lower":
        lower_zones += 1
        z.set_prop("young", 1.6e10)
    elif"default") == "upper":
        upper_zones += 1

print(lower_zones, upper_zones)

Here’s another useful link: Using Python in Itasca Software | US Minneapolis - Itasca Consulting Group, Inc.

@Francesco_IT, this is a bit more involved question and it would be easier to figure out what is happening if you send us the datafile(s). Please submit support request for this.

Here’s correct syntax to “filter out the zones which have not “burgers-mohr” model” (note the not equal sign !=):

fish callback add test_MC_BG([::list(zone.list)(zone.model(::zone.list)!='burgers-mohr')]) -1

Here’s another example about list filtering (multithreaded): Splitting: Automatic Execution of Functions on Type Contents — FLAC3D 7.0 documentation

Can you just tell me if Python scripts can be used during cycling as by fish callback? I didn’t find such info in the documentation.

@Francesco_IT I personally have never used Python functions in callbacks but after digging through documentation, I found that it is doable and there are examples.

Python command to register a callback (called during cycling) is: itasca.set_callback(function_name: str, call_point: float or str)

Please look here for documentation and examples:
Python Callback Functions
Recording Peak Particle Velocity / Python Examlple
Please read carefully the Note at the top of the page about saving/restoring/resetting Python state:
Python Scripting

I reworked my toy example to use Python and now there are two files, one with FLAC3D commands to set the model and another with Python that sets callback:

; test.dat - set the model and cycle
model new
model large-strain off
model gravity 10

zone create brick
zone cmodel elastic
zone property young 1000 poisson 0.2 density 1
zone gp fix velocity-z range pos-z 0

call ''
model solve
# - set call through Python to change zone density
import itasca as it
it.command('python-reset-state false')

def change_density(*args):
    for zp in
        if zp.pos_z() > 5:
            zp.set_prop('density', 5)
it.set_callback("change_density", -1)

To my understanding, list splitting cannot be used in Python as it is developed specifically for multi-threaded Fish. So you will have to choose what is faster, using Python or multi-threaded Fish.

Dear @apyatigorets
thank a lot for your valuable support.
I will go through your example and documentation. Also, as suggested by you, I submitted to the support the issue about splitting and timestep during cycling in creep analysis and I will document here the findings if any.



An update regarding the FISH splitting and multithreading.
From the support, a correct way to include more than one filter ad the same time is:

[global BurgersAndMCZones = list(zone.list)(zone.model(::zone.list)==“burgers-mohr” | zone.model(::zone.list)==“mohr-coulomb”)]
fish callback add test_MC_BG([::BurgersAndMCZones]) -1
model solve creep time-total [time_total]
fish callback remove test_MC_BG -1

This works fine, provided that the BurgersAndMCZones is updated following the zone activation and the function test_MC_BG is added and removed at each activation step. Moreover, the function test_MC_BG has to be defined with:

fish operator test_MC_BG(pnt)

where pnt is a pointer to be used for splitting.
In this way, the code is 8 times faster !!! (2 hours vs 16 hours) than the previous version (no splitting) with almost identical results (“numerical noise”).
Thank you.


1 Like