Importing/Exporting data structures

PyFreeFEM automates conversion and exchange of FreeFEM and python data structures. The data structures that are supported are listed in the following correspondence table:

python

FreeFEM

float number

real number

numpy.array

real[int] array

complex[int] array

integer numpy.array (dtype=int)

int[int] array

scipy.sparse matrices (csc, csr, lil types…)

sparse matrix

matrix<complex>

numpy.ndarray (two dimensional array)

real[int,int] array

complex[int,int] array

pymedit.Mesh

mesh

pymedit.Mesh3D

mesh3

These data are automatically converted when exported or imported from one language to the other with automated reading and writing operations in temporary files.

Mesh data structures

Meshes are exported from FreeFEM into python with the Mesh and Mesh3D objects implemented in the pymedit library. pymedit enables to manipulate triangular/tetrahedral meshes and solution data following the INRIA mesh format.

Exporting FreeFEM data into Python

Exporting FreeFEM data is done from the .edp script by using the macros exportVar, exportArray, exportIntArray, exportComplexArray, export2DArray, exportComplex2DArray, exportMatrix, exportComplexMatrix, exportMesh and exportMesh3D implemented in pyfreefem/edp/io.edp.

These macros still require the special preprocessing instruction IMPORT "io.edp" at the beginning of the .edp script.

freefem ex10_io_export.edp
   IMPORT "io.edp"

   real var = pi;
   real[int] arr = [1,2,3,4];

   mesh Th = square(10,10);
   fespace Fh1(Th,P1);

   varf laplace(u,v) = int2d(Th)(u*v+dx(u)*dx(v)+dy(u)*dy(v));
   varf rhs(u,v) = int1d(Th,1)(v);

   matrix A = laplace(Fh1,Fh1);
   real[int] f= rhs(0,Fh1);

   real[int] u=A^-1*f;

   complex[int] arrCpx = [1+1i,2+1i,3];

   real[int,int] B = [[1,2,3],[4,5,6]];
   complex[int,int] Bcpx = [[1+1i,2+2i,3],[4,5,6+1i]];


   dispVar(var);
   exportVar(var);
   export2DArray(B);

   exportMesh(Th);

   exportArray(arr);
   export2DArray(B);
   exportArray(f);
   exportArray(u);
   exportMatrix(A);
   exportComplexMatrix(Acpx);
   exportComplexArray(arrCpx);
   exportComplex2DArray(Bcpx);

The execute() method returns a dictionary containing the exported data structures.

python ex10_io_export.py
from pyfreefem import FreeFemRunner

exports = FreeFemRunner("ex10_io_export.edp").execute()
exports['Th'].plot(title="mesh Th",bcEdgeLabels=True)
print('var='+str(exports['var']))
print('A=',exports['A'])
print('f=',exports['f'])
print('arr='+str(exports['arr']))
print('arrCpx=',exports['arrCpx'])
print('B=',exports['B'])
print('Bcpx=',exports['Bcpx'])
print('f=',exports['f'])

Running this script should show the following output and figure:

console
$ python ex10_io_export.py
var=3.141592653589793
arr=[1. 2. 3. 4.]
arrCpx= [1.+1.j 2.+1.j 3.+0.j]
A= <Compressed Sparse Column sparse matrix of dtype 'float64'
     with 761 stored elements and shape (121, 121)>
  Coords     Values
  (0, 0)     1.0016666666666667
  (1, 0)     -0.49958333333333327
  (11, 0)    -0.49958333333333327
  (12, 0)    0.0008333333333333339
  (0, 1)     -0.49958333333333327
  (1, 1)     2.0025
  (2, 1)     -0.49958333333333327
  (12, 1)    -0.9991666666666665
  :  :
  (108, 120) 0.0008333333333333331
  (109, 120) -0.49958333333333343
  (119, 120) -0.49958333333333343
  (120, 120) 1.001666666666667
Acpx= <Compressed Sparse Column sparse matrix of dtype 'complex128'
     with 761 stored elements and shape (121, 121)>
  Coords     Values
  (0, 0)     (0.9983333333333333-0.06666666666666668j)
  (1, 0)     (-0.5004166666666666-0.016666666666666666j)
  (11, 0)    (-0.5004166666666666-0.016666666666666666j)
  (12, 0)    (-0.0008333333333333339+0j)
  :  :
  (109, 120) (-0.5004166666666667-0.016666666666666663j)
  (119, 120) (-0.5004166666666667-0.016666666666666663j)
  (120, 120) (0.9983333333333336-0.06666666666666665j)
