Dear community,
I noticed a weird bug when trying to export arrays to files when running several FreeFem++ processes with a Python parallel for loop. The bug seems to be related to the interpretation of macros imported from external files.
I am using the following Python code calling pyfreefem for exporting an array in multiple output folders:
# This code does not work !
from pyfreefem import FreeFemRunner
from multiprocessing.pool import ThreadPool as Pool
code = """
IMPORT "io.edp"
real[int] x = [1,2,3,4,5];
exportArray(x);
"""
def process_data(index):
FreeFemRunner(code, config={"FILE": str(index)},
run_dir="test/output_"+str(index), debug=1).execute()
indices=range(100)
with Pool(processes=8) as pool:
pool.map(process_data, indices)
The code is supposed to save hundred times the file test/output_{i}/ffexport/array_x where i is an integer between 0 and 99.
For running this code, pyfreefem needs to be installed with pip install pyfreefem
.
The macro exportArray
is defined here: it does
func int saveArray(string fileName, real[int] &value){
ofstream file(fileName);
file.precision(16);
file << value;
dispDebug("Saved "+fileName,2,"blue");
}
macro exportArray(a) saveArray("$FFEXPORTDIR/array_"+Stringification(a),a)//
When executed, the line IMPORT "io.edp"
is substituted into a regular import of a local copy of the file io.edp and $FFEXPORTDIR
is replaced with test/output_{i}/ffexport
.
Running this code with Python fails for some of the processes (not all) with the message
4 : real[int] x = [1,2,3,4,5];
5 : exportArray(x) saveArray("test/output_68/ffexport/array_"+Stringification((xx)),x); sizestack + 1024 =4568 ( 3544 )
Error opening file test/output_68/ffexport/array_x
current line = 85
call saveArray at line 5
Exec error : Error opening file
-- number :1
The problem seems to be related to the interpretation of the macro exportArray
which saves the file. Curiously, if we replace exportArray(x)
with exportArray2(x)
where exportArray2
is a copy of the macro exportArray
that we insert directly in the running file , then it works:
# THIS CODE WORKS !
from pyfreefem import FreeFemRunner
from multiprocessing.pool import ThreadPool as Pool
code = """
IMPORT "io.edp"
real[int] x = [1,2,3,4,5];
macro exportArray2(a) saveArray("$FFEXPORTDIR/array_"+Stringification(a),a)//
exportArray2(x);
"""
def process_data(index):
FreeFemRunner(code, config={"FILE": str(index)},
run_dir="test/output_"+str(index), debug=1).execute()
indices=range(100)
with Pool(processes=8) as pool:
pool.map(process_data, indices)
Would you have an idea about why the original version fails ?
PS : Sorry for not providing a more minimal code which would not rely on pyfreefem, but I hope my message and the instructions are sufficiently clear.