FreeFEM output and debugging¶
Setting FreeFEM verbosity¶
By default, PyFreeFEM hides the standard output of the FreeFEM process. It is possible to
display it by specifying an integer value to the parameter verbosity
when calling execute():
from pyfreefem import FreeFemRunner
script = """
mesh Th=square(30,30);
fespace Fh(Th,P1);
Fh u,v;
solve laplace(u,v)=
int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))
-int2d(Th)(v)
+on(1,2,3,4,u=0);"""
runner = FreeFemRunner(script)
runner.execute(verbosity=2)
$ python ex_verbosity.py
-- FreeFem++ v4.12 (mer 25 jan 2023 14:14:39 CET - git v4.12)
file : /tmp/pyfreefem_6vwrtwvg/run.edp verbosity= 2
Load: lg_fem lg_mesh lg_mesh3 eigenvalue
1 :
2 : mesh Th=square(30,30);
3 : fespace Fh(Th,P1);
4 : Fh u,v;
5 :
6 : solve laplace(u,v)=
7 : int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))
8 : -int2d(Th)(v)
9 : +on(1,2,3,4,u=0); -- Problem type ( complex : 0 )
sizestack + 1024 =1576 ( 552 )
-- Square mesh : nb vertices =961 , nb triangles = 1800 , nb boundary edges 120
Nb of Vertices 961 , Nb of Triangles 1800
Nb of edge on user boundary 120 , Nb of edges on true boundary 120
-- Change of Mesh 0 0x1ddc9e0
-- size of Matrix 0 Bytes
-- Solve :
min 2.20333e-63 max 0.0736069
times: compile 0.002109s, execution 0.003763s, mpirank:0
CodeAlloc : nb ptr 3737, size :504368 mpirank: 0
Ok: Normal End
When not specified, the method execute() assumes the default value
verbosity=-1 (no standard output).
Setting verbosity=n with a non-negative integer n displays
the standard output of the command FreeFem++ with the verbosity option -v n.
Retrieving FreeFEM standard output¶
FreeFEM standard output can be retrieve after having called execute()
by using the rets attribute:
print(runner.rets)
(0, '-- FreeFem++ v4.12 (mer 25 jan 2023 14:14:39 CET - git v4.12)\n file : /tmp/pyfreefem_9xj1goi1/run.edp verbosity= 2\n Load: lg_fem lg_mesh lg_mesh3 eigenvalue \n 1 : \n 2 : mesh Th=square(30,30);\n 3 : fespace Fh(Th,P1);\n 4 : Fh u,v;\n 5 : \n 6 : solve laplace(u,v)=\n 7 : int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))\n 8 : -int2d(Th)(v)\n 9 : +on(1,2,3,4,u=0); -- Problem type ( complex : 0 ) \n sizestack + 1024 =1576 ( 552 )\n\n -- Square mesh : nb vertices =961 , nb triangles = 1800 , nb boundary edges 120\n Nb of Vertices 961 , Nb of Triangles 1800\n Nb of edge on user boundary 120 , Nb of edges on true boundary 120\n -- Change of Mesh 0 0x23e79e0\n -- size of Matrix 0 Bytes\n -- Solve : \n min 2.20333e-63 max 0.0736069\ntimes: compile 0.001899s, execution 0.003733s, mpirank:0\n CodeAlloc : nb ptr 3737, size :504368 mpirank: 0\nOk: Normal End\n', '', '-- FreeFem++ v4.12 (mer 25 jan 2023 14:14:39 CET - git v4.12)\n file : /tmp/pyfreefem_9xj1goi1/run.edp verbosity= 2\n Load: lg_fem lg_mesh lg_mesh3 eigenvalue \n 1 : \n 2 : mesh Th=square(30,30);\n 3 : fespace Fh(Th,P1);\n 4 : Fh u,v;\n 5 : \n 6 : solve laplace(u,v)=\n 7 : int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))\n 8 : -int2d(Th)(v)\n 9 : +on(1,2,3,4,u=0); -- Problem type ( complex : 0 ) \n sizestack + 1024 =1576 ( 552 )\n\n -- Square mesh : nb vertices =961 , nb triangles = 1800 , nb boundary edges 120\n Nb of Vertices 961 , Nb of Triangles 1800\n Nb of edge on user boundary 120 , Nb of edges on true boundary 120\n -- Change of Mesh 0 0x23e79e0\n -- size of Matrix 0 Bytes\n -- Solve : \n min 2.20333e-63 max 0.0736069\ntimes: compile 0.001899s, execution 0.003733s, mpirank:0\n CodeAlloc : nb ptr 3737, size :504368 mpirank: 0\nOk: Normal End\n')
Retrieving the values of PyFreeFEM magic variables¶
The values of PyFreeFEM magic variables can be retrieved after
calling the method
pyfreefem.FreeFemRunner.execute() from the config attribute:
from pyfreefem import FreeFemRunner
script="""
DEFAULT (res,"high")
IFEQ (res,"high")
DEFAULT (N,100)
ENDIF
IFEQ (res,"medium")
DEFAULT (N,50)
ENDIF
IFEQ (res,"low")
DEFAULT (N,10)
ENDIF
mesh Th=square(N,N);"""
runner = FreeFemRunner(script)
runner.execute({'res':'medium'})
print(runner.config)
$ python test.py
{'res': 'medium', 'DEBUG': 0, 'RUNDIR': '/tmp/pyfreefem_zoaqyf8k', 'FFEXPORTDIR': '/tmp/pyfreefem_zoaqyf8k/ffexport', 'FFIMPORTDIR': '/tmp/pyfreefem_zoaqyf8k/ffimport'}
Debugging¶
It is possible to have detailed information about parsing operation and
code execution with a flexible level of verbosity by
specifying a sufficiently large integer value to the
debug argument in either the FreeFemRunner constructor or
the execute() routine:
1from pyfreefem import FreeFemRunner
2
3script = """
4DEFAULT (Re,10)
5SET (Pe,30)
6SET (ratioRePe,$Re/$Pe)
7real Re=$Re;
8real Pe=$Pe;
9real ratio=$ratioRePe;"""
10
11FreeFemRunner(script,debug=10).execute()
Output:
$ python script.py
0 :
Interpreted :
1 : DEFAULT (Re,10)
Defined Re=10
2 : SET (Pe,30)
Defined Pe=30
3 : SET (ratioRePe,$Re/$Pe)
Defined ratioRePe=0.3333333333333333
4 : real Re=$Re;
Interpreted : real Re=10;
5 : real Pe=$Pe;
Interpreted : real Pe=30;
6 : real ratio=$ratioRePe;
Interpreted : real ratio=0.3333333333333333
Write /tmp/pyfreefem_0k3s9o5b/run.edp
Reset directory /tmp/pyfreefem_0k3s9o5b/ffexport
FreeFem++ /tmp/pyfreefem_0k3s9o5b/run.edp -v 0 -nw (0.01s)
Note
The debug argument of the method execute() has
precedence over the one of the FreeFemRunner constructor.
runner = FreeFemRunner(script, debug=10)
runner.execute(debug=100) # Execution will follow with debug=100
Debugging syntax errors¶
If the .edp script
is syntaxically incorrect, an exception will be raised. For instance, setting script in the
above code to
3script = """
4DEFAULT (Re,10)
5SET (Pe,30)
6SET (ratioRePe,$Re/$Pe)
7real Re=$Re
8real Pe=$Pe;
9real ratio=$ratioRePe;"""
and executing with debug=0 yields:
$ python test.py
Error : the process "FreeFem++ /tmp/pyfreefem_3kzp33g9/run.edp -v 0 -nw" failed with return code 1.
Error line number 3, in file /tmp/pyfreefem_3kzp33g9/run.edp, before token real
syntax error
current line = 2
Compile error : syntax error
line number :3, real
error Compile error : syntax error
line number :3, real
code = 1 mpirank: 0
Traceback (most recent call last):
File "/home/florian/python/pyfreefem/pyfreefem/examples/test.py", line 11, in <module>
FreeFemRunner(script,debug=0).execute()
File "/home/florian/python/pyfreefem/pyfreefem/freefemrunner.py", line 307, in execute
raise e
File "/home/florian/python/pyfreefem/pyfreefem/freefemrunner.py", line 301, in execute
exec2(self.cmd(target_file, **kwargs),
File "/home/florian/python/pyfreefem/pyfreefem/io.py", line 253, in exec2
raise ExecException('Error : the process "'
pyfreefem.io.ExecException
This output may not seem very explicit to understand the mistake. More information can be retrieved
by showing FreeFEM standard output with verbosity=1:
FreeFemRunner(script).execute(verbosity=1)
$ python test.py
-- FreeFem++ v4.12 (mer 25 jan 2023 14:14:39 CET - git v4.12)
file : /tmp/pyfreefem_dkem5s5z/run.edp
Load: lg_fem lg_mesh lg_mesh3 eigenvalue
1 :
2 : real Re=10
3 : real
Error line number 3, in file /tmp/pyfreefem_dkem5s5z/run.edp, before token real
syntax error
current line = 2
Compile error : syntax error
line number :3, real
error Compile error : syntax error
line number :3, real
code = 1 mpirank: 0
Error : the process "FreeFem++ /tmp/pyfreefem_dkem5s5z/run.edp -v 1 -nw" failed with return code 1.
-- FreeFem++ v4.12 (mer 25 jan 2023 14:14:39 CET - git v4.12)
file : /tmp/pyfreefem_dkem5s5z/run.edp
Load: lg_fem lg_mesh lg_mesh3 eigenvalue
1 :
2 : real Re=10
3 : real
Error line number 3, in file /tmp/pyfreefem_dkem5s5z/run.edp, before token real
syntax error
current line = 2
Compile error : syntax error
line number :3, real
error Compile error : syntax error
line number :3, real
code = 1 mpirank: 0
Traceback (most recent call last):
File "/home/florian/python/pyfreefem/pyfreefem/examples/test.py", line 11, in <module>
FreeFemRunner(script).execute(verbosity=1)
File "/home/florian/python/pyfreefem/pyfreefem/freefemrunner.py", line 307, in execute
raise e
File "/home/florian/python/pyfreefem/pyfreefem/freefemrunner.py", line 301, in execute
exec2(self.cmd(target_file, **kwargs),
File "/home/florian/python/pyfreefem/pyfreefem/io.py", line 253, in exec2
raise ExecException('Error : the process "'
pyfreefem.io.ExecException
from where it is more clear to infer that the problem comes from the missing comma of line 7 in script.py
(real Re=$N).
Note
If the standard output is still not readable enough for debugging, it can be useful to specify a running directory with
FreeFemRunner(script, run_dir="run").execute(verbosity=1)
and to check directly the file run/run.edp.