B= [[1. 2. 3.]
 [4. 5. 6.]]
Bcpx= [[1.+1.j 2.+2.j 3.+0.j]
 [4.+0.j 5.+0.j 6.+1.j]]
f= [0.05 0.1  0.1  0.1  0.1  0.1  0.1  0.1  0.1  0.1  0.05 0.   0.   0.
 0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.
 0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.
  :  :
 0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.
 0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.
 0.   0.   0.   0.   0.   0.   0.   0.   0.  ]
_images/Th_python.png
pymedit plot after running ex10_io_export.py

Importing python data into FreeFEM

The data that are listed in the above table can be imported in a .edp script by using the macros importVar, importArray, importComplexArray, importIntArray, import2DArray, importComplex2DArray, importMatrix, importComplexMatrix, importMesh3D implemented in pyfreefem/edp/io.edp. These macros can be used by inserting the special preprocessing instruction IMPORT "io.edp" at the beginning of the .edp script.

pyfreefem/edp/io.edp also include the macros dispVar, dispArray, dispMatrix for conveniently displaying the values of corresponding variables.

freefem ex11_io_import.edp
IMPORT "io.edp"

mesh Th=importMesh("Th");
plot(Th,cmm="Th");

real x = importVar("x");
dispVar(x);

real[int] arr = importArray("arr");
dispArray(arr);

complex[int] arrCpx = importComplexArray("arr_cpx");
dispArray(arrCpx);

matrix A = importMatrix("A");
dispMatrix(A);

real[int,int] B = import2DArray("B");
disp2DArray(B);

complex[int,int] Bcpx = importComplex2DArray("Bcpx");
disp2DArray(Bcpx);

In this example, Th, x, arr, arrCpx, A, Acpx, B, Bcpx, refer to python data structures that must be imported before executing the script by using the method import_variables() of the FreeFemRunner class:

python ex11_io_import.py
from pyfreefem import FreeFemRunner

import numpy as np
from pymedit import square
import scipy.sparse as sp

x = np.pi
arr = np.asarray([1,2,3])
arr_cpx = np.asarray([1+1j,2+1j,3])
B = np.asarray([[1,2,3],[4,5,6]],dtype=float)
Bcpx = np.asarray([[1+1j,2+2j,3],[4,5,6+1j]])
Th = square(10,10)        # a pymedit.Mesh square mesh
A = sp.diags([1,2,3,4])
Acpx = sp.diags([1+1j,2,3+3j,4+1j])

runner = FreeFemRunner("ex11_io_import.edp")

runner.import_variables(x, arr, arr_cpx, Th, A, Acpx, B, Bcpx)
runner.execute(verbosity=0, plot=True)

Running this script should show the following output and figure:

console
$ python ex11_io_import.py
x=3.14159
arr=3
       1       2       3
arrCpx=3
     (1,1)   (2,1)   (3,0)
 build matrix 4x4 nnz =4 bin = 1 fname = run/ffimport/matrix_A
A=#  HashMatrix Matrix (COO) 0x5cb5144944b0
#    n       m        nnz     half     fortran   state
4 4 4 0 0 0 0
         0         0 1
         1         1 2
         2         2 3
         3         3 4

 build matrix 4x4 nnz =4 bin = 1 fname = run/ffimport/matrixComplex_Acpx
Acpx=#  HashMatrix Matrix (COO) 0x5cb5144945e0
#    n       m        nnz     half     fortran   state
4 4 4 0 0 0 0
         0         0 (1,1)
         1         1 (2,0)
         2         2 (3,3)
         3         3 (4,1)

B=2 3
        1   2   3
        4   5   6

Bcpx=2 3
      (1,1) (2,2) (3,0)
      (4,0) (5,0) (6,1)
_images/Th_freefem.png
FreeFem plot after running ex11_io_import.py

Manual imports and exports

Alternatively, you can read and write FreeFEM data structures using the following functions from the module pyfreefem.io:

Floating variables can be directly stored in text files, while pymedit mesh objects can be saved into .mesh files readable by FreeFEM with the method pymedit.Mesh.save().