getfem-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Getfem-commits] (no subject)


From: Tetsuo Koyama
Subject: [Getfem-commits] (no subject)
Date: Fri, 21 Jun 2019 09:51:54 -0400 (EDT)

branch: code_cleanup_to_pep8
commit bcfb2d3211be3244143029f562567a0e35969e8d
Author: Tetsuo Koyama <address@hidden>
Date:   Fri Jun 21 22:22:37 2019 +0900

    clean formats to conform to the PEP 8 style guide
    
    https://pypi.python.org/pypi/autopep8/
---
 interface/tests/python/check_asm.py                | 383 +++++----
 interface/tests/python/check_export.py             | 225 ++++--
 interface/tests/python/check_global_functions.py   | 141 ++--
 interface/tests/python/check_levelset.py           |  77 +-
 interface/tests/python/check_mixed_mesh.py         | 241 +++---
 interface/tests/python/check_secondary_domain.py   | 147 ++--
 .../tests/python/demo_Mindlin_Reissner_plate.py    |  88 ++-
 interface/tests/python/demo_crack.py               | 222 +++---
 .../python/demo_cracked_thermo_elastic_body.py     | 277 ++++---
 interface/tests/python/demo_dynamic_contact_1D.py  | 874 ++++++++++++---------
 .../tests/python/demo_elastic_ring_contact.py      | 371 +++++----
 interface/tests/python/demo_fictitious_domains.py  | 134 ++--
 .../tests/python/demo_finite_strain_plasticity.py  | 494 +++++++-----
 .../python/demo_finite_strain_plasticity_3D.py     | 485 +++++++-----
 interface/tests/python/demo_laplacian.py           | 101 +--
 interface/tests/python/demo_laplacian_DG.py        | 173 ++--
 .../tests/python/demo_laplacian_aposteriori.py     | 185 +++--
 interface/tests/python/demo_laplacian_pyramid.py   | 141 ++--
 .../tests/python/demo_large_sliding_contact.py     | 606 ++++++++------
 interface/tests/python/demo_mortar.py              |  97 +--
 interface/tests/python/demo_navier_stokes.py       | 125 +--
 .../tests/python/demo_nonlinear_elasticity.py      | 285 +++----
 interface/tests/python/demo_parallel_laplacian.py  | 140 ++--
 interface/tests/python/demo_phase_field.py         | 275 ++++---
 interface/tests/python/demo_plasticity.py          | 145 ++--
 interface/tests/python/demo_plate.py               |  92 +--
 interface/tests/python/demo_static_contact.py      | 480 ++++++-----
 interface/tests/python/demo_step_by_step.py        |  30 +-
 interface/tests/python/demo_stokes_3D_tank.py      | 138 ++--
 interface/tests/python/demo_stokes_3D_tank_draw.py |  71 +-
 .../demo_thermo_elasticity_electrical_coupling.py  | 244 +++---
 interface/tests/python/demo_tresca.py              |  77 +-
 interface/tests/python/demo_tripod.py              | 149 ++--
 interface/tests/python/demo_tripod_alt.py          | 137 ++--
 interface/tests/python/demo_unit_disk.py           |  47 +-
 interface/tests/python/demo_wave.py                |  84 +-
 interface/tests/python/demo_wave_equation.py       |  85 +-
 interface/tests/python/demo_wheel_contact.py       | 193 +++--
 interface/tests/python/getfem_tvtk.py              | 488 +++++++-----
 interface/tests/python/tutorial1.py                |  28 +-
 40 files changed, 5094 insertions(+), 3681 deletions(-)

diff --git a/interface/tests/python/check_asm.py 
b/interface/tests/python/check_asm.py
index d0972c5..e5ba39d 100644
--- a/interface/tests/python/check_asm.py
+++ b/interface/tests/python/check_asm.py
@@ -33,209 +33,284 @@ import os
 
 
 NX = 4
-m = gf.Mesh('triangles grid', np.arange(0,1+1./NX,1./NX),
-            np.arange(0,1+1./NX,1./NX))     # Structured mesh
-fem = gf.Fem('FEM_PK(2,1)')
-mfu = gf.MeshFem(m, 1); mfu.set_fem(fem)    # Lagrange P1 scalar fem
-mfv = gf.MeshFem(m, 3); mfv.set_fem(fem)    # Lagrange P1 vector fem
-mfw = gf.MeshFem(m, 2); mfw.set_fem(fem)    # Lagrange P1 vector fem
-mim = gf.MeshIm(m, gf.Integ('IM_TRIANGLE(4)'))
+m = gf.Mesh(
+    "triangles grid",
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+)  # Structured mesh
+fem = gf.Fem("FEM_PK(2,1)")
+mfu = gf.MeshFem(m, 1)
+mfu.set_fem(fem)  # Lagrange P1 scalar fem
+mfv = gf.MeshFem(m, 3)
+mfv.set_fem(fem)  # Lagrange P1 vector fem
+mfw = gf.MeshFem(m, 2)
+mfw.set_fem(fem)  # Lagrange P1 vector fem
+mim = gf.MeshIm(m, gf.Integ("IM_TRIANGLE(4)"))
 
 
-U = mfu.eval('x+y')
-V = mfv.eval('[x*y, x*y, x*y]')
-W = mfw.eval('[x*y, x*y]')
+U = mfu.eval("x+y")
+V = mfv.eval("[x*y, x*y, x*y]")
+W = mfw.eval("[x*y, x*y]")
 
 
-md = gf.Model('real')
+md = gf.Model("real")
 
-md.add_fem_variable('u', mfu)
-md.set_variable('u', U)
-md.add_fem_variable('v', mfv)
-md.set_variable('v', V)
-md.add_fem_variable('w', mfw)
-md.set_variable('w', W)
+md.add_fem_variable("u", mfu)
+md.set_variable("u", U)
+md.add_fem_variable("v", mfv)
+md.set_variable("v", V)
+md.add_fem_variable("w", mfw)
+md.set_variable("w", W)
 
 
 # Simple test on the integral of u
-result = gf.asm('generic', mim, 0, "u", -1, md)
-if (abs(result-1) > 1e-8) : print("Bad value"); exit(1)
+result = gf.asm("generic", mim, 0, "u", -1, md)
+if abs(result - 1) > 1e-8:
+    print("Bad value")
+    exit(1)
 
 # Single contraction and comparison with Trace
-result1 = gf.asm('generic', mim, 0,
-                 "Def P(a):=a*(a'); Contract(P(Grad_v), 1, 2)", -1, md)
-result2 = gf.asm('generic', mim, 0,
-                 "Def P(a):=a*(a'); Trace(P(Grad_v))", -1, md)
-if (abs(result1-result2) > 1e-8) : print("Bad value"); exit(1)
+result1 = gf.asm(
+    "generic", mim, 0, "Def P(a):=a*(a'); Contract(P(Grad_v), 1, 2)", -1, md
+)
+result2 = gf.asm("generic", mim, 0, "Def P(a):=a*(a'); Trace(P(Grad_v))", -1, 
md)
+if abs(result1 - result2) > 1e-8:
+    print("Bad value")
+    exit(1)
 
 # Constant order 3 tensor contraction test
-result1 = gf.asm('generic', mim, 0,
-                 "Contract([[[1,1],[2,2]],[[1,1],[2,2]]], 1, 2)", -1, md)
-result2 = np.array([3., 3.]);
-if (np.linalg.norm(result1-result2) > 1e-8) : print("Bad value"); exit(1)
+result1 = gf.asm(
+    "generic", mim, 0, "Contract([[[1,1],[2,2]],[[1,1],[2,2]]], 1, 2)", -1, md
+)
+result2 = np.array([3.0, 3.0])
+if np.linalg.norm(result1 - result2) > 1e-8:
+    print("Bad value")
+    exit(1)
 
 # Single contraction, comparison with "*"
-result1 = gf.asm('generic', mim, 0, "Contract(Grad_v, 2, Grad_u, 1)", -1, md)
-result2 = gf.asm('generic', mim, 0, "Grad_v * Grad_u", -1, md)
-if (np.linalg.norm(result1-result2) > 1e-8) : print("Bad value"); exit(1)
+result1 = gf.asm("generic", mim, 0, "Contract(Grad_v, 2, Grad_u, 1)", -1, md)
+result2 = gf.asm("generic", mim, 0, "Grad_v * Grad_u", -1, md)
+if np.linalg.norm(result1 - result2) > 1e-8:
+    print("Bad value")
+    exit(1)
 
 # Double contraction order one expression, comparison with ":"
-result1 = gf.asm('generic', mim, 1,
-                 "Contract(Grad_v, 1, 2, Grad_Test_v, 1, 2)", -1, md)
-result2 = gf.asm('generic', mim, 1, "Grad_v : Grad_Test_v", -1, md)
-if (np.linalg.norm(result1-result2) > 1e-8) : print("Bad value"); exit(1)
+result1 = gf.asm("generic", mim, 1, "Contract(Grad_v, 1, 2, Grad_Test_v, 1, 
2)", -1, md)
+result2 = gf.asm("generic", mim, 1, "Grad_v : Grad_Test_v", -1, md)
+if np.linalg.norm(result1 - result2) > 1e-8:
+    print("Bad value")
+    exit(1)
 
 # Double contraction order two expression, comparison with ":"
-result1 = gf.asm('generic', mim, 2,
-                 "Contract(Grad_Test2_v, 1, 2, Grad_Test_v, 1, 2)", -1, md)
-result2 = gf.asm('generic', mim, 2, "Grad_Test2_v : Grad_Test_v", -1, md)
-if (np.linalg.norm(result1.full()-result2.full()) > 1e-8) :
-  print("Bad value"); exit(1)
-result1 = gf.asm('generic', mim, 2,
-                 "Contract(Grad_Test_v, 2, 1, Grad_Test2_v, 2, 1)", -1, md)
-if (np.linalg.norm(result1.full()-result2.full()) > 1e-8) :
-  print("Bad value"); exit(1)
+result1 = gf.asm(
+    "generic", mim, 2, "Contract(Grad_Test2_v, 1, 2, Grad_Test_v, 1, 2)", -1, 
md
+)
+result2 = gf.asm("generic", mim, 2, "Grad_Test2_v : Grad_Test_v", -1, md)
+if np.linalg.norm(result1.full() - result2.full()) > 1e-8:
+    print("Bad value")
+    exit(1)
+result1 = gf.asm(
+    "generic", mim, 2, "Contract(Grad_Test_v, 2, 1, Grad_Test2_v, 2, 1)", -1, 
md
+)
+if np.linalg.norm(result1.full() - result2.full()) > 1e-8:
+    print("Bad value")
+    exit(1)
 
 print('\nAssembly string "Def P(u):= Grad(u); P(Grad(u)+[1;1])" gives:')
-res = gf.asm('expression analysis', 'Def P(u):= Grad(u); P(Grad(u)+[1;1])',
-             mim, 2, md)
-if (res != "(Hess_u)"): print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Def P(u):= Grad(u); P(Grad(u)+[1;1])", 
mim, 2, md)
+if res != "(Hess_u)":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Grad_u\')" gives:')
-res = gf.asm('expression analysis', "Grad(Grad_u')",  mim, 2, md)
-if (res != "(Reshape(Hess_u, 1, 2, 2))"): print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad(Grad_u')", mim, 2, md)
+if res != "(Reshape(Hess_u, 1, 2, 2))":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Sym(Grad_w))" gives:')
-res = gf.asm('expression analysis', "Grad(Sym(Grad_w))",  mim, 2, md)
-if (res != "((Hess_w+(Hess_w'))*0.5)"): print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad(Sym(Grad_w))", mim, 2, md)
+if res != "((Hess_w+(Hess_w'))*0.5)":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Skew(Grad_w))" gives:')
-res = gf.asm('expression analysis', "Grad(Skew(Grad_w))",  mim, 2, md)
-if (res != "((Hess_w-(Hess_w'))*0.5)"): print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad(Skew(Grad_w))", mim, 2, md)
+if res != "((Hess_w-(Hess_w'))*0.5)":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Grad_w*Grad_u)" gives:')
-res = gf.asm('expression analysis', "Grad(Grad_w*Grad_u)",  mim, 2, md)
+res = gf.asm("expression analysis", "Grad(Grad_w*Grad_u)", mim, 2, md)
 print(res)
-if (res != "(Contract(Hess_w, 2, Grad_u, 1)+(Grad_w.Hess_u))"):
-  print("Bad gradient"); exit(1)
+if res != "(Contract(Hess_w, 2, Grad_u, 1)+(Grad_w.Hess_u))":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(u*Grad_w)" gives:')
-res = gf.asm('expression analysis', "Grad(u*Grad_w)",  mim, 2, md)
-if (res != "((Grad_w@Grad_u)+(u*Hess_w))"): print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad(u*Grad_w)", mim, 2, md)
+if res != "((Grad_w@Grad_u)+(u*Hess_w))":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Grad_w:Id(meshdim))" gives:')
-res = gf.asm('expression analysis', "Grad(Grad_w:Id(meshdim))",  mim, 2, md)
-if (res != "(Contract([[1,0],[0,1]], 1, 2, Hess_w, 1, 2))"):
-  print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad(Grad_w:Id(meshdim))", mim, 2, md)
+if res != "(Contract([[1,0],[0,1]], 1, 2, Hess_w, 1, 2))":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Grad_w:Id(meshdim))" gives:')
-res = gf.asm('expression analysis', "Grad(Grad_w@Grad_v)",  mim, 2, md)
-if (res != "(Index_move_last((Hess_w@Grad_v), 3)+(Grad_w@Hess_v))"):
-  print("Bad gradient"); exit(1)
-  
+res = gf.asm("expression analysis", "Grad(Grad_w@Grad_v)", mim, 2, md)
+if res != "(Index_move_last((Hess_w@Grad_v), 3)+(Grad_w@Hess_v))":
+    print("Bad gradient")
+    exit(1)
+
 print('\nAssembly string "Grad(Grad_w.Grad_w)" gives:')
-res = gf.asm('expression analysis', "Grad(Grad_w.Grad_w)",  mim, 2, md)
-if (res !=
-    "(Index_move_last(Contract(Hess_w, 2, Grad_w, 1), 2)+(Grad_w.Hess_w))"):
-  print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad(Grad_w.Grad_w)", mim, 2, md)
+if res != "(Index_move_last(Contract(Hess_w, 2, Grad_w, 1), 
2)+(Grad_w.Hess_w))":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Grad_w./Grad_w)" gives:')
-res = gf.asm('expression analysis', "Grad(Grad_w./Grad_w)",  mim, 2, md)
-if (res !=
-    "((Hess_w./(Grad_w@[1,1]))-(((Grad_w./sqr(Grad_w))@[1,1]).*Hess_w))"):
-  print("Bad gradient"); exit(1)
-  
+res = gf.asm("expression analysis", "Grad(Grad_w./Grad_w)", mim, 2, md)
+if res != "((Hess_w./(Grad_w@[1,1]))-(((Grad_w./sqr(Grad_w))@[1,1]).*Hess_w))":
+    print("Bad gradient")
+    exit(1)
+
 print('\nAssembly string "Grad(Grad_w/u)" gives:')
-res = gf.asm('expression analysis', "Grad(Grad_w/u)",  mim, 2, md)
-if (res != "((Hess_w/u)-((Grad_w/sqr(u))@Grad_u))"):
-  print("Bad gradient"); exit(1)
-  
+res = gf.asm("expression analysis", "Grad(Grad_w/u)", mim, 2, md)
+if res != "((Hess_w/u)-((Grad_w/sqr(u))@Grad_u))":
+    print("Bad gradient")
+    exit(1)
+
 print('\nAssembly string "Grad([u,u; 2,1; u,u])" gives:')
-res = gf.asm('expression analysis', "Grad([u,u; 2,1; u,u])",  mim, 2, md)
-if (res != 
"([[[Grad_u(1),0,Grad_u(1)],[Grad_u(1),0,Grad_u(1)]],[[Grad_u(2),0,Grad_u(2)],[Grad_u(2),0,Grad_u(2)]]])"):
-  print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad([u,u; 2,1; u,u])", mim, 2, md)
+if (
+    res
+    != 
"([[[Grad_u(1),0,Grad_u(1)],[Grad_u(1),0,Grad_u(1)]],[[Grad_u(2),0,Grad_u(2)],[Grad_u(2),0,Grad_u(2)]]])"
+):
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad([[u,2,u],[u,1,u]])" gives:')
-res = gf.asm('expression analysis', "Grad([[u,2,u],[u,1,u]])",  mim, 2, md)
-if (res != 
"([[[Grad_u(1),0,Grad_u(1)],[Grad_u(1),0,Grad_u(1)]],[[Grad_u(2),0,Grad_u(2)],[Grad_u(2),0,Grad_u(2)]]])"):
-  print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad([[u,2,u],[u,1,u]])", mim, 2, md)
+if (
+    res
+    != 
"([[[Grad_u(1),0,Grad_u(1)],[Grad_u(1),0,Grad_u(1)]],[[Grad_u(2),0,Grad_u(2)],[Grad_u(2),0,Grad_u(2)]]])"
+):
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad([u;u])" gives:')
-res = gf.asm('expression analysis', "Grad([u,u])",  mim, 2, md)
-if (res != "([[Grad_u(1),Grad_u(1)],[Grad_u(2),Grad_u(2)]])"):
-  print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad([u,u])", mim, 2, md)
+if res != "([[Grad_u(1),Grad_u(1)],[Grad_u(2),Grad_u(2)]])":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Reshape(Grad_w, 1, 4))" gives:')
-res = gf.asm('expression analysis', "Grad(Reshape(Grad_w, 1, 4))",  mim, 2, md)
-if (res != "(Reshape(Hess_w, 1, 4, 2))"): print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad(Reshape(Grad_w, 1, 4))", mim, 2, md)
+if res != "(Reshape(Hess_w, 1, 4, 2))":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Grad_w(1,2))" gives:')
-res = gf.asm('expression analysis', "Grad(Grad_w(1,2))",  mim, 2, md)
-if (res != "(Hess_w(1, 2, :))"): print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad(Grad_w(1,2))", mim, 2, md)
+if res != "(Hess_w(1, 2, :))":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Index_move_last(Grad_w, 1))" gives:')
-res = gf.asm('expression analysis', "Grad(Index_move_last(Grad_w, 1))", mim, 
2, md)
-if (res != "(Swap_indices(Index_move_last(Hess_w, 1), 2, 3))"):
-  print("Bad gradient"); exit(1)
+res = gf.asm("expression analysis", "Grad(Index_move_last(Grad_w, 1))", mim, 
2, md)
+if res != "(Swap_indices(Index_move_last(Hess_w, 1), 2, 3))":
+    print("Bad gradient")
+    exit(1)
 
 print('\nAssembly string "Grad(Contract(Grad_w, 1, 2, Grad_w, 1, 2))" gives:')
-res = gf.asm('expression analysis', "Grad(Contract(Grad_w, 1, 2, Grad_w, 1, 
2))", mim, 2, md)
-if (res != "(Contract(Hess_w, 1, 2, Grad_w, 1, 2)+Contract(Grad_w, 1, 2, 
Hess_w, 1, 2))"):
-  print("Bad gradient"); exit(1)
-
-
-str = "Grad(sin(u))"; print('\nAssembly string "%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 2, md)
-if (res != "((cos(u)@[1,1]).*Grad_u)"): print("Bad gradient"); exit(1)
-
-str = "Grad(cos(Grad_u))"; print('\nAssembly string "%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 2, md)
-if (res != "((DER_PDFUNC_COS(Grad_u)@[1,1]).*Hess_u)"):
-  print("Bad gradient"); exit(1)
-  
-str = "Grad(min(v, 2*v))"; print('\nAssembly string "%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 0, md)
-if (res != "(((DER_PDFUNC2_MAX(v, (2*v))@[1,1]).*Grad_v)+((DER_PDFUNC1_MAX(v, 
(2*v))@[1,1]).*(2*Grad_v)))"):
-  print("Bad gradient"); exit(1)
-  
-str = "Grad(Norm(v))"; print('\nAssembly string "%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 1, md)
-if (res != "(Derivative_1_Norm(v).Grad_v)"):
-  print("Bad gradient"); exit(1)
-
-str = "Diff((v*u).v, v)"; print('\nAssembly string "%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 2, md)
-
-str = "Diff((v*u).v,v,[0, 1, 3])"; print('\nAssembly string "%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 2, md)
-if (res != "((v.([0,1,3]*u))+((v*u).[0,1,3]))"):
-  print("Bad gradient"); exit(1)
-
-str = "Diff((w*u).Grad_u, u, 3)"; print('\nAssembly string "%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 2, md)
-if (res != "(Grad_u.(w*3))"):
-  print("Bad gradient"); exit(1)
-
-str = "Diff((w*u).Grad_u, u, X.w)"; print('\nAssembly string "%s" gives:' % 
str)
-res = gf.asm('expression analysis', str,  mim, 2, md)
-if (res != "((Grad_u.(w*(X.w)))+((w*u).((w.[[1,0],[0,1]])+(X.Grad_w))))"):
-  print("Bad gradient"); exit(1)
-
-str = "Diff((w*u).Grad_u,u,X(1))"; print('\nAssembly string "%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 2, md)
-if (res != "((Grad_u.(w*X(1)))+((w*u).[1,0]))"):
-  print("Bad gradient"); exit(1)
-  
-str = "Def GradU(u):=Grad_w+Grad_u; GradU(w)(2,2)"; print('\nAssembly string 
"%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 2, md)
-if (res != "((Grad_w+Grad_w)(2, 2))"):
-  print("Bad gradient"); exit(1)
-
-str = "Def GradU:=Grad_w; GradU(2,2)"; print('\nAssembly string "%s" gives:' % 
str)
-res = gf.asm('expression analysis', str,  mim, 2, md)
-if (res != "(Grad_w(2, 2))"):
-  print("Bad gradient"); exit(1)
-
-str = "Grad(u*Test_u)"; print('\nAssembly string "%s" gives:' % str)
-res = gf.asm('expression analysis', str,  mim, 1, md)
-
+res = gf.asm(
+    "expression analysis", "Grad(Contract(Grad_w, 1, 2, Grad_w, 1, 2))", mim, 
2, md
+)
+if res != "(Contract(Hess_w, 1, 2, Grad_w, 1, 2)+Contract(Grad_w, 1, 2, 
Hess_w, 1, 2))":
+    print("Bad gradient")
+    exit(1)
+
+
+str = "Grad(sin(u))"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 2, md)
+if res != "((cos(u)@[1,1]).*Grad_u)":
+    print("Bad gradient")
+    exit(1)
+
+str = "Grad(cos(Grad_u))"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 2, md)
+if res != "((DER_PDFUNC_COS(Grad_u)@[1,1]).*Hess_u)":
+    print("Bad gradient")
+    exit(1)
+
+str = "Grad(min(v, 2*v))"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 0, md)
+if (
+    res
+    != "(((DER_PDFUNC2_MAX(v, (2*v))@[1,1]).*Grad_v)+((DER_PDFUNC1_MAX(v, 
(2*v))@[1,1]).*(2*Grad_v)))"
+):
+    print("Bad gradient")
+    exit(1)
+
+str = "Grad(Norm(v))"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 1, md)
+if res != "(Derivative_1_Norm(v).Grad_v)":
+    print("Bad gradient")
+    exit(1)
+
+str = "Diff((v*u).v, v)"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 2, md)
+
+str = "Diff((v*u).v,v,[0, 1, 3])"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 2, md)
+if res != "((v.([0,1,3]*u))+((v*u).[0,1,3]))":
+    print("Bad gradient")
+    exit(1)
+
+str = "Diff((w*u).Grad_u, u, 3)"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 2, md)
+if res != "(Grad_u.(w*3))":
+    print("Bad gradient")
+    exit(1)
+
+str = "Diff((w*u).Grad_u, u, X.w)"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 2, md)
+if res != "((Grad_u.(w*(X.w)))+((w*u).((w.[[1,0],[0,1]])+(X.Grad_w))))":
+    print("Bad gradient")
+    exit(1)
+
+str = "Diff((w*u).Grad_u,u,X(1))"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 2, md)
+if res != "((Grad_u.(w*X(1)))+((w*u).[1,0]))":
+    print("Bad gradient")
+    exit(1)
+
+str = "Def GradU(u):=Grad_w+Grad_u; GradU(w)(2,2)"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 2, md)
+if res != "((Grad_w+Grad_w)(2, 2))":
+    print("Bad gradient")
+    exit(1)
+
+str = "Def GradU:=Grad_w; GradU(2,2)"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 2, md)
+if res != "(Grad_w(2, 2))":
+    print("Bad gradient")
+    exit(1)
+
+str = "Grad(u*Test_u)"
+print('\nAssembly string "%s" gives:' % str)
+res = gf.asm("expression analysis", str, mim, 1, md)
diff --git a/interface/tests/python/check_export.py 
b/interface/tests/python/check_export.py
index 9e6350b..1833a68 100644
--- a/interface/tests/python/check_export.py
+++ b/interface/tests/python/check_export.py
@@ -29,70 +29,185 @@
 import getfem as gf
 import numpy as np
 
-m0 = gf.Mesh('cartesian',[0,1,2,3],[0,1,2],[-3,-2])
-
-m0.add_convex(gf.GeoTrans('GT_QK(2,2)'),[[0,0,0,.4,.6,.5,1.2,1,1],
-                                         [0,.3,1,0,.5,1,-.1,.5,1.1],
-                                         [0,0,0,0,0,0,0,0,0]])
-
-m0.add_convex(gf.GeoTrans('GT_PK(2,2)'),[[2, 2,2,2.6,2.5,3.2],
-                                         [0,.3,1,  0, .5,  0],
-                                         [0, 0,0,  0,  0,  0]])
-
-m0.add_convex(gf.GeoTrans('GT_PK(1,3)'),[[3.1, 2.8, 3.2, 3.7],
-                                         [  0,  .3,  .7, 1.3],
-                                         [  0,   0,   0,   0]])
-
-m0.add_convex(gf.GeoTrans('GT_PRISM(3,1)'),[[0, 1, 0, 0, 1, 0],
-                                            [0, 0, 1, 0, 0, 1],
-                                            [0, 0, 0, 1, 1, 1]]);
-
-
-m0.add_convex(gf.GeoTrans('GT_PK(3,2)'),[np.array([0, .5, 1, 0, .5, 0, 0, .5, 
0, 0])-1.5,
-                                         np.array([0, 0, 0, .5, .5, 1, 0, 0, 
.5, 0])-1,
-                                         np.array([0, 0, 0, 0, 0, 0, .5, .5, 
.5, 1])-1.1])
-
-m0.add_convex(gf.GeoTrans('GT_QK(3,2)'),[np.array([0, .5, 1, 0, .5, 1, 0, .5, 
1, 0, .5, 1, 0, .5, 1, 0, .5, 1, 0, .5, 1, 0, .5, 1, 0, .5, 1])-1.5,
-                                         np.array([0, 0, 0, .5, .5, .5, 1, 1, 
1, 0, 0, 0, .5, .5, .5, 1, 1, 1, 0, 0, 0, .5, .5, .5, 1, 1, 1])-1,
-                                         np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 
.5, .5, .5, .5, .5, .5, .5, .5, .5, 1, 1, 1, 1, 1, 1, 1, 1, 1])])
-
-m0.add_convex(gf.GeoTrans('GT_PRISM_INCOMPLETE_P2'),[[1,.5,0,.5,0,0,  1,  0,  
0,1,.5,0,.5,0,0],
-                                                   [0, 1,2, 0,1,0,  0,  2,  
0,0, 1,2, 0,1,0],
-                                                   [2, 2,2, 
2,2,2,3.5,3.5,3.5,4,4, 4,4, 4,4]]);
-
-
-m1 = gf.Mesh('cartesian',[0,1,2,3],[0,1,2],[-3,-2])
-
-mf0 = gf.MeshFem(m0); mf0.set_classical_fem(1)
-mf1 = gf.MeshFem(m1); mf1.set_classical_fem(1)
-
-sl = gf.Slice(('boundary',),m0,6)
+m0 = gf.Mesh("cartesian", [0, 1, 2, 3], [0, 1, 2], [-3, -2])
+
+m0.add_convex(
+    gf.GeoTrans("GT_QK(2,2)"),
+    [
+        [0, 0, 0, 0.4, 0.6, 0.5, 1.2, 1, 1],
+        [0, 0.3, 1, 0, 0.5, 1, -0.1, 0.5, 1.1],
+        [0, 0, 0, 0, 0, 0, 0, 0, 0],
+    ],
+)
+
+m0.add_convex(
+    gf.GeoTrans("GT_PK(2,2)"),
+    [[2, 2, 2, 2.6, 2.5, 3.2], [0, 0.3, 1, 0, 0.5, 0], [0, 0, 0, 0, 0, 0]],
+)
+
+m0.add_convex(
+    gf.GeoTrans("GT_PK(1,3)"), [[3.1, 2.8, 3.2, 3.7], [0, 0.3, 0.7, 1.3], [0, 
0, 0, 0]]
+)
+
+m0.add_convex(
+    gf.GeoTrans("GT_PRISM(3,1)"),
+    [[0, 1, 0, 0, 1, 0], [0, 0, 1, 0, 0, 1], [0, 0, 0, 1, 1, 1]],
+)
+
+
+m0.add_convex(
+    gf.GeoTrans("GT_PK(3,2)"),
+    [
+        np.array([0, 0.5, 1, 0, 0.5, 0, 0, 0.5, 0, 0]) - 1.5,
+        np.array([0, 0, 0, 0.5, 0.5, 1, 0, 0, 0.5, 0]) - 1,
+        np.array([0, 0, 0, 0, 0, 0, 0.5, 0.5, 0.5, 1]) - 1.1,
+    ],
+)
+
+m0.add_convex(
+    gf.GeoTrans("GT_QK(3,2)"),
+    [
+        np.array(
+            [
+                0,
+                0.5,
+                1,
+                0,
+                0.5,
+                1,
+                0,
+                0.5,
+                1,
+                0,
+                0.5,
+                1,
+                0,
+                0.5,
+                1,
+                0,
+                0.5,
+                1,
+                0,
+                0.5,
+                1,
+                0,
+                0.5,
+                1,
+                0,
+                0.5,
+                1,
+            ]
+        )
+        - 1.5,
+        np.array(
+            [
+                0,
+                0,
+                0,
+                0.5,
+                0.5,
+                0.5,
+                1,
+                1,
+                1,
+                0,
+                0,
+                0,
+                0.5,
+                0.5,
+                0.5,
+                1,
+                1,
+                1,
+                0,
+                0,
+                0,
+                0.5,
+                0.5,
+                0.5,
+                1,
+                1,
+                1,
+            ]
+        )
+        - 1,
+        np.array(
+            [
+                0,
+                0,
+                0,
+                0,
+                0,
+                0,
+                0,
+                0,
+                0,
+                0.5,
+                0.5,
+                0.5,
+                0.5,
+                0.5,
+                0.5,
+                0.5,
+                0.5,
+                0.5,
+                1,
+                1,
+                1,
+                1,
+                1,
+                1,
+                1,
+                1,
+                1,
+            ]
+        ),
+    ],
+)
+
+m0.add_convex(
+    gf.GeoTrans("GT_PRISM_INCOMPLETE_P2"),
+    [
+        [1, 0.5, 0, 0.5, 0, 0, 1, 0, 0, 1, 0.5, 0, 0.5, 0, 0],
+        [0, 1, 2, 0, 1, 0, 0, 2, 0, 0, 1, 2, 0, 1, 0],
+        [2, 2, 2, 2, 2, 2, 3.5, 3.5, 3.5, 4, 4, 4, 4, 4, 4],
+    ],
+)
+
+
+m1 = gf.Mesh("cartesian", [0, 1, 2, 3], [0, 1, 2], [-3, -2])
+
+mf0 = gf.MeshFem(m0)
+mf0.set_classical_fem(1)
+mf1 = gf.MeshFem(m1)
+mf1.set_classical_fem(1)
+
+sl = gf.Slice(("boundary",), m0, 6)
 U = np.random.standard_normal(mf0.nbdof())
 
 # VTK:
-m0.export_to_vtk('check_export0.vtk','quality')
-m1.export_to_vtk('check_export1.vtk','quality')
-mf0.export_to_vtk('check_export2.vtk','ascii')
-mf1.export_to_vtk('check_export3.vtk','ascii')
-
+m0.export_to_vtk("check_export0.vtk", "quality")
+m1.export_to_vtk("check_export1.vtk", "quality")
+mf0.export_to_vtk("check_export2.vtk", "ascii")
+mf1.export_to_vtk("check_export3.vtk", "ascii")
 
 
 # DX:
 try:
-    m0.export_to_dx('check_export0.dx')
+    m0.export_to_dx("check_export0.dx")
 except RuntimeError as detail:
     print(detail)
 
-m1.export_to_dx('check_export0.dx','ascii','edges')
-m1.export_to_dx('check_export0.dx','ascii','append')
-sl.export_to_dx('check_export1.dx','ascii')
-sl.export_to_dx('check_export1.dx','append','edges')
-sl.export_to_dx('check_export1.dx','append','serie','rndserie',mf0,U)
-sl.export_to_dx('check_export1.dx','append','serie','rndserie',mf0,U)
+m1.export_to_dx("check_export0.dx", "ascii", "edges")
+m1.export_to_dx("check_export0.dx", "ascii", "append")
+sl.export_to_dx("check_export1.dx", "ascii")
+sl.export_to_dx("check_export1.dx", "append", "edges")
+sl.export_to_dx("check_export1.dx", "append", "serie", "rndserie", mf0, U)
+sl.export_to_dx("check_export1.dx", "append", "serie", "rndserie", mf0, U)
 
 # POS:
-m0.export_to_pos('check_export0.pos','m0')
-m1.export_to_pos('check_export1.pos','m1')
-mf0.export_to_pos('check_export2.pos','mf0')
-mf1.export_to_pos('check_export3.pos','mf1')
-sl.export_to_pos('check_export4.pos','sl',mf0,U,'U')
+m0.export_to_pos("check_export0.pos", "m0")
+m1.export_to_pos("check_export1.pos", "m1")
+mf0.export_to_pos("check_export2.pos", "mf0")
+mf1.export_to_pos("check_export3.pos", "mf1")
+sl.export_to_pos("check_export4.pos", "sl", mf0, U, "U")
diff --git a/interface/tests/python/check_global_functions.py 
b/interface/tests/python/check_global_functions.py
index 4e90f1b..73d1c89 100644
--- a/interface/tests/python/check_global_functions.py
+++ b/interface/tests/python/check_global_functions.py
@@ -31,87 +31,94 @@ import getfem as gf
 import os
 
 # mesh fem to export
-m = gf.Mesh('triangles grid', [-1, -0.5, 0, 0.5, 1], [-1, -0.5, 0, 0.5, 1])
+m = gf.Mesh("triangles grid", [-1, -0.5, 0, 0.5, 1], [-1, -0.5, 0, 0.5, 1])
 # m = gf.Mesh('import','gmsh','quad.msh')
 mf = gf.MeshFem(m)
-mf.set_fem(gf.Fem('FEM_PK(2,1)'))
+mf.set_fem(gf.Fem("FEM_PK(2,1)"))
 PTs = mf.basic_dof_nodes()
 
 # crack:
-ck0  = gf.GlobalFunction('crack',0)
-ck1  = gf.GlobalFunction('crack',1)
-ck2  = gf.GlobalFunction('crack',2)
-ck3  = gf.GlobalFunction('crack',3)
-ck4  = gf.GlobalFunction('crack',4)
-ck5  = gf.GlobalFunction('crack',5)
-ck6  = gf.GlobalFunction('crack',6)
-ck7  = gf.GlobalFunction('crack',7)
-ck8  = gf.GlobalFunction('crack',8)
-ck9  = gf.GlobalFunction('crack',9)
-ck10 = gf.GlobalFunction('crack',10)
-ck11 = gf.GlobalFunction('crack',11)
-mf.export_to_pos( 'check_global_functions0.pos', ck0(PTs), 'ck0')
-mf.export_to_pos( 'check_global_functions1.pos', ck1(PTs), 'ck1')
-mf.export_to_pos( 'check_global_functions2.pos', ck2(PTs), 'ck2')
-mf.export_to_pos( 'check_global_functions3.pos', ck3(PTs), 'ck3')
-mf.export_to_pos( 'check_global_functions4.pos', ck4(PTs), 'ck4')
-mf.export_to_pos( 'check_global_functions5.pos', ck5(PTs), 'ck5')
-mf.export_to_pos( 'check_global_functions6.pos', ck6(PTs), 'ck6')
-mf.export_to_pos( 'check_global_functions7.pos', ck7(PTs), 'ck7')
-mf.export_to_pos( 'check_global_functions8.pos', ck8(PTs), 'ck8')
-mf.export_to_pos( 'check_global_functions9.pos', ck9(PTs), 'ck9')
-mf.export_to_pos('check_global_functions10.pos',ck10(PTs),'ck10')
-mf.export_to_pos('check_global_functions11.pos',ck11(PTs),'ck11')
+ck0 = gf.GlobalFunction("crack", 0)
+ck1 = gf.GlobalFunction("crack", 1)
+ck2 = gf.GlobalFunction("crack", 2)
+ck3 = gf.GlobalFunction("crack", 3)
+ck4 = gf.GlobalFunction("crack", 4)
+ck5 = gf.GlobalFunction("crack", 5)
+ck6 = gf.GlobalFunction("crack", 6)
+ck7 = gf.GlobalFunction("crack", 7)
+ck8 = gf.GlobalFunction("crack", 8)
+ck9 = gf.GlobalFunction("crack", 9)
+ck10 = gf.GlobalFunction("crack", 10)
+ck11 = gf.GlobalFunction("crack", 11)
+mf.export_to_pos("check_global_functions0.pos", ck0(PTs), "ck0")
+mf.export_to_pos("check_global_functions1.pos", ck1(PTs), "ck1")
+mf.export_to_pos("check_global_functions2.pos", ck2(PTs), "ck2")
+mf.export_to_pos("check_global_functions3.pos", ck3(PTs), "ck3")
+mf.export_to_pos("check_global_functions4.pos", ck4(PTs), "ck4")
+mf.export_to_pos("check_global_functions5.pos", ck5(PTs), "ck5")
+mf.export_to_pos("check_global_functions6.pos", ck6(PTs), "ck6")
+mf.export_to_pos("check_global_functions7.pos", ck7(PTs), "ck7")
+mf.export_to_pos("check_global_functions8.pos", ck8(PTs), "ck8")
+mf.export_to_pos("check_global_functions9.pos", ck9(PTs), "ck9")
+mf.export_to_pos("check_global_functions10.pos", ck10(PTs), "ck10")
+mf.export_to_pos("check_global_functions11.pos", ck11(PTs), "ck11")
 
 # cutoff:
-co0 = gf.GlobalFunction('cutoff',-1,0.4,0.01,0.4)
-co1 = gf.GlobalFunction('cutoff', 0,0.4,0.01,0.4)
-co2 = gf.GlobalFunction('cutoff', 1,0.4,0.01,0.4)
-co3 = gf.GlobalFunction('cutoff', 2,0.4,0.01,0.4)
-mf.export_to_pos('check_global_functions12.pos',co0(PTs),'cutoff -1')
-mf.export_to_pos('check_global_functions13.pos',co1(PTs),'cutoff  0')
-mf.export_to_pos('check_global_functions14.pos',co2(PTs),'cutoff  1')
-mf.export_to_pos('check_global_functions15.pos',co3(PTs),'cutoff  2')
+co0 = gf.GlobalFunction("cutoff", -1, 0.4, 0.01, 0.4)
+co1 = gf.GlobalFunction("cutoff", 0, 0.4, 0.01, 0.4)
+co2 = gf.GlobalFunction("cutoff", 1, 0.4, 0.01, 0.4)
+co3 = gf.GlobalFunction("cutoff", 2, 0.4, 0.01, 0.4)
+mf.export_to_pos("check_global_functions12.pos", co0(PTs), "cutoff -1")
+mf.export_to_pos("check_global_functions13.pos", co1(PTs), "cutoff  0")
+mf.export_to_pos("check_global_functions14.pos", co2(PTs), "cutoff  1")
+mf.export_to_pos("check_global_functions15.pos", co3(PTs), "cutoff  2")
 
 
 # parser:
-p0 = gf.GlobalFunction('parser','0')
-p1 = gf.GlobalFunction('parser','1')
-p2 = gf.GlobalFunction('parser','2')
-p3 = gf.GlobalFunction('parser','3')
-p00 = gf.GlobalFunction('parser','x','[1;0]')
-p11 = gf.GlobalFunction('parser','y','[0;1]')
-p22 = 
gf.GlobalFunction('parser','r','[x/r;y/r]','[y*y/(r*r*r);-x*y/(r*r*r);-x*y/(r*r*r);x*x/(r*r*r)]')
-p33 = 
gf.GlobalFunction('parser','theta','[-y/(r*r);x/(r*r)]','[2*x*y/(pow(r,4));(y*y-x*x)/(pow(r,4));(y*y-x*x)/(pow(r,4));-2*x*y/(pow(r,4))]')
+p0 = gf.GlobalFunction("parser", "0")
+p1 = gf.GlobalFunction("parser", "1")
+p2 = gf.GlobalFunction("parser", "2")
+p3 = gf.GlobalFunction("parser", "3")
+p00 = gf.GlobalFunction("parser", "x", "[1;0]")
+p11 = gf.GlobalFunction("parser", "y", "[0;1]")
+p22 = gf.GlobalFunction(
+    "parser", "r", "[x/r;y/r]", 
"[y*y/(r*r*r);-x*y/(r*r*r);-x*y/(r*r*r);x*x/(r*r*r)]"
+)
+p33 = gf.GlobalFunction(
+    "parser",
+    "theta",
+    "[-y/(r*r);x/(r*r)]",
+    
"[2*x*y/(pow(r,4));(y*y-x*x)/(pow(r,4));(y*y-x*x)/(pow(r,4));-2*x*y/(pow(r,4))]",
+)
 
-mf.export_to_pos('check_global_functions16.pos',p0(PTs),'0')
-mf.export_to_pos('check_global_functions17.pos',p1(PTs),'1')
-mf.export_to_pos('check_global_functions18.pos',p2(PTs),'2')
-mf.export_to_pos('check_global_functions19.pos',p3(PTs),'3')
-mf.export_to_pos('check_global_functions20.pos',p00(PTs),'x')
-mf.export_to_pos('check_global_functions21.pos',p11(PTs),'y')
-mf.export_to_pos('check_global_functions22.pos',p22(PTs),'r')
-mf.export_to_pos('check_global_functions23.pos',p33(PTs),'theta')
-mf.export_to_pos('check_global_functions24.pos',p00.grad(PTs),'grad(x)')
-mf.export_to_pos('check_global_functions25.pos',p11.grad(PTs),'grad(y)')
-mf.export_to_pos('check_global_functions26.pos',p22.grad(PTs),'grad(r)')
-mf.export_to_pos('check_global_functions27.pos',p33.grad(PTs),'grad(theta)')
+mf.export_to_pos("check_global_functions16.pos", p0(PTs), "0")
+mf.export_to_pos("check_global_functions17.pos", p1(PTs), "1")
+mf.export_to_pos("check_global_functions18.pos", p2(PTs), "2")
+mf.export_to_pos("check_global_functions19.pos", p3(PTs), "3")
+mf.export_to_pos("check_global_functions20.pos", p00(PTs), "x")
+mf.export_to_pos("check_global_functions21.pos", p11(PTs), "y")
+mf.export_to_pos("check_global_functions22.pos", p22(PTs), "r")
+mf.export_to_pos("check_global_functions23.pos", p33(PTs), "theta")
+mf.export_to_pos("check_global_functions24.pos", p00.grad(PTs), "grad(x)")
+mf.export_to_pos("check_global_functions25.pos", p11.grad(PTs), "grad(y)")
+mf.export_to_pos("check_global_functions26.pos", p22.grad(PTs), "grad(r)")
+mf.export_to_pos("check_global_functions27.pos", p33.grad(PTs), "grad(theta)")
 
 # product:
-p0 = ck0*ck1
-p1 = ck1*ck2
-p2 = ck2*ck3
-mf.export_to_pos('check_global_functions28.pos',p0(PTs),'ck0*ck1')
-mf.export_to_pos('check_global_functions29.pos',p1(PTs),'ck1*ck2')
-mf.export_to_pos('check_global_functions30.pos',p2(PTs),'ck2*ck3')
+p0 = ck0 * ck1
+p1 = ck1 * ck2
+p2 = ck2 * ck3
+mf.export_to_pos("check_global_functions28.pos", p0(PTs), "ck0*ck1")
+mf.export_to_pos("check_global_functions29.pos", p1(PTs), "ck1*ck2")
+mf.export_to_pos("check_global_functions30.pos", p2(PTs), "ck2*ck3")
 
 # add:
-ad0 = ck0+ck1
-ad1 = ck1+ck2
-ad2 = ck2+ck3
-mf.export_to_pos('check_global_functions31.pos',ad0(PTs),'ck0+ck1')
-mf.export_to_pos('check_global_functions32.pos',ad1(PTs),'ck1+ck2')
-mf.export_to_pos('check_global_functions33.pos',ad2(PTs),'ck2+ck3')
+ad0 = ck0 + ck1
+ad1 = ck1 + ck2
+ad2 = ck2 + ck3
+mf.export_to_pos("check_global_functions31.pos", ad0(PTs), "ck0+ck1")
+mf.export_to_pos("check_global_functions32.pos", ad1(PTs), "ck1+ck2")
+mf.export_to_pos("check_global_functions33.pos", ad2(PTs), "ck2+ck3")
 
 for i in range(34):
-  os.remove("check_global_functions%i.pos" % i);
+    os.remove("check_global_functions%i.pos" % i)
diff --git a/interface/tests/python/check_levelset.py 
b/interface/tests/python/check_levelset.py
index 0f86843..09e41ef 100644
--- a/interface/tests/python/check_levelset.py
+++ b/interface/tests/python/check_levelset.py
@@ -30,33 +30,40 @@ import getfem as gf
 import numpy as np
 from scipy import rand
 
-eps = 1.0/10
-
-m = gf.Mesh('regular_simplices', np.arange(-1,1+eps,eps), 
np.arange(-1,1+eps,eps), 'degree', 2, 'noised')
-#m = gf.Mesh('cartesian', np.arange(-1,1+eps,eps), np.arange(-1,1+eps,eps))
-
-ls1 = gf.LevelSet(m, 2, 'y', 'x')
-#ls1 = gf.LevelSet(m, 2, 'sqr(x) + sqr(y) - sqr(0.7)', 'x-.4')
-#ls1 = gf.LevelSet(m, 2, 'x + y - 0.2') #, 'x-5')
-#ls1 = gf.LevelSet(m, 2, 'x + y - 0.2', 'x-5')
-#ls2 = gf.LevelSet(m, 2, '0.6*sqr(x) + sqr(y-0.1) - sqr(0.6)');
-#ls3 = gf.LevelSet(m, 4, 'sqr(x) + sqr(y+.08) - sqr(0.05)');
-ls2 = gf.LevelSet(m, 2, 'y+0.1', 'x')
-ls3 = gf.LevelSet(m, 2, 'y-0.1', 'x')
+eps = 1.0 / 10
+
+m = gf.Mesh(
+    "regular_simplices",
+    np.arange(-1, 1 + eps, eps),
+    np.arange(-1, 1 + eps, eps),
+    "degree",
+    2,
+    "noised",
+)
+# m = gf.Mesh('cartesian', np.arange(-1,1+eps,eps), np.arange(-1,1+eps,eps))
+
+ls1 = gf.LevelSet(m, 2, "y", "x")
+# ls1 = gf.LevelSet(m, 2, 'sqr(x) + sqr(y) - sqr(0.7)', 'x-.4')
+# ls1 = gf.LevelSet(m, 2, 'x + y - 0.2') #, 'x-5')
+# ls1 = gf.LevelSet(m, 2, 'x + y - 0.2', 'x-5')
+# ls2 = gf.LevelSet(m, 2, '0.6*sqr(x) + sqr(y-0.1) - sqr(0.6)');
+# ls3 = gf.LevelSet(m, 4, 'sqr(x) + sqr(y+.08) - sqr(0.05)');
+ls2 = gf.LevelSet(m, 2, "y+0.1", "x")
+ls3 = gf.LevelSet(m, 2, "y-0.1", "x")
 
 mls = gf.MeshLevelSet(m)
 
 mls.add(ls1)
 if True:
-  mls.sup(ls1)
-  mls.add(ls1)
-  mls.add(ls2)
-  mls.add(ls2)
-  mls.add(ls2)
-  mls.add(ls3)
+    mls.sup(ls1)
+    mls.add(ls1)
+    mls.add(ls2)
+    mls.add(ls2)
+    mls.add(ls2)
+    mls.add(ls3)
 mls.adapt()
 
-#print(mls.linked_mesh())
+# print(mls.linked_mesh())
 
 lls = mls.levelsets()
 
@@ -67,25 +74,25 @@ ctip = mls.crack_tip_convexes()
 mf = gf.MeshFem(m)
 mf.set_classical_fem(1)
 
-mfls = gf.MeshFem('levelset',mls,mf)
+mfls = gf.MeshFem("levelset", mls, mf)
 
 gf.memstats()
 
 nbd = mfls.nbdof()
 
 if True:
-  sl = gf.Slice(('none',), mls, 2);
-  U = rand(1,nbd);
-  sl.export_to_pos('slU.pos',mfls,U,'U')
-  mfls.export_to_pos('U.pos',U,'U')
-  cm.export_to_pos('cm.pos')
-  m.export_to_pos('m.pos')
+    sl = gf.Slice(("none",), mls, 2)
+    U = rand(1, nbd)
+    sl.export_to_pos("slU.pos", mfls, U, "U")
+    mfls.export_to_pos("U.pos", U, "U")
+    cm.export_to_pos("cm.pos")
+    m.export_to_pos("m.pos")
 else:
-  sl = gf.Slice(('none',), mls, 1);
-  for i in range(nbd):
-    U = np.zeros(nbd)
-    U[i] = 1
-    sl.export_to_pos('slU'+str(i)+'.pos',mfls,U,'U'+str(i))
-    mfls.export_to_pos('U'+str(i)+'.pos',U,'U'+str(i))
-  cm.export_to_pos('cm.pos')
-  m.export_to_pos('m.pos')
+    sl = gf.Slice(("none",), mls, 1)
+    for i in range(nbd):
+        U = np.zeros(nbd)
+        U[i] = 1
+        sl.export_to_pos("slU" + str(i) + ".pos", mfls, U, "U" + str(i))
+        mfls.export_to_pos("U" + str(i) + ".pos", U, "U" + str(i))
+    cm.export_to_pos("cm.pos")
+    m.export_to_pos("m.pos")
diff --git a/interface/tests/python/check_mixed_mesh.py 
b/interface/tests/python/check_mixed_mesh.py
index bf6cd81..3b0d0c7 100644
--- a/interface/tests/python/check_mixed_mesh.py
+++ b/interface/tests/python/check_mixed_mesh.py
@@ -35,8 +35,8 @@ import os
 # parameters
 E = 1.0e3
 Nu = 0.25
-Lambda = E*Nu/((1.0+Nu)*(1.0-2.0*Nu))
-Mu = E/(2*(1+Nu))
+Lambda = E * Nu / ((1.0 + Nu) * (1.0 - 2.0 * Nu))
+Mu = E / (2 * (1 + Nu))
 
 
 # define constants
@@ -44,150 +44,201 @@ NEUMANN_BOUNDARY = 1
 NEUMANN_BOUNDARY_NO_LOAD = 2
 DIRICHLET_BOUNDARY = 3
 OMEGA = 4
-INNER_FACES=6
+INNER_FACES = 6
 
 degree = 1
 
-make_check=('srcdir' in os.environ);
-filename='../meshes/mixed_mesh.gmf'
-if (make_check):
-    filename=os.environ['srcdir']+'/'+filename
+make_check = "srcdir" in os.environ
+filename = "../meshes/mixed_mesh.gmf"
+if make_check:
+    filename = os.environ["srcdir"] + "/" + filename
 
-m = gf.Mesh('load', filename)
+m = gf.Mesh("load", filename)
 
-#--------------- boundary condtions
+# --------------- boundary condtions
 # detect some boundary of the mesh
 
-face_left = m.outer_faces_with_direction([0, 0., -1.0], 0.01)
-face_right = m.outer_faces_with_direction([0., 0., 1.0], 0.01)
+face_left = m.outer_faces_with_direction([0, 0.0, -1.0], 0.01)
+face_right = m.outer_faces_with_direction([0.0, 0.0, 1.0], 0.01)
 
-face_top = m.outer_faces_with_direction([0., 1., 0], 0.01)
-face_bottom = m.outer_faces_with_direction([0., -1., 0], 0.01)
-face_top1 = m.outer_faces_with_direction([1., 0., 0], 0.01)
-face_bottom1 = m.outer_faces_with_direction([-1., 0., 0], 0.01)
-face_top_bottom =  
np.append(np.append(np.append(face_top,face_bottom,axis=1),face_top1 , axis=1), 
face_bottom1, axis=1)
+face_top = m.outer_faces_with_direction([0.0, 1.0, 0], 0.01)
+face_bottom = m.outer_faces_with_direction([0.0, -1.0, 0], 0.01)
+face_top1 = m.outer_faces_with_direction([1.0, 0.0, 0], 0.01)
+face_bottom1 = m.outer_faces_with_direction([-1.0, 0.0, 0], 0.01)
+face_top_bottom = np.append(
+    np.append(np.append(face_top, face_bottom, axis=1), face_top1, axis=1),
+    face_bottom1,
+    axis=1,
+)
 
 # create boundary regions
-m.set_region(NEUMANN_BOUNDARY,face_right)
-m.set_region(NEUMANN_BOUNDARY_NO_LOAD,face_top_bottom)
-m.set_region(DIRICHLET_BOUNDARY,face_left)
+m.set_region(NEUMANN_BOUNDARY, face_right)
+m.set_region(NEUMANN_BOUNDARY_NO_LOAD, face_top_bottom)
+m.set_region(DIRICHLET_BOUNDARY, face_left)
 
 in_faces = m.inner_faces()
 m.set_region(INNER_FACES, in_faces)
 
 
-listTetra = [];
-listHexa = [];
-listPrism = [];
-listPyramid = [];
+listTetra = []
+listHexa = []
+listPrism = []
+listPyramid = []
 
 for i in range(m.nbcvs()):
-    gt = m.geotrans(i) # id of element
-    if str(gt[0])=='GT_PK(3,1)':
-        #print 'index of TETRA: ', i
+    gt = m.geotrans(i)  # id of element
+    if str(gt[0]) == "GT_PK(3,1)":
+        # print 'index of TETRA: ', i
         listTetra.append(i)
-    elif str(gt[0])=='GT_PYRAMID(1)':
-        #print 'index of PYRAMID: ', i
+    elif str(gt[0]) == "GT_PYRAMID(1)":
+        # print 'index of PYRAMID: ', i
         listPyramid.append(i)
-    elif str(gt[0])=='GT_PRISM(3,1)':
-        #print 'index of PRISM: ', i
+    elif str(gt[0]) == "GT_PRISM(3,1)":
+        # print 'index of PRISM: ', i
         listPrism.append(i)
-    elif str(gt[0])=='GT_QK(3,1)':
-        #print 'index of HEXA: ', i
+    elif str(gt[0]) == "GT_QK(3,1)":
+        # print 'index of HEXA: ', i
         listHexa.append(i)
     else:
-        print('Geometric transformation: ', gt[0])
+        print("Geometric transformation: ", gt[0])
 
-print('num Tetra: ', len(listTetra))
-print('num Hexa: ', len(listHexa))
-print('num Hexa: ', len(listHexa))
-print('num Hexa: ', len(listHexa))
+print("num Tetra: ", len(listTetra))
+print("num Hexa: ", len(listHexa))
+print("num Hexa: ", len(listHexa))
+print("num Hexa: ", len(listHexa))
 
 
 mfu = gf.MeshFem(m, 3)
 
-mfu.set_fem(gf.Fem('FEM_QK(3,{d})'.format(d=degree)),listHexa)
-mfu.set_fem(gf.Fem('FEM_PYRAMID_LAGRANGE({d})'.format(d=degree)),listPyramid)
-mfu.set_fem(gf.Fem('FEM_PK_PRISM(3,{d})'.format(d=degree)),listPrism)
-mfu.set_fem(gf.Fem('FEM_PK(3,{d})'.format(d=degree)),listTetra)
+mfu.set_fem(gf.Fem("FEM_QK(3,{d})".format(d=degree)), listHexa)
+mfu.set_fem(gf.Fem("FEM_PYRAMID_LAGRANGE({d})".format(d=degree)), listPyramid)
+mfu.set_fem(gf.Fem("FEM_PK_PRISM(3,{d})".format(d=degree)), listPrism)
+mfu.set_fem(gf.Fem("FEM_PK(3,{d})".format(d=degree)), listTetra)
 
 mim = gf.MeshIm(m, 3)
 
 
 # Model
-md = gf.Model('real')
-md.add_fem_variable('u',mfu)
-md.add_initialized_data('mu_para', Mu)
-md.add_initialized_data('lambda_para', Lambda)
-md.add_linear_generic_assembly_brick(mim,"lambda_para*Div_u*Div_Test_u + 
2*mu_para*Sym(Grad_u):Grad_Test_u")
-md.add_initialized_data('Fdata',[0.0,-1.0, 0.0])
-md.add_source_term_brick(mim, 'u', 'Fdata', NEUMANN_BOUNDARY)
-md.add_initialized_data('DirichletData', [0, 0, 0])
-md.add_Dirichlet_condition_with_simplification('u', 
DIRICHLET_BOUNDARY,'DirichletData')
-
-md.solve('max_res', 1E-9, 'max_iter', 100, 'noisy', 'lsolver', 'mumps', 
'lsearch', 'simplest',  'alpha min', 0.8)
-U = md.variable('u');
-
-
-mfer = gf.MeshFem(m,1)
-mfer.set_fem(gf.Fem('FEM_PK(3,{d})'.format(d=0)),listTetra)
-mfer.set_fem(gf.Fem('FEM_QK(3,{d})'.format(d=0)),listHexa)
-mfer.set_fem(gf.Fem('FEM_PYRAMID_LAGRANGE({d})'.format(d=0)),listPyramid)
-mfer.set_fem(gf.Fem('FEM_PK_PRISM(3,{d})'.format(d=0)),listPrism)
-
-divsigma = '(lambda_para+ mu_para)*(Hess_u(1,1,:) + Hess_u(2,2,:) + 
Hess_u(3,3,:) ) + mu_para*(Hess_u:Id( qdim(u) ))' 
+md = gf.Model("real")
+md.add_fem_variable("u", mfu)
+md.add_initialized_data("mu_para", Mu)
+md.add_initialized_data("lambda_para", Lambda)
+md.add_linear_generic_assembly_brick(
+    mim, "lambda_para*Div_u*Div_Test_u + 2*mu_para*Sym(Grad_u):Grad_Test_u"
+)
+md.add_initialized_data("Fdata", [0.0, -1.0, 0.0])
+md.add_source_term_brick(mim, "u", "Fdata", NEUMANN_BOUNDARY)
+md.add_initialized_data("DirichletData", [0, 0, 0])
+md.add_Dirichlet_condition_with_simplification("u", DIRICHLET_BOUNDARY, 
"DirichletData")
+
+md.solve(
+    "max_res",
+    1e-9,
+    "max_iter",
+    100,
+    "noisy",
+    "lsolver",
+    "mumps",
+    "lsearch",
+    "simplest",
+    "alpha min",
+    0.8,
+)
+U = md.variable("u")
+
+
+mfer = gf.MeshFem(m, 1)
+mfer.set_fem(gf.Fem("FEM_PK(3,{d})".format(d=0)), listTetra)
+mfer.set_fem(gf.Fem("FEM_QK(3,{d})".format(d=0)), listHexa)
+mfer.set_fem(gf.Fem("FEM_PYRAMID_LAGRANGE({d})".format(d=0)), listPyramid)
+mfer.set_fem(gf.Fem("FEM_PK_PRISM(3,{d})".format(d=0)), listPrism)
+
+divsigma = "(lambda_para+ mu_para)*(Hess_u(1,1,:) + Hess_u(2,2,:) + 
Hess_u(3,3,:) ) + mu_para*(Hess_u:Id( qdim(u) ))"
 # 1a) interior residual
-bulkresidual = 
'sqr(element_size)*Norm_sqr({divsigma})*Test_psi'.format(divsigma=divsigma)
+bulkresidual = "sqr(element_size)*Norm_sqr({divsigma})*Test_psi".format(
+    divsigma=divsigma
+)
 
-ETA1tmp = gf.asm_generic(mim,1,bulkresidual,-1
-                        ,md
-                        ,'psi',True,mfer,np.zeros(mfer.nbdof())) 
-ETA1 = ETA1tmp [ ETA1tmp.size - mfer.nbdof() : ETA1tmp.size ]
+ETA1tmp = gf.asm_generic(
+    mim, 1, bulkresidual, -1, md, "psi", True, mfer, np.zeros(mfer.nbdof())
+)
+ETA1 = ETA1tmp[ETA1tmp.size - mfer.nbdof() : ETA1tmp.size]
 
 
-# 1b) jump at inner faces    
+# 1b) jump at inner faces
 sig_u = "(lambda_para*Trace(Grad_u)*Id(qdim(u)) + mu_para*(Grad_u + Grad_u'))"
 grad_u_neighbor = "Interpolate(Grad_u,neighbour_elt)"
-sig_u_neighbor = "(lambda_para*Trace({Grad_u})*Id(qdim(u)) + 
mu_para*(({Grad_u}) + ({Grad_u})'))".format(Grad_u=grad_u_neighbor)
+sig_u_neighbor = "(lambda_para*Trace({Grad_u})*Id(qdim(u)) + 
mu_para*(({Grad_u}) + ({Grad_u})'))".format(
+    Grad_u=grad_u_neighbor
+)
 
-stress_jump_inner = "((({sig_u}) - ({sig_u_neighbor}))*Normal 
)".format(sig_u=sig_u,sig_u_neighbor=sig_u_neighbor)
-edgeresidual = 
"0.5*(element_size*Norm_sqr({stress_jump_inner})*2*0.5*(Test_psi + 
Interpolate(Test_psi,neighbour_elt)))".format(stress_jump_inner=stress_jump_inner)
+stress_jump_inner = "((({sig_u}) - ({sig_u_neighbor}))*Normal )".format(
+    sig_u=sig_u, sig_u_neighbor=sig_u_neighbor
+)
+edgeresidual = 
"0.5*(element_size*Norm_sqr({stress_jump_inner})*2*0.5*(Test_psi + 
Interpolate(Test_psi,neighbour_elt)))".format(
+    stress_jump_inner=stress_jump_inner
+)
 
-ETA2tmp = gf.asm_generic(mim,1,edgeresidual,INNER_FACES
-                        ,md
-                        ,'psi',True,mfer,np.zeros(mfer.nbdof()))
-ETA2 = ETA2tmp [ ETA2tmp.size - mfer.nbdof() : ETA2tmp.size ]
+ETA2tmp = gf.asm_generic(
+    mim, 1, edgeresidual, INNER_FACES, md, "psi", True, mfer, 
np.zeros(mfer.nbdof())
+)
+ETA2 = ETA2tmp[ETA2tmp.size - mfer.nbdof() : ETA2tmp.size]
 
 
-# 1c) jump at NEUMANN_BOUNDARY  
+# 1c) jump at NEUMANN_BOUNDARY
 
 g = "[0; -1.0; 0]"
-stress_jump_at_Neumann = "(({g}) - ({Lambda}*Trace(Grad_u)*Id(qdim(u)) + 
{Mu}*(Grad_u+Grad_u'))*Normal )".format(g = g, Lambda= Lambda, Mu = Mu)
-
-edgeresidual_Neumann = 
"(element_size*Norm_sqr({stress_jump_at_Neumann})*Test_psi)".format(stress_jump_at_Neumann=stress_jump_at_Neumann)
-
-ETA3tmp = gf.asm_generic(mim,1,edgeresidual_Neumann,NEUMANN_BOUNDARY
-                        ,md
-                        ,'psi',True,mfer,np.zeros(mfer.nbdof()))
-
-ETA3 = ETA3tmp [ ETA3tmp.size - mfer.nbdof() : ETA3tmp.size ]
-
-print('sum(ETA3): ', sum(ETA3))
+stress_jump_at_Neumann = "(({g}) - ({Lambda}*Trace(Grad_u)*Id(qdim(u)) + 
{Mu}*(Grad_u+Grad_u'))*Normal )".format(
+    g=g, Lambda=Lambda, Mu=Mu
+)
+
+edgeresidual_Neumann = 
"(element_size*Norm_sqr({stress_jump_at_Neumann})*Test_psi)".format(
+    stress_jump_at_Neumann=stress_jump_at_Neumann
+)
+
+ETA3tmp = gf.asm_generic(
+    mim,
+    1,
+    edgeresidual_Neumann,
+    NEUMANN_BOUNDARY,
+    md,
+    "psi",
+    True,
+    mfer,
+    np.zeros(mfer.nbdof()),
+)
+
+ETA3 = ETA3tmp[ETA3tmp.size - mfer.nbdof() : ETA3tmp.size]
+
+print("sum(ETA3): ", sum(ETA3))
 
 # 1d) jump at NEUMANN_BOUNDARY_NO_LOAD
 g = "[0; 0; 0]"
-stress_jump_at_Neumann = "(({g}) - ({Lambda}*Trace(Grad_u)*Id(qdim(u)) + 
{Mu}*(Grad_u+Grad_u'))*Normal )".format(g = g, Lambda= Lambda, Mu = Mu)
+stress_jump_at_Neumann = "(({g}) - ({Lambda}*Trace(Grad_u)*Id(qdim(u)) + 
{Mu}*(Grad_u+Grad_u'))*Normal )".format(
+    g=g, Lambda=Lambda, Mu=Mu
+)
 
-edgeresidual_Neumann = 
"(element_size*Norm_sqr({stress_jump_at_Neumann})*Test_psi)".format(stress_jump_at_Neumann=stress_jump_at_Neumann)
+edgeresidual_Neumann = 
"(element_size*Norm_sqr({stress_jump_at_Neumann})*Test_psi)".format(
+    stress_jump_at_Neumann=stress_jump_at_Neumann
+)
 
-ETA4tmp = gf.asm_generic(mim,1,edgeresidual_Neumann,NEUMANN_BOUNDARY_NO_LOAD
-                        ,md ,'psi',True,mfer,np.zeros(mfer.nbdof()))
+ETA4tmp = gf.asm_generic(
+    mim,
+    1,
+    edgeresidual_Neumann,
+    NEUMANN_BOUNDARY_NO_LOAD,
+    md,
+    "psi",
+    True,
+    mfer,
+    np.zeros(mfer.nbdof()),
+)
 
-ETA4 = ETA4tmp [ ETA4tmp.size - mfer.nbdof() : ETA4tmp.size ]
+ETA4 = ETA4tmp[ETA4tmp.size - mfer.nbdof() : ETA4tmp.size]
 
-print('sum(ETA4): ', sum(ETA4))
+print("sum(ETA4): ", sum(ETA4))
 
 
-ETA_square = ETA1 + ETA2 + ETA3 + ETA4 # element wise
+ETA_square = ETA1 + ETA2 + ETA3 + ETA4  # element wise
 
-ETA  = np.sqrt( ETA_square )# element wise
+ETA = np.sqrt(ETA_square)  # element wise
diff --git a/interface/tests/python/check_secondary_domain.py 
b/interface/tests/python/check_secondary_domain.py
index 28ee9dd..a93c555 100644
--- a/interface/tests/python/check_secondary_domain.py
+++ b/interface/tests/python/check_secondary_domain.py
@@ -34,58 +34,99 @@ import os
 
 NX = 4
 
-m1 =  gf.Mesh('cartesian', np.arange(0,1+1./NX,1./NX)) # Structured 1D mesh
-mfu1 = gf.MeshFem(m1, 1); mfu1.set_fem(gf.Fem('FEM_PK(1,1)'))
-mim1 = gf.MeshIm(m1, gf.Integ('IM_GAUSS1D(4)'))
-U1 = mfu1.eval('x')
-
-
-m2 = gf.Mesh('triangles grid', np.arange(0,1+1./NX,1./NX),
-            np.arange(0,1+1./NX,1./NX))     # Structured 2D mesh
-mfu2 = gf.MeshFem(m2, 1); mfu2.set_fem(gf.Fem('FEM_PK(2,1)'))
-mim2 = gf.MeshIm(m2, gf.Integ('IM_TRIANGLE(4)'))
-U2 = mfu2.eval('x+y')
-
-
-
-md = gf.Model('real')
-
-md.add_fem_variable('u1', mfu1)
-md.set_variable('u1', U1)
-md.add_fem_variable('u2', mfu2)
-md.set_variable('u2', U2)
-
-md.add_standard_secondary_domain('secdom', mim2);
-
-
-result = gf.asm('generic', mim1, 0, "u1*Secondary_Domain(u2)", -1, md,
-                "Secondary_domain", "secdom")
-if (abs(result-0.5) > 1e-8) : print("Bad value"); exit(1)
-
-result = gf.asm('generic', mim1, 0, "u1*(Secondary_Domain(Grad_u2)(1))", -1, 
md,
-                "Secondary_domain", "secdom")
-if (abs(result-0.5) > 1e-8) : print("Bad value"); exit(1)
-
-result = gf.asm('generic', mim1, 0,
-                "u1*(Secondary_Domain(X)(1)+Secondary_Domain(X)(2))", -1, md,
-                "Secondary_domain", "secdom")
-if (abs(result-0.5) > 1e-8) : print("Bad value"); exit(1)
-
-result = gf.asm('generic', mim1, 0, "u1*sqr(Secondary_Domain(u2))", -1, md,
-                "Secondary_domain", "secdom")
-if (abs(result-7./12.) > 1e-8) : print("Bad value"); exit(1)
-
-
-
-
-
-M = gf.asm('generic', mim1, 2, "Test_u1*Secondary_Domain(Test2_u2)", -1, md,
-           "Secondary_domain", "secdom")
-V1 = gf.asm('generic', mim1, 1, "Test_u1", -1, md)
-V2 = gf.asm('generic', mim2, 1, "Test_u2", -1, md)
+m1 = gf.Mesh("cartesian", np.arange(0, 1 + 1.0 / NX, 1.0 / NX))  # Structured 
1D mesh
+mfu1 = gf.MeshFem(m1, 1)
+mfu1.set_fem(gf.Fem("FEM_PK(1,1)"))
+mim1 = gf.MeshIm(m1, gf.Integ("IM_GAUSS1D(4)"))
+U1 = mfu1.eval("x")
+
+
+m2 = gf.Mesh(
+    "triangles grid",
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+)  # Structured 2D mesh
+mfu2 = gf.MeshFem(m2, 1)
+mfu2.set_fem(gf.Fem("FEM_PK(2,1)"))
+mim2 = gf.MeshIm(m2, gf.Integ("IM_TRIANGLE(4)"))
+U2 = mfu2.eval("x+y")
+
+
+md = gf.Model("real")
+
+md.add_fem_variable("u1", mfu1)
+md.set_variable("u1", U1)
+md.add_fem_variable("u2", mfu2)
+md.set_variable("u2", U2)
+
+md.add_standard_secondary_domain("secdom", mim2)
+
+
+result = gf.asm(
+    "generic", mim1, 0, "u1*Secondary_Domain(u2)", -1, md, "Secondary_domain", 
"secdom"
+)
+if abs(result - 0.5) > 1e-8:
+    print("Bad value")
+    exit(1)
+
+result = gf.asm(
+    "generic",
+    mim1,
+    0,
+    "u1*(Secondary_Domain(Grad_u2)(1))",
+    -1,
+    md,
+    "Secondary_domain",
+    "secdom",
+)
+if abs(result - 0.5) > 1e-8:
+    print("Bad value")
+    exit(1)
+
+result = gf.asm(
+    "generic",
+    mim1,
+    0,
+    "u1*(Secondary_Domain(X)(1)+Secondary_Domain(X)(2))",
+    -1,
+    md,
+    "Secondary_domain",
+    "secdom",
+)
+if abs(result - 0.5) > 1e-8:
+    print("Bad value")
+    exit(1)
+
+result = gf.asm(
+    "generic",
+    mim1,
+    0,
+    "u1*sqr(Secondary_Domain(u2))",
+    -1,
+    md,
+    "Secondary_domain",
+    "secdom",
+)
+if abs(result - 7.0 / 12.0) > 1e-8:
+    print("Bad value")
+    exit(1)
+
+
+M = gf.asm(
+    "generic",
+    mim1,
+    2,
+    "Test_u1*Secondary_Domain(Test2_u2)",
+    -1,
+    md,
+    "Secondary_domain",
+    "secdom",
+)
+V1 = gf.asm("generic", mim1, 1, "Test_u1", -1, md)
+V2 = gf.asm("generic", mim2, 1, "Test_u2", -1, md)
 
 for i in range(0, V1.size):
-  for j in range(0, V2.size):
-    if (abs(M[i,j] - V1[i]*V2[j]) > 1E-8):
-      print("Bad value for matrix assembly"); exit(1)
-    
+    for j in range(0, V2.size):
+        if abs(M[i, j] - V1[i] * V2[j]) > 1e-8:
+            print("Bad value for matrix assembly")
+            exit(1)
diff --git a/interface/tests/python/demo_Mindlin_Reissner_plate.py 
b/interface/tests/python/demo_Mindlin_Reissner_plate.py
index 309fdf5..0cb3b73 100644
--- a/interface/tests/python/demo_Mindlin_Reissner_plate.py
+++ b/interface/tests/python/demo_Mindlin_Reissner_plate.py
@@ -31,32 +31,38 @@ import getfem as gf
 import os
 
 ## Parameters
-Emodulus = 1.          # Young Modulus
-nu       = 0.5         # Poisson Coefficient
-epsilon  = 0.001       # Plate thickness
-kappa     = 5./6.      # Shear correction factor
-f = -5.*pow(epsilon,3.) # Prescribed force on the top of the plate
+Emodulus = 1.0  # Young Modulus
+nu = 0.5  # Poisson Coefficient
+epsilon = 0.001  # Plate thickness
+kappa = 5.0 / 6.0  # Shear correction factor
+f = -5.0 * pow(epsilon, 3.0)  # Prescribed force on the top of the plate
 
-variant = 0            # 0 : not reduced, 1 : with reduced integration,
-                       # 2 : MITC reduction
-quadrangles = True     # Locking free only on quadrangle for the moment
-K = 1                  # Degree of the finite element method
+variant = 0  # 0 : not reduced, 1 : with reduced integration,
+# 2 : MITC reduction
+quadrangles = True  # Locking free only on quadrangle for the moment
+K = 1  # Degree of the finite element method
 dirichlet_version = 1  # 0 = simplification, 1 = with multipliers,
-                       # 2 = penalization
-r = 1.E8               # Penalization parameter.
-NX = 80                # Number of element per direction
+# 2 = penalization
+r = 1.0e8  # Penalization parameter.
+NX = 80  # Number of element per direction
 
 
-if (quadrangles):
-  m = gf.Mesh('cartesian', np.arange(0., 1.+1./NX, 1./NX),np.arange(0., 
1.+1./NX, 1./NX))
+if quadrangles:
+    m = gf.Mesh(
+        "cartesian",
+        np.arange(0.0, 1.0 + 1.0 / NX, 1.0 / NX),
+        np.arange(0.0, 1.0 + 1.0 / NX, 1.0 / NX),
+    )
 else:
-  m = gf.Mesh('import','structured',
-              'GT="GT_PK(2,1)";SIZES=[1,1];NOISED=0;NSUBDIV=[%d,%d];'
-              % (NX, NX))
+    m = gf.Mesh(
+        "import",
+        "structured",
+        'GT="GT_PK(2,1)";SIZES=[1,1];NOISED=0;NSUBDIV=[%d,%d];' % (NX, NX),
+    )
 
 ## Create a mesh_fem for a 2D vector field
 mftheta = gf.MeshFem(m, 2)
-mfu = gf.MeshFem(m, 1);
+mfu = gf.MeshFem(m, 1)
 mftheta.set_classical_fem(K)
 mfu.set_classical_fem(K)
 mim = gf.MeshIm(m, 6)
@@ -67,31 +73,35 @@ border = m.outer_faces()
 m.set_region(1, border)
 
 ## Build the model
-md=gf.Model('real')
-md.add_fem_variable('u', mfu)
-md.add_fem_variable('theta', mftheta)
-md.add_initialized_data('E', Emodulus)
-md.add_initialized_data('nu', nu)
-md.add_initialized_data('epsilon', epsilon)
-md.add_initialized_data('kappa', kappa)
+md = gf.Model("real")
+md.add_fem_variable("u", mfu)
+md.add_fem_variable("theta", mftheta)
+md.add_initialized_data("E", Emodulus)
+md.add_initialized_data("nu", nu)
+md.add_initialized_data("epsilon", epsilon)
+md.add_initialized_data("kappa", kappa)
 
-md.add_Mindlin_Reissner_plate_brick(mim, mim_reduced, 'u', 'theta', 'E', 'nu', 
'epsilon', 'kappa', variant)
+md.add_Mindlin_Reissner_plate_brick(
+    mim, mim_reduced, "u", "theta", "E", "nu", "epsilon", "kappa", variant
+)
 
-md.add_initialized_data('VolumicData', f)
-md.add_source_term_brick(mim, 'u', 'VolumicData');
-md.add_initialized_data('DirichletData', 0);
+md.add_initialized_data("VolumicData", f)
+md.add_source_term_brick(mim, "u", "VolumicData")
+md.add_initialized_data("DirichletData", 0)
 
-if (dirichlet_version == 0):
-    md.add_Dirichlet_condition_with_simplification('u', 1, 'DirichletData');   
-elif (dirichlet_version == 1):
-    md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, 1, 
'DirichletData');
-elif (dirichlet_version == 2):
-    md.add_Dirichlet_condition_with_penalization(mim, 'u', r, 1, 
'DirichletData');
+if dirichlet_version == 0:
+    md.add_Dirichlet_condition_with_simplification("u", 1, "DirichletData")
+elif dirichlet_version == 1:
+    md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, 1, 
"DirichletData")
+elif dirichlet_version == 2:
+    md.add_Dirichlet_condition_with_penalization(mim, "u", r, 1, 
"DirichletData")
 
-print ('Number of Dof: %d' % md.nbdof()) 
+print("Number of Dof: %d" % md.nbdof())
 
 md.solve()
-U = md.variable('u');
+U = md.variable("u")
 
-mfu.export_to_vtk('Deflection.vtk', U)
-print ('You can view solutions with for instance:\nmayavi2 -d Deflection.vtk 
-f WarpScalar -m Surface')
+mfu.export_to_vtk("Deflection.vtk", U)
+print(
+    "You can view solutions with for instance:\nmayavi2 -d Deflection.vtk -f 
WarpScalar -m Surface"
+)
diff --git a/interface/tests/python/demo_crack.py 
b/interface/tests/python/demo_crack.py
index 8388d2f..2cb391c 100644
--- a/interface/tests/python/demo_crack.py
+++ b/interface/tests/python/demo_crack.py
@@ -27,13 +27,14 @@
   $Id$
 """
 try:
-  import getfem as gf
+    import getfem as gf
 except ImportError:
-  import sys
-  sys.path.append('../../src/python/')
-  import getfem as gf
+    import sys
+
+    sys.path.append("../../src/python/")
+    import getfem as gf
 else:
-  print("module getfem not found!")
+    print("module getfem not found!")
 
 import numpy as np
 import math
@@ -51,124 +52,155 @@ variant = 4
 #               the jump (example of use of xfem_plus and xfem_minus).
 
 # Parameters:  ######################
-nx = 20                             #
-                                    #
-DIRICHLET  = 101                    #
-                                    #
-Lambda = 1.25E10 # Lame coefficient #
-Mu = 1.875E10    # Lame coefficient #
+nx = 20  #
+#
+DIRICHLET = 101  #
+#
+Lambda = 1.25e10  # Lame coefficient #
+Mu = 1.875e10  # Lame coefficient #
 #####################################
 
 # Mesh definition:
-m = gf.Mesh('regular_simplices', -0.5+np.arange(nx+1)/float(nx),
-                                 -0.5+np.arange(nx+1)/float(nx))
-#m = gf.Mesh('import','gmsh','quad.msh')
+m = gf.Mesh(
+    "regular_simplices",
+    -0.5 + np.arange(nx + 1) / float(nx),
+    -0.5 + np.arange(nx + 1) / float(nx),
+)
+# m = gf.Mesh('import','gmsh','quad.msh')
 
 # Boundary set:
 m.set_region(DIRICHLET, m.outer_faces())
 
 # Global functions for asymptotic enrichment:
-ck0 = gf.GlobalFunction('crack',0)
-ck1 = gf.GlobalFunction('crack',1)
-ck2 = gf.GlobalFunction('crack',2)
-ck3 = gf.GlobalFunction('crack',3)
-if variant == 1: # Cutoff enrichement 
-   coff = gf.GlobalFunction('cutoff',2,0.4,0.01,0.4)
-   ckoff0 = ck0*coff # gf.GlobalFunction('product',ck0,coff)
-   ckoff1 = ck1*coff
-   ckoff2 = ck2*coff
-   ckoff3 = ck3*coff
+ck0 = gf.GlobalFunction("crack", 0)
+ck1 = gf.GlobalFunction("crack", 1)
+ck2 = gf.GlobalFunction("crack", 2)
+ck3 = gf.GlobalFunction("crack", 3)
+if variant == 1:  # Cutoff enrichement
+    coff = gf.GlobalFunction("cutoff", 2, 0.4, 0.01, 0.4)
+    ckoff0 = ck0 * coff  # gf.GlobalFunction('product',ck0,coff)
+    ckoff1 = ck1 * coff
+    ckoff2 = ck2 * coff
+    ckoff3 = ck3 * coff
 
 # Levelset definition:
-ls = gf.LevelSet(m,1,'y','x')
+ls = gf.LevelSet(m, 1, "y", "x")
 
 mls = gf.MeshLevelSet(m)
 mls.add(ls)
 if variant > 2:
-   ls2 =  gf.LevelSet(m,1,'x+0.125','abs(y)-0.375')
-   mls.add(ls2);
+    ls2 = gf.LevelSet(m, 1, "x+0.125", "abs(y)-0.375")
+    mls.add(ls2)
 mls.adapt()
 
 # Basic mesh_fem without enrichment:
 mf_pre_u = gf.MeshFem(m)
-mf_pre_u.set_fem(gf.Fem('FEM_PK(2,1)'))
+mf_pre_u.set_fem(gf.Fem("FEM_PK(2,1)"))
 
 # Definition of the enriched finite element method (MeshFemLevelSet):
-mfls_u = gf.MeshFem('levelset',mls,mf_pre_u)
-
-if variant == 1: # Cutoff enrichement 
-   # MeshFemGlobalFunction:
-   mf_sing_u = gf.MeshFem('global 
function',m,ls,[ckoff0,ckoff1,ckoff2,ckoff3],1)
-   # MeshFemDirectSum:
-   mf_u      = gf.MeshFem('sum',mf_sing_u,mfls_u)
+mfls_u = gf.MeshFem("levelset", mls, mf_pre_u)
+
+if variant == 1:  # Cutoff enrichement
+    # MeshFemGlobalFunction:
+    mf_sing_u = gf.MeshFem(
+        "global function", m, ls, [ckoff0, ckoff1, ckoff2, ckoff3], 1
+    )
+    # MeshFemDirectSum:
+    mf_u = gf.MeshFem("sum", mf_sing_u, mfls_u)
 else:
-   mf_sing_u = gf.MeshFem('global function',m,ls,[ck0,ck1,ck2,ck3],1)
-   mf_part_unity = gf.MeshFem(m)
-   mf_part_unity.set_classical_fem(1)
-   DOFpts = mf_part_unity.basic_dof_nodes()
-   # Search the dofs to be enriched with the asymptotic displacement.
-   Idofs_center = np.nonzero(np.square(DOFpts[0,:]) +
-                             np.square(DOFpts[1,:]) <= 0.1**2)[0]
-   mf_xfem_sing = gf.MeshFem('product', mf_part_unity, mf_sing_u)
-   mf_xfem_sing.set_enriched_dofs(Idofs_center)
-   if variant > 2:
-      Idofs_up = np.nonzero(np.square(DOFpts[0,:]+0.125) +
-                            np.square(DOFpts[1,:]-0.375) <= 0.1**2)[0]
-      Idofs_down = np.nonzero(np.square(DOFpts[0,:]+0.125) +
-                              np.square(DOFpts[1,:]+0.375) <= 0.1**2)[0]
-      mf_sing_u2 = gf.MeshFem('global function',m,ls2,[ck0,ck1,ck2,ck3],1)
-      mf_xfem_sing2 = gf.MeshFem('product', mf_part_unity, mf_sing_u2)
-      mf_xfem_sing2.set_enriched_dofs(np.union1d(Idofs_up, Idofs_down))
-   if variant == 2:
-      mf_u = gf.MeshFem('sum', mf_xfem_sing, mfls_u)
-   else:
-      mf_u = gf.MeshFem('sum', mf_xfem_sing, mf_xfem_sing2, mfls_u)
+    mf_sing_u = gf.MeshFem("global function", m, ls, [ck0, ck1, ck2, ck3], 1)
+    mf_part_unity = gf.MeshFem(m)
+    mf_part_unity.set_classical_fem(1)
+    DOFpts = mf_part_unity.basic_dof_nodes()
+    # Search the dofs to be enriched with the asymptotic displacement.
+    Idofs_center = np.nonzero(
+        np.square(DOFpts[0, :]) + np.square(DOFpts[1, :]) <= 0.1 ** 2
+    )[0]
+    mf_xfem_sing = gf.MeshFem("product", mf_part_unity, mf_sing_u)
+    mf_xfem_sing.set_enriched_dofs(Idofs_center)
+    if variant > 2:
+        Idofs_up = np.nonzero(
+            np.square(DOFpts[0, :] + 0.125) + np.square(DOFpts[1, :] - 0.375)
+            <= 0.1 ** 2
+        )[0]
+        Idofs_down = np.nonzero(
+            np.square(DOFpts[0, :] + 0.125) + np.square(DOFpts[1, :] + 0.375)
+            <= 0.1 ** 2
+        )[0]
+        mf_sing_u2 = gf.MeshFem("global function", m, ls2, [ck0, ck1, ck2, 
ck3], 1)
+        mf_xfem_sing2 = gf.MeshFem("product", mf_part_unity, mf_sing_u2)
+        mf_xfem_sing2.set_enriched_dofs(np.union1d(Idofs_up, Idofs_down))
+    if variant == 2:
+        mf_u = gf.MeshFem("sum", mf_xfem_sing, mfls_u)
+    else:
+        mf_u = gf.MeshFem("sum", mf_xfem_sing, mf_xfem_sing2, mfls_u)
 
 mf_u.set_qdim(2)
 
 # MeshIm definition (MeshImLevelSet):
-mim = gf.MeshIm('levelset', mls, 'all',
-        gf.Integ('IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)'),
-        gf.Integ('IM_STRUCTURED_COMPOSITE(IM_GAUSS_PARALLELEPIPED(2,6),9)'),
-        gf.Integ('IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),5)'))
+mim = gf.MeshIm(
+    "levelset",
+    mls,
+    "all",
+    gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)"),
+    gf.Integ("IM_STRUCTURED_COMPOSITE(IM_GAUSS_PARALLELEPIPED(2,6),9)"),
+    gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),5)"),
+)
 
 # Exact solution for a single crack:
-mf_ue = gf.MeshFem('global function',m,ls,[ck0,ck1,ck2,ck3])
-A = 2+2*Mu/(Lambda+2*Mu); B=-2*(Lambda+Mu)/(Lambda+2*Mu)
-Ue = np.zeros([2,4])
-Ue[0,0] =   0; Ue[1,0] = A-B # sin(theta/2)
-Ue[0,1] = A+B; Ue[1,1] = 0   # cos(theta/2)
-Ue[0,2] =  -B; Ue[1,2] = 0   # sin(theta/2)*sin(theta)
-Ue[0,3] =   0; Ue[1,3] = B   # cos(theta/2)*cos(theta)
-Ue /= 2*np.pi
-Ue = Ue.T.reshape(1,8)
+mf_ue = gf.MeshFem("global function", m, ls, [ck0, ck1, ck2, ck3])
+A = 2 + 2 * Mu / (Lambda + 2 * Mu)
+B = -2 * (Lambda + Mu) / (Lambda + 2 * Mu)
+Ue = np.zeros([2, 4])
+Ue[0, 0] = 0
+Ue[1, 0] = A - B  # sin(theta/2)
+Ue[0, 1] = A + B
+Ue[1, 1] = 0  # cos(theta/2)
+Ue[0, 2] = -B
+Ue[1, 2] = 0  # sin(theta/2)*sin(theta)
+Ue[0, 3] = 0
+Ue[1, 3] = B  # cos(theta/2)*cos(theta)
+Ue /= 2 * np.pi
+Ue = Ue.T.reshape(1, 8)
 
 # Model definition:
-md = gf.Model('real')
-md.add_fem_variable('u', mf_u)
+md = gf.Model("real")
+md.add_fem_variable("u", mf_u)
 # data
-md.add_initialized_data('lambda', [Lambda])
-md.add_initialized_data('mu', [Mu])
-md.add_isotropic_linearized_elasticity_brick(mim,'u','lambda','mu')
+md.add_initialized_data("lambda", [Lambda])
+md.add_initialized_data("mu", [Mu])
+md.add_isotropic_linearized_elasticity_brick(mim, "u", "lambda", "mu")
 md.add_initialized_fem_data("DirichletData", mf_ue, Ue)
-md.add_Dirichlet_condition_with_penalization(mim,'u', 1e12, DIRICHLET, 
'DirichletData')
-
-if variant == 5 or variant == 6: # Penalisation of the jump over the first 
crack
-   mim_bound1 = gf.MeshIm('levelset', mls, 'boundary(a)',
-                          
gf.Integ('IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)'))
-   #gf.asm_generic(mim_bound1, 0, '1', -1) # length of the crack
-   md.add_linear_term\
-   (mim_bound1, 
'1e17*(Xfem_plus(u)-Xfem_minus(u)).(Xfem_plus(Test_u)-Xfem_minus(Test_u))')
-
-if variant == 4 or variant == 6: # Penalisation of the jump over the second 
crack
-   mim_bound2 = gf.MeshIm('levelset', mls, 'boundary(b)',
-                          
gf.Integ('IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)'))
-   md.add_linear_term\
-   (mim_bound2, 
'1e17*(Xfem_plus(u)-Xfem_minus(u)).(Xfem_plus(Test_u)-Xfem_minus(Test_u))')
+md.add_Dirichlet_condition_with_penalization(mim, "u", 1e12, DIRICHLET, 
"DirichletData")
+
+if variant == 5 or variant == 6:  # Penalisation of the jump over the first 
crack
+    mim_bound1 = gf.MeshIm(
+        "levelset",
+        mls,
+        "boundary(a)",
+        gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)"),
+    )
+    # gf.asm_generic(mim_bound1, 0, '1', -1) # length of the crack
+    md.add_linear_term(
+        mim_bound1,
+        
"1e17*(Xfem_plus(u)-Xfem_minus(u)).(Xfem_plus(Test_u)-Xfem_minus(Test_u))",
+    )
+
+if variant == 4 or variant == 6:  # Penalisation of the jump over the second 
crack
+    mim_bound2 = gf.MeshIm(
+        "levelset",
+        mls,
+        "boundary(b)",
+        gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)"),
+    )
+    md.add_linear_term(
+        mim_bound2,
+        
"1e17*(Xfem_plus(u)-Xfem_minus(u)).(Xfem_plus(Test_u)-Xfem_minus(Test_u))",
+    )
 
 # Assembly of the linear system and solve:
 md.solve()
-U = md.variable('u')
+U = md.variable("u")
 
 # Interpolation of the solution on a cut mesh for the drawing purpose
 cut_mesh = mls.cut_mesh()
@@ -176,16 +208,16 @@ mfv = gf.MeshFem(cut_mesh, 2)
 mfv.set_classical_discontinuous_fem(2, 0.001)
 mf_ue.set_qdim(2)
 
-V  = gf.compute_interpolate_on(mf_u, U, mfv)
+V = gf.compute_interpolate_on(mf_u, U, mfv)
 Ve = gf.compute_interpolate_on(mf_ue, Ue, mfv)
 
 # Computation of the Von Mises stress
 mfvm = gf.MeshFem(cut_mesh)
 mfvm.set_classical_discontinuous_fem(2, 0.001)
-md.add_initialized_fem_data('u_cut', mfv, V)
-VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u_cut', 'lambda', 
'mu', mfvm)
+md.add_initialized_fem_data("u_cut", mfv, V)
+VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca("u_cut", "lambda", 
"mu", mfvm)
 
-mfv.export_to_pos('crack.pos', V, 'V', Ve, 'Ve', mfvm, VM, 'Von Mises')
+mfv.export_to_pos("crack.pos", V, "V", Ve, "Ve", mfvm, VM, "Von Mises")
 
-print('You can view the solution with (for example):')
-print('gmsh crack.pos')
+print("You can view the solution with (for example):")
+print("gmsh crack.pos")
diff --git a/interface/tests/python/demo_cracked_thermo_elastic_body.py 
b/interface/tests/python/demo_cracked_thermo_elastic_body.py
index 8789b42..fe34c56 100644
--- a/interface/tests/python/demo_cracked_thermo_elastic_body.py
+++ b/interface/tests/python/demo_cracked_thermo_elastic_body.py
@@ -34,53 +34,60 @@ np.set_printoptions(threshold=np.nan)
 gf.util_trace_level(1)
 
 # Parameters:  #########################################################
-E0 = 5E2            # [N/mm^2] Young modulus at reference temperature
-nu = 0.45           # [-] Poisson ratio
-beta = 8e-5         # [1/K] Expansion coefficient
-gamma = 0.1         # [1/K] Coefficient of thermal weakening
-theta0 = 30.        # [C] Reference temperature
-alpha = 0.1         # [mm^2/s] Thermal diffusivity (0.1 for rubber)
-alpha_env = 0.02    # [N/mm/s/K] Heat transfer coefficient
+E0 = 5e2  # [N/mm^2] Young modulus at reference temperature
+nu = 0.45  # [-] Poisson ratio
+beta = 8e-5  # [1/K] Expansion coefficient
+gamma = 0.1  # [1/K] Coefficient of thermal weakening
+theta0 = 30.0  # [C] Reference temperature
+alpha = 0.1  # [mm^2/s] Thermal diffusivity (0.1 for rubber)
+alpha_env = 0.02  # [N/mm/s/K] Heat transfer coefficient
 alpha_crack = 0.01  # [N/mm/s/K] Heat transfer coefficient
-mR = 287e3*5e-9     # [N*mm/K] --> 287000 [N*mm/kg/K] * mass [kg]
-room_temp = 30.     # [C] temperature on one side of the block
-jump_temp = 100.    # [C] temperature jump between the two sides
+mR = 287e3 * 5e-9  # [N*mm/K] --> 287000 [N*mm/kg/K] * mass [kg]
+room_temp = 30.0  # [C] temperature on one side of the block
+jump_temp = 100.0  # [C] temperature jump between the two sides
 
 # Mesh definition:
-L = 40.             # [mm]
-l = 10.             # [mm]
-ny = 10             # Number of elements in each direction
-quad = True         # quad mesh or triangle one
-
-h = l/ny;
-nx = np.floor(L/h);
-
-if (quad):
-  m=gf.Mesh("cartesian", -L/2.+np.arange(nx+1)*h, -l/2+np.arange(ny+1)*h)
+L = 40.0  # [mm]
+l = 10.0  # [mm]
+ny = 10  # Number of elements in each direction
+quad = True  # quad mesh or triangle one
+
+h = l / ny
+nx = np.floor(L / h)
+
+if quad:
+    m = gf.Mesh(
+        "cartesian", -L / 2.0 + np.arange(nx + 1) * h, -l / 2 + np.arange(ny + 
1) * h
+    )
 else:
-  m=gf.Mesh("regular_simplices", -L/2+np.arange(nx+1)*h, 
-l/2+np.arange(ny+1)*h)
-
-LEFT_RG   = 101
-RIGHT_RG  = 102
+    m = gf.Mesh(
+        "regular_simplices",
+        -L / 2 + np.arange(nx + 1) * h,
+        -l / 2 + np.arange(ny + 1) * h,
+    )
+
+LEFT_RG = 101
+RIGHT_RG = 102
 BOTTOM_RG = 103
-TOP_RG    = 104
-fleft   = m.outer_faces_with_direction([-1., 0.], 0.5)
-fright  = m.outer_faces_with_direction([1., 0.], 0.5)
-fbottom = m.outer_faces_with_direction([0., -1.], 0.5)
-ftop    = m.outer_faces_with_direction([0., 1.], 0.5)
-m.set_region(LEFT_RG,   fleft);
-m.set_region(RIGHT_RG,  fright);
-m.set_region(BOTTOM_RG, fbottom);
-m.set_region(TOP_RG,    ftop);
+TOP_RG = 104
+fleft = m.outer_faces_with_direction([-1.0, 0.0], 0.5)
+fright = m.outer_faces_with_direction([1.0, 0.0], 0.5)
+fbottom = m.outer_faces_with_direction([0.0, -1.0], 0.5)
+ftop = m.outer_faces_with_direction([0.0, 1.0], 0.5)
+m.set_region(LEFT_RG, fleft)
+m.set_region(RIGHT_RG, fright)
+m.set_region(BOTTOM_RG, fbottom)
+m.set_region(TOP_RG, ftop)
 
 m.export_to_vtk("mesh.vtk")
 
 # Levelset definition:
-R1 = 2.5; R2 = 16;
+R1 = 2.5
+R2 = 16
 ytip = R1
-xtip = np.sqrt(R2*R2-R1*R1)
-ls1 = gf.LevelSet(m, 2, "y-%g*tanh(x/7.)" % R1, "x*x+y*y-%g" % (R2*R2))
-ls2 = gf.LevelSet(m, 2, "y+%g*tanh(x/7.)" % R1, "x*x+y*y-%g" % (R2*R2))
+xtip = np.sqrt(R2 * R2 - R1 * R1)
+ls1 = gf.LevelSet(m, 2, "y-%g*tanh(x/7.)" % R1, "x*x+y*y-%g" % (R2 * R2))
+ls2 = gf.LevelSet(m, 2, "y+%g*tanh(x/7.)" % R1, "x*x+y*y-%g" % (R2 * R2))
 mls = gf.MeshLevelSet(m)
 mls.add(ls1)
 mls.add(ls2)
@@ -88,10 +95,10 @@ mls.adapt()
 
 # Basic mesh_fem without enrichment:
 mf_pre = gf.MeshFem(m)
-if (quad):
-  mf_pre.set_fem(gf.Fem("FEM_QK(2,2)"))
+if quad:
+    mf_pre.set_fem(gf.Fem("FEM_QK(2,2)"))
 else:
-  mf_pre.set_fem(gf.Fem("FEM_PK(2,2)"))
+    mf_pre.set_fem(gf.Fem("FEM_PK(2,2)"))
 
 # Definition of the enriched finite element method (MeshFemLevelSet):
 mfls = gf.MeshFem("levelset", mls, mf_pre)
@@ -100,38 +107,57 @@ mfls = gf.MeshFem("levelset", mls, mf_pre)
 mf_part_unity = gf.MeshFem(m)
 mf_part_unity.set_classical_fem(1)
 DOFpts = mf_part_unity.basic_dof_nodes()
-ctip_dofs = [np.nonzero(np.linalg.norm(DOFpts-x,axis=0) < 0.5)[0]
-             for x in [[[xtip],[-ytip]],[[-xtip],[ytip] ],
-                       [[xtip],[ytip]], [[-xtip],[-ytip]]]]
-ck = [gf.GlobalFunction("crack",i) for i in range(4)]
-mf_sing = [gf.MeshFem("product", mf_part_unity,
-                      gf.MeshFem("global function", m, ls, ck, 1))
-           for ls in [ls1,ls2]]
-mf_sing[0].set_enriched_dofs(np.union1d(ctip_dofs[0],ctip_dofs[1]))
-mf_sing[1].set_enriched_dofs(np.union1d(ctip_dofs[2],ctip_dofs[3]))
+ctip_dofs = [
+    np.nonzero(np.linalg.norm(DOFpts - x, axis=0) < 0.5)[0]
+    for x in [
+        [[xtip], [-ytip]],
+        [[-xtip], [ytip]],
+        [[xtip], [ytip]],
+        [[-xtip], [-ytip]],
+    ]
+]
+ck = [gf.GlobalFunction("crack", i) for i in range(4)]
+mf_sing = [
+    gf.MeshFem("product", mf_part_unity, gf.MeshFem("global function", m, ls, 
ck, 1))
+    for ls in [ls1, ls2]
+]
+mf_sing[0].set_enriched_dofs(np.union1d(ctip_dofs[0], ctip_dofs[1]))
+mf_sing[1].set_enriched_dofs(np.union1d(ctip_dofs[2], ctip_dofs[3]))
 mf_u = gf.MeshFem("sum", mf_sing[0], mf_sing[1], mfls)
 mf_u.set_qdim(2)
 
 mf_theta = gf.MeshFem("sum", mf_sing[0], mf_sing[1], mfls)
 
 # MeshIm definition (MeshImLevelSet):
-if (quad):
-  mim = gf.MeshIm("levelset", mls, "all",
-         gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),5)"),
-         gf.Integ("IM_STRUCTURED_COMPOSITE(IM_GAUSS_PARALLELEPIPED(2,6),9)"),
-         gf.Integ("IM_GAUSS_PARALLELEPIPED(2,4)"))
+if quad:
+    mim = gf.MeshIm(
+        "levelset",
+        mls,
+        "all",
+        gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),5)"),
+        gf.Integ("IM_STRUCTURED_COMPOSITE(IM_GAUSS_PARALLELEPIPED(2,6),9)"),
+        gf.Integ("IM_GAUSS_PARALLELEPIPED(2,4)"),
+    )
 else:
-  mim = gf.MeshIm("levelset", mls, "all",
-         gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)"),
-         gf.Integ("IM_STRUCTURED_COMPOSITE(IM_GAUSS_PARALLELEPIPED(2,6),9)"),
-         gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),5)"))
-
-mim_bound = [gf.MeshIm("levelset", mls, boundary,
-                       gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)"))
-             for boundary in ["boundary(a)", "boundary(b)"]]
-
-surf_crack = gf.asm("generic", mim_bound[0], 0, "1", -1)\
-            +gf.asm("generic", mim_bound[1], 0, "1", -1)
+    mim = gf.MeshIm(
+        "levelset",
+        mls,
+        "all",
+        gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)"),
+        gf.Integ("IM_STRUCTURED_COMPOSITE(IM_GAUSS_PARALLELEPIPED(2,6),9)"),
+        gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),5)"),
+    )
+
+mim_bound = [
+    gf.MeshIm(
+        "levelset", mls, boundary, 
gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(6),3)")
+    )
+    for boundary in ["boundary(a)", "boundary(b)"]
+]
+
+surf_crack = gf.asm("generic", mim_bound[0], 0, "1", -1) + gf.asm(
+    "generic", mim_bound[1], 0, "1", -1
+)
 print("surf_crack = %g" % surf_crack)
 
 
@@ -140,12 +166,13 @@ md = gf.Model("real")
 md.add_fem_variable("u", mf_u)
 md.add_fem_variable("theta", mf_theta)
 md.add_variable("P", 1)
-md.add_variable("T", 1); md.set_variable("T", 273+room_temp)
+md.add_variable("T", 1)
+md.set_variable("T", 273 + room_temp)
 # Data
 md.add_initialized_data("surf_crack", surf_crack)
-md.add_initialized_data("mu0", E0/(2*(1+nu)))
-md.add_initialized_data("la0", E0*nu/((1-2*nu)*(1+nu)))
-md.add_initialized_data("ka0", E0/(3*(1-2*nu)))
+md.add_initialized_data("mu0", E0 / (2 * (1 + nu)))
+md.add_initialized_data("la0", E0 * nu / ((1 - 2 * nu) * (1 + nu)))
+md.add_initialized_data("ka0", E0 / (3 * (1 - 2 * nu)))
 md.add_initialized_data("alpha", alpha)
 md.add_initialized_data("alpha_env", alpha_env)
 md.add_initialized_data("alpha_crack", alpha_crack)
@@ -154,8 +181,8 @@ md.add_initialized_data("gamma", gamma)
 md.add_initialized_data("mR", mR)
 md.add_initialized_data("theta0", theta0)
 # Lamé coefficients + bulk modulus
-for p1,p2 in [["la","la0"],["mu","mu0"],["ka","ka0"]]:
-  md.add_macro(p1, "%s/(1+gamma*(theta-theta0))" % p2)
+for p1, p2 in [["la", "la0"], ["mu", "mu0"], ["ka", "ka0"]]:
+    md.add_macro(p1, "%s/(1+gamma*(theta-theta0))" % p2)
 # Deformation gradient
 md.add_macro("F", "Id(2)+Grad_u")
 md.add_macro("Fm", "Id(2)+Xfem_minus(Grad_u)")
@@ -171,25 +198,33 @@ md.add_macro("S", 
"((la*Trace(E)*Id(2)+2*mu*E)/th-1.5*(th-1/th)*ka*Id(2))")
 # Elasticity term
 md.add_nonlinear_term(mim, "(F*S):Grad_Test_u")
 # Diffusion term
-md.add_nonlinear_term(mim,
-  "alpha*Det(F)*(Inv(F')*Grad_theta).(Inv(F')*Grad_Test_theta)")
+md.add_nonlinear_term(
+    mim, "alpha*Det(F)*(Inv(F')*Grad_theta).(Inv(F')*Grad_Test_theta)"
+)
 for mimb in mim_bound:
-  md.add_nonlinear_term(mimb, # Ideal Gas law
-  "(P*((Xfem_plus(u)-Xfem_minus(u)).Normalized(Inv(Fm')*Normal)+1e-6)"
-  "-mR*T/surf_crack)*Test_P")
-  md.add_nonlinear_term(mimb, # Heat flux equilibrium
-                        "(Nanson(Fm)*(T-273-Xfem_minus(theta))"
-                        "+Nanson(Fp)*(T-273-Xfem_plus(theta)))*Test_T")
-  md.add_nonlinear_term(mimb, # Heat exchange on the cracks
-  "-alpha_crack*(Nanson(Fm)*(T-273-Xfem_minus(theta))*Xfem_minus(Test_theta)"
-               "+Nanson(Fp)*(T-273-Xfem_plus(theta))*Xfem_plus(Test_theta))")
-for var,rg in [["theta_B", BOTTOM_RG],["theta_T",TOP_RG]]: # Heat exchange at
-  md.add_initialized_data(var, room_temp)                  # bottom/top
-  md.add_nonlinear_term(mim,"-alpha_env*Nanson(F)*("+var+"-theta)*Test_theta",
-                        rg)
-for mimb in mim_bound: # Follower pressure
-  md.add_nonlinear_term(mimb,"(P*Det(Fm)*Inv(Fm')*Normal).Xfem_minus(Test_u)")
-  md.add_nonlinear_term(mimb,"(-P*Det(Fp)*Inv(Fp')*Normal).Xfem_plus(Test_u)")
+    md.add_nonlinear_term(
+        mimb,  # Ideal Gas law
+        "(P*((Xfem_plus(u)-Xfem_minus(u)).Normalized(Inv(Fm')*Normal)+1e-6)"
+        "-mR*T/surf_crack)*Test_P",
+    )
+    md.add_nonlinear_term(
+        mimb,  # Heat flux equilibrium
+        "(Nanson(Fm)*(T-273-Xfem_minus(theta))"
+        "+Nanson(Fp)*(T-273-Xfem_plus(theta)))*Test_T",
+    )
+    md.add_nonlinear_term(
+        mimb,  # Heat exchange on the cracks
+        
"-alpha_crack*(Nanson(Fm)*(T-273-Xfem_minus(theta))*Xfem_minus(Test_theta)"
+        "+Nanson(Fp)*(T-273-Xfem_plus(theta))*Xfem_plus(Test_theta))",
+    )
+for var, rg in [["theta_B", BOTTOM_RG], ["theta_T", TOP_RG]]:  # Heat exchange 
at
+    md.add_initialized_data(var, room_temp)  # bottom/top
+    md.add_nonlinear_term(
+        mim, "-alpha_env*Nanson(F)*(" + var + "-theta)*Test_theta", rg
+    )
+for mimb in mim_bound:  # Follower pressure
+    md.add_nonlinear_term(mimb, 
"(P*Det(Fm)*Inv(Fm')*Normal).Xfem_minus(Test_u)")
+    md.add_nonlinear_term(mimb, 
"(-P*Det(Fp)*Inv(Fp')*Normal).Xfem_plus(Test_u)")
 
 # Fixed displacement
 md.add_Dirichlet_condition_with_multipliers(mim, "u", 1, LEFT_RG)
@@ -197,12 +232,12 @@ md.add_Dirichlet_condition_with_multipliers(mim, "u", 1, 
RIGHT_RG)
 
 
 # Solve with fixed pressure (to open the crack lips)
-md.disable_variable("P");
+md.disable_variable("P")
 md.set_variable("P", [1e-2])
-md.solve("max_res", 5E-4, "max_iter", 100, "noisy")
+md.solve("max_res", 5e-4, "max_iter", 100, "noisy")
 
 # Solve fully coupled problem
-md.enable_variable("P");
+md.enable_variable("P")
 
 # Interpolation of the solution on a cut mesh for the drawing purpose
 cut_mesh = mls.cut_mesh()
@@ -227,24 +262,46 @@ md.add_macro("SI", 
"((laI*Trace(EI)*Id(2)+2*muI*EI)/thI-1.5*(thI-1/thI)*kaI*Id(2
 
 # Increase temperature gap
 it = 0
-for fact in [0,0.2,0.4,0.6,0.8,1.]:
-  md.set_variable("theta_T", room_temp + fact*jump_temp)
-  md.solve("max_res", 5E-8, "max_iter", 100, "noisy")
-
-  U = md.variable("u")
-  theta = md.variable("theta")
-  T = md.variable("T")
-  print("Gas temperature %g C" % (T-273))
-  P = md.variable("P")
-  print("Gas pressure %g MPa" % P)
-
-  V  = gf.compute_interpolate_on(mf_u, U, mfv)
-  Th = gf.compute_interpolate_on(mf_theta, theta, mfw)
-  VM = md.interpolation("sqrt(3/2)*Norm(Deviator(Cauchy_stress_from_PK2(SI, 
graduI)))", mfvm)
-
-  mfv.export_to_pos("cracked_body_%i.pos" % it, V, "V", mfw, Th, 
"Temperature", mfvm, VM, "Von Mises stress")
-  mfv.export_to_vtk("cracked_body_%i.vtk" % it, V, "V", mfw, Th, 
"Temperature", mfvm, VM, "Von Mises stress")
-  it +=1
+for fact in [0, 0.2, 0.4, 0.6, 0.8, 1.0]:
+    md.set_variable("theta_T", room_temp + fact * jump_temp)
+    md.solve("max_res", 5e-8, "max_iter", 100, "noisy")
+
+    U = md.variable("u")
+    theta = md.variable("theta")
+    T = md.variable("T")
+    print("Gas temperature %g C" % (T - 273))
+    P = md.variable("P")
+    print("Gas pressure %g MPa" % P)
+
+    V = gf.compute_interpolate_on(mf_u, U, mfv)
+    Th = gf.compute_interpolate_on(mf_theta, theta, mfw)
+    VM = md.interpolation(
+        "sqrt(3/2)*Norm(Deviator(Cauchy_stress_from_PK2(SI, graduI)))", mfvm
+    )
+
+    mfv.export_to_pos(
+        "cracked_body_%i.pos" % it,
+        V,
+        "V",
+        mfw,
+        Th,
+        "Temperature",
+        mfvm,
+        VM,
+        "Von Mises stress",
+    )
+    mfv.export_to_vtk(
+        "cracked_body_%i.vtk" % it,
+        V,
+        "V",
+        mfw,
+        Th,
+        "Temperature",
+        mfvm,
+        VM,
+        "Von Mises stress",
+    )
+    it += 1
 
 print("You can view the solution with (for example):")
 print("paraview cracked_body_2.vtk")
diff --git a/interface/tests/python/demo_dynamic_contact_1D.py 
b/interface/tests/python/demo_dynamic_contact_1D.py
index ee34110..8a72828 100644
--- a/interface/tests/python/demo_dynamic_contact_1D.py
+++ b/interface/tests/python/demo_dynamic_contact_1D.py
@@ -33,117 +33,169 @@ import matplotlib.pyplot as plt
 import time, os, sys
 
 # Numerical parameters
-NX = 20               # Number of elements
-T = 12                # Simulation time
-dt = 0.002            # Time step
-u_degree = 1          # Degree of the finite element method for u
+NX = 20  # Number of elements
+T = 12  # Simulation time
+dt = 0.002  # Time step
+u_degree = 1  # Degree of the finite element method for u
 
-gamma0_N = 5.         # Nitsche parameter gamma
-theta_N =  0.         # Nitsche parameter theta
+gamma0_N = 5.0  # Nitsche parameter gamma
+theta_N = 0.0  # Nitsche parameter theta
 
-gamma0_P = 1.         # Penalization parameter
+gamma0_P = 1.0  # Penalization parameter
 
-beta = 0.             # Newmark parameter beta
-gamma = 0.5           # Newmark parameter gamma
+beta = 0.0  # Newmark parameter beta
+gamma = 0.5  # Newmark parameter gamma
 
-e_PS = 0.             # Restitution coefficient for Paoli-Schatzman scheme
+e_PS = 0.0  # Restitution coefficient for Paoli-Schatzman scheme
 
-version = 4           # 0 = pure Signorini contact
-                      # 1 = pure Signorini contact with Paoli-Schatzman scheme
-                      # 2 = penalized contact
-                      # 3 = Nitsche's method
-                      # 4 = Taylor-Flanagan method
+version = 4  # 0 = pure Signorini contact
+# 1 = pure Signorini contact with Paoli-Schatzman scheme
+# 2 = penalized contact
+# 3 = Nitsche's method
+# 4 = Taylor-Flanagan method
 
 lump_mass_matrix = 0  # 0 = standard mass matrix
-                      # 1 = basic lumped mass matrix
+# 1 = basic lumped mass matrix
 
 mass_matrix_type = 0  # 0 = standard mass matrix
-                      # 1 = redistributed mass matrix
-                      # 2 = singular dynamic mass matrix
+# 1 = redistributed mass matrix
+# 2 = singular dynamic mass matrix
 
 
 # Output parameters
-dtplot = 0.05         # Time step for intermediate plots
-do_inter_plot = False # Intermediate plots or not
+dtplot = 0.05  # Time step for intermediate plots
+do_inter_plot = False  # Intermediate plots or not
 do_final_plot = True  # Final plots or not
-output_directory = './expe_num'
-root_filename = 'dyn1d'
-do_export_in_files = False;
-
-# Read optional parameters on the command line 
-for i in range(1,len(sys.argv)): exec(sys.argv[i])
-
-print("Begin experiment for", end=' ')
-if    (version == 0): print("Pure Signorini contact", end=' ')
-elif  (version == 1): print("Paoli-Schatzman scheme", end=' ')
-elif  (version == 2): print("Penalized contact", end=' ')
-elif  (version == 3): print("Nitsche's method", end=' ')
-elif  (version == 4): print("Taylor-Flanagan method", end=' ')
-print(" in P%d, with NX = %d, dt = %g" % (u_degree,NX, dt))
-
-if (version == 4 and beta != 0): print('Incompatibility'); exit(1)
+output_directory = "./expe_num"
+root_filename = "dyn1d"
+do_export_in_files = False
+
+# Read optional parameters on the command line
+for i in range(1, len(sys.argv)):
+    exec(sys.argv[i])
+
+print("Begin experiment for", end=" ")
+if version == 0:
+    print("Pure Signorini contact", end=" ")
+elif version == 1:
+    print("Paoli-Schatzman scheme", end=" ")
+elif version == 2:
+    print("Penalized contact", end=" ")
+elif version == 3:
+    print("Nitsche's method", end=" ")
+elif version == 4:
+    print("Taylor-Flanagan method", end=" ")
+print(" in P%d, with NX = %d, dt = %g" % (u_degree, NX, dt))
+
+if version == 4 and beta != 0:
+    print("Incompatibility")
+    exit(1)
 
 # Deduced parameters
-h = 1./NX
-TT = np.arange(0, T+dt, dt)
+h = 1.0 / NX
+TT = np.arange(0, T + dt, dt)
 NT = TT.size
-dt_max_approx = h/(2* u_degree);
-if (version == 2): dt_max_approx = min(dt_max_approx, 2*h/(gamma0_P))
-if (version == 3): dt_max_approx = min(dt_max_approx, 2*h/(gamma0_N))
-print('Approximative dt_max for CFL :', dt_max_approx)
-if (beta == 0 and dt > dt_max_approx): print('Time step too large'); exit(1)
+dt_max_approx = h / (2 * u_degree)
+if version == 2:
+    dt_max_approx = min(dt_max_approx, 2 * h / (gamma0_P))
+if version == 3:
+    dt_max_approx = min(dt_max_approx, 2 * h / (gamma0_N))
+print("Approximative dt_max for CFL :", dt_max_approx)
+if beta == 0 and dt > dt_max_approx:
+    print("Time step too large")
+    exit(1)
 
 # Exact solution. The solution is periodic of period 3
 # Return the displacement (d=0), x derivative (d=1) or time derivative (d=2)
-def uExact(x, t, d = 0):
+def uExact(x, t, d=0):
     # Shift the time 't' with t=0 : beginning of the period
-    tp = t % 3.
+    tp = t % 3.0
     # The solution has 3 phases
     # Shift the time 'tp' with t=0 : beginning of a phase
     # and get also the phase number
-    tf = tp % 1.
+    tf = tp % 1.0
     nf = np.floor(tp)
     # Get the index of the zone in each phase : I, II, III, IV
     # (zones are given according to characteristics of the wave equation)
-    if (tf<x): zone = 1 if (tf<=(1-x)) else 3
-    else:      zone = 2 if (tf<=(1-x)) else 4
+    if tf < x:
+        zone = 1 if (tf <= (1 - x)) else 3
+    else:
+        zone = 2 if (tf <= (1 - x)) else 4
     # Solution according to the Phase (1,2,3) and the zone (I, II, III, IV)
     if nf == 0:
-        if   zone == 1: u = 1./2.-x/2.;   dxu = -1./2.;  dtu = 0.;
-        elif zone == 2: u = 1./2.-tf/2.;  dxu = 0.;      dtu = -1./2.;
-        elif zone == 3: u = 1./2.-x/2.;   dxu = -1./2.;  dtu = 0;
-        elif zone == 4: u = 1./2.-tf/2.;  dxu = 0;       dtu = -1./2.;
-    elif nf == 1: 
-        if   zone == 1: u = -tf/2.;       dxu = 0;       dtu = -1./2.
-        elif zone == 2: u = -x/2.;        dxu = -1./2.;  dtu = 0;
-        elif zone == 3: u = -1./2.+x/2.;  dxu = 1./2.;   dtu = 0;
-        elif zone == 4: u = -1./2.+tf/2.; dxu = 0;       dtu = 1./2.;
+        if zone == 1:
+            u = 1.0 / 2.0 - x / 2.0
+            dxu = -1.0 / 2.0
+            dtu = 0.0
+        elif zone == 2:
+            u = 1.0 / 2.0 - tf / 2.0
+            dxu = 0.0
+            dtu = -1.0 / 2.0
+        elif zone == 3:
+            u = 1.0 / 2.0 - x / 2.0
+            dxu = -1.0 / 2.0
+            dtu = 0
+        elif zone == 4:
+            u = 1.0 / 2.0 - tf / 2.0
+            dxu = 0
+            dtu = -1.0 / 2.0
+    elif nf == 1:
+        if zone == 1:
+            u = -tf / 2.0
+            dxu = 0
+            dtu = -1.0 / 2.0
+        elif zone == 2:
+            u = -x / 2.0
+            dxu = -1.0 / 2.0
+            dtu = 0
+        elif zone == 3:
+            u = -1.0 / 2.0 + x / 2.0
+            dxu = 1.0 / 2.0
+            dtu = 0
+        elif zone == 4:
+            u = -1.0 / 2.0 + tf / 2.0
+            dxu = 0
+            dtu = 1.0 / 2.0
     elif nf == 2:
-        if   zone == 1: u = tf/2.;        dxu = 0;       dtu = 1./2.;
-        elif zone == 2: u = tf/2.;        dxu = 0;       dtu = 1./2.;
-        elif zone == 3: u = 1./2.-x/2.;   dxu = -1./2.;  dtu = 0;
-        elif zone == 4: u = 1./2.-x/2.;   dxu = -1./2.;  dtu = 0.
-    return (u if (d == 0) else (dxu if (d == 1) else dtu))
-
-
-def linsolve(M, B): # Call Superlu to solve a sparse linear system
+        if zone == 1:
+            u = tf / 2.0
+            dxu = 0
+            dtu = 1.0 / 2.0
+        elif zone == 2:
+            u = tf / 2.0
+            dxu = 0
+            dtu = 1.0 / 2.0
+        elif zone == 3:
+            u = 1.0 / 2.0 - x / 2.0
+            dxu = -1.0 / 2.0
+            dtu = 0
+        elif zone == 4:
+            u = 1.0 / 2.0 - x / 2.0
+            dxu = -1.0 / 2.0
+            dtu = 0.0
+    return u if (d == 0) else (dxu if (d == 1) else dtu)
+
+
+def linsolve(M, B):  # Call Superlu to solve a sparse linear system
     return (((gf.linsolve_superlu(M, B))[0]).T)[0]
 
+
 # Mesh
-m=gf.Mesh('cartesian', np.arange(0,1+1./NX,1./NX))
+m = gf.Mesh("cartesian", np.arange(0, 1 + 1.0 / NX, 1.0 / NX))
 
 # Selection of the contact and Dirichlet boundaries
-GAMMAC = 1; GAMMAD = 2
+GAMMAC = 1
+GAMMAD = 2
 border = m.outer_faces()
 normals = m.normal_of_faces(border)
-contact_boundary = border[:,np.nonzero(normals[0] < -0.01)[0]]
+contact_boundary = border[:, np.nonzero(normals[0] < -0.01)[0]]
 m.set_region(GAMMAC, contact_boundary)
-contact_boundary = border[:,np.nonzero(normals[0] > 0.01)[0]]
+contact_boundary = border[:, np.nonzero(normals[0] > 0.01)[0]]
 m.set_region(GAMMAD, contact_boundary)
 
 # Finite element methods
 mfu = gf.MeshFem(m)
-mfu.set_classical_fem(u_degree) # Assumed to be a Lagrange FEM in the following
+mfu.set_classical_fem(u_degree)  # Assumed to be a Lagrange FEM in the 
following
 
 mfd = gf.MeshFem(m, 1)
 mfd.set_classical_fem(u_degree)
@@ -152,350 +204,458 @@ mfd.set_classical_fem(u_degree)
 mim = gf.MeshIm(m, 4)
 
 # GetFEM model
-md = gf.Model('real'); md.add_fem_variable('u', mfu)
-md.add_fem_data('v', mfu)
-md.add_initialized_data('t_N', theta_N)
-md.add_initialized_data('g_N', gamma0_N/h)
+md = gf.Model("real")
+md.add_fem_variable("u", mfu)
+md.add_fem_data("v", mfu)
+md.add_initialized_data("t_N", theta_N)
+md.add_initialized_data("g_N", gamma0_N / h)
 
 # Initial conditions
-U0 = mfu.eval('0.5-0.5*x')   # Initial displacement
-Um1 = np.copy(U0)            # U_{-1} for Paoli-Schatzman scheme
+U0 = mfu.eval("0.5-0.5*x")  # Initial displacement
+Um1 = np.copy(U0)  # U_{-1} for Paoli-Schatzman scheme
 Ndof = U0.size
-V0 = np.zeros(Ndof)          # Initial velocity
-s0 = 0.                      # Initial stress
-md.set_variable('u', U0); md.set_variable('v', V0)
+V0 = np.zeros(Ndof)  # Initial velocity
+s0 = 0.0  # Initial stress
+md.set_variable("u", U0)
+md.set_variable("v", V0)
 
 # Mass and stiffness matrices
-M = gf.asm_generic(mim, 2, 'u*Test_u', -1, md)
-if (lump_mass_matrix == 1):
-    assert (u_degree == 1), "Sorry, basic lump only for affine elements"
+M = gf.asm_generic(mim, 2, "u*Test_u", -1, md)
+if lump_mass_matrix == 1:
+    assert u_degree == 1, "Sorry, basic lump only for affine elements"
     for j in range(0, Ndof):
-        for i in range(1, u_degree+1):
-            if (j+i < Ndof): M[j,j] += M[j,j+i]; M[j,j+i] = 0.;
-            if (j-i >= 0): M[j,j] += M[j,j-i]; M[j,j-i] = 0.;
-K = gf.asm_generic(mim, 2, 'Grad_u*Grad_Test_u', -1, md)
+        for i in range(1, u_degree + 1):
+            if j + i < Ndof:
+                M[j, j] += M[j, j + i]
+                M[j, j + i] = 0.0
+            if j - i >= 0:
+                M[j, j] += M[j, j - i]
+                M[j, j - i] = 0.0
+K = gf.asm_generic(mim, 2, "Grad_u*Grad_Test_u", -1, md)
 
 # Dirichlet condition on the top
-for i in range(0, u_degree+1): K[Ndof-1,Ndof-1-i] = 0.
-for i in range(0, u_degree+1): M[Ndof-1,Ndof-1-i] = 0.
-M[Ndof-1,Ndof-1] = 1.; K[Ndof-1,Ndof-1] = 1.;
-M2 = gf.Spmat('copy', M);
-
-if (mass_matrix_type == 1): # Redistributed mass matrix
-    M[1,1] += M[0,0]; M[0,0] = 0.;
-    for i in range(1, u_degree+1):
-        M[i,i] += M[i,0]; M[0,i] = M[i,0] = 0.
-    M2 = gf.Spmat('copy', M); M2[0,0] = 1.
-elif (mass_matrix_type == 2): # Singular dynamic mass matrix
-    assert (u_degree == 1), 'Sorry, implemented for linear element only'
-    M[1,1] = 7.*h/12.;
-    for i in range(0, u_degree+1): M[0,i] = M[i,0] = 0.
-    M2 = gf.Spmat('copy', M); M2[0,0] = 1.
+for i in range(0, u_degree + 1):
+    K[Ndof - 1, Ndof - 1 - i] = 0.0
+for i in range(0, u_degree + 1):
+    M[Ndof - 1, Ndof - 1 - i] = 0.0
+M[Ndof - 1, Ndof - 1] = 1.0
+K[Ndof - 1, Ndof - 1] = 1.0
+M2 = gf.Spmat("copy", M)
+
+if mass_matrix_type == 1:  # Redistributed mass matrix
+    M[1, 1] += M[0, 0]
+    M[0, 0] = 0.0
+    for i in range(1, u_degree + 1):
+        M[i, i] += M[i, 0]
+        M[0, i] = M[i, 0] = 0.0
+    M2 = gf.Spmat("copy", M)
+    M2[0, 0] = 1.0
+elif mass_matrix_type == 2:  # Singular dynamic mass matrix
+    assert u_degree == 1, "Sorry, implemented for linear element only"
+    M[1, 1] = 7.0 * h / 12.0
+    for i in range(0, u_degree + 1):
+        M[0, i] = M[i, 0] = 0.0
+    M2 = gf.Spmat("copy", M)
+    M2[0, 0] = 1.0
 
 # Matrices for Newmark method
-MV0 = M.mult(V0); MV1 = np.copy(MV0)
-MA0 = -K.mult(U0);
-if (mass_matrix_type >= 1): MA0[0] = 0;
-
-K_m = gf.Spmat('copy', K); K_m.scale(dt*dt*beta);
-K_N = gf.Spmat('add', M, K_m);  # Newmark matrix without contact
-K_N_C = gf.Spmat('copy', K_N);  # Newmark matrix with effective contact
-
-if (version == 0):     # Pure Signorini contact
-    for i in range(0, u_degree+1): K_N_C[0,i] = 0.
-    K_N_C[0,0] = 1;
-elif (version == 1 or version == 4):
+MV0 = M.mult(V0)
+MV1 = np.copy(MV0)
+MA0 = -K.mult(U0)
+if mass_matrix_type >= 1:
+    MA0[0] = 0
+
+K_m = gf.Spmat("copy", K)
+K_m.scale(dt * dt * beta)
+K_N = gf.Spmat("add", M, K_m)
+# Newmark matrix without contact
+K_N_C = gf.Spmat("copy", K_N)
+# Newmark matrix with effective contact
+
+if version == 0:  # Pure Signorini contact
+    for i in range(0, u_degree + 1):
+        K_N_C[0, i] = 0.0
+    K_N_C[0, 0] = 1
+elif version == 1 or version == 4:
     # Pure Signorini contact with Paoli-Schatzman scheme
-    for i in range(0, u_degree+1): K_N_C[0,i] = 0.
-    K_N_C[0,0] = 1;
-elif (version == 2):   # Penalized contact
-    K_N_C[0,0] += dt*dt*beta*(gamma0_P/h)
-elif (version == 3):   # Nitsche contact
-    asstr_Nitsche = '-(t_N/g_N)*Grad_u*Grad_Test_u'
+    for i in range(0, u_degree + 1):
+        K_N_C[0, i] = 0.0
+    K_N_C[0, 0] = 1
+elif version == 2:  # Penalized contact
+    K_N_C[0, 0] += dt * dt * beta * (gamma0_P / h)
+elif version == 3:  # Nitsche contact
+    asstr_Nitsche = "-(t_N/g_N)*Grad_u*Grad_Test_u"
     K_N1 = gf.asm_generic(mim, 2, asstr_Nitsche, GAMMAC, md)
-    K_Nitsche1 = gf.Spmat('add', K, K_N1)
-    K_N1.scale(dt*dt*beta);
-    K_N = gf.Spmat('add', K_N, K_N1)
-    asstr_Nitsche = '(1/g_N)*(g_N*u+Grad_u)*(g_N*Test_u+t_N*Grad_Test_u)'
+    K_Nitsche1 = gf.Spmat("add", K, K_N1)
+    K_N1.scale(dt * dt * beta)
+    K_N = gf.Spmat("add", K_N, K_N1)
+    asstr_Nitsche = "(1/g_N)*(g_N*u+Grad_u)*(g_N*Test_u+t_N*Grad_Test_u)"
     K_N2 = gf.asm_generic(mim, 2, asstr_Nitsche, GAMMAC, md)
-    K_Nitsche2 = gf.Spmat('add', K_Nitsche1, K_N2)
-    K_N2.scale(dt*dt*beta);
-    K_N_C = gf.Spmat('add', K_N, K_N2)
-    asstr_Nitsche = '(t_N/g_N)*Grad_u*Grad_Test_u ' \
-             + '+(1/g_N)*neg_part(g_N*u+Grad_u)*(g_N*Test_u+t_N*Grad_Test_u)'
-else: assert(false), "Unvalid version"
-              
+    K_Nitsche2 = gf.Spmat("add", K_Nitsche1, K_N2)
+    K_N2.scale(dt * dt * beta)
+    K_N_C = gf.Spmat("add", K_N, K_N2)
+    asstr_Nitsche = (
+        "(t_N/g_N)*Grad_u*Grad_Test_u "
+        + "+(1/g_N)*neg_part(g_N*u+Grad_u)*(g_N*Test_u+t_N*Grad_Test_u)"
+    )
+else:
+    assert false, "Unvalid version"
+
 # Misc initializations
 Ndof = U0.size
-Fc = np.zeros(Ndof); Uex = np.zeros(Ndof); Vex = np.zeros(Ndof); 
-Xdraw = np.arange(0, 1+0.001, 0.001) # Grid for plot
+Fc = np.zeros(Ndof)
+Uex = np.zeros(Ndof)
+Vex = np.zeros(Ndof)
+Xdraw = np.arange(0, 1 + 0.001, 0.001)  # Grid for plot
 Ndraw = Xdraw.size
 tplot = 0
-store_E   = np.zeros(NT);
-store_VL2 = np.zeros(NT); store_VL2_ex = np.zeros(NT)
-store_UL2 = np.zeros(NT); store_UL2_ex = np.zeros(NT)
-store_UH1 = np.zeros(NT); store_UH1_ex = np.zeros(NT)
-store_u0  = np.zeros(NT); store_u0_ex  = np.zeros(NT)
-store_v0  = np.zeros(NT); store_v0_ex  = np.zeros(NT)
-store_s0  = np.zeros(NT); store_s0_ex  = np.zeros(NT)
-fem_nodes = mfu.basic_dof_nodes(); s0 = s1 = ux = 0.;
+store_E = np.zeros(NT)
+store_VL2 = np.zeros(NT)
+store_VL2_ex = np.zeros(NT)
+store_UL2 = np.zeros(NT)
+store_UL2_ex = np.zeros(NT)
+store_UH1 = np.zeros(NT)
+store_UH1_ex = np.zeros(NT)
+store_u0 = np.zeros(NT)
+store_u0_ex = np.zeros(NT)
+store_v0 = np.zeros(NT)
+store_v0_ex = np.zeros(NT)
+store_s0 = np.zeros(NT)
+store_s0_ex = np.zeros(NT)
+fem_nodes = mfu.basic_dof_nodes()
+s0 = s1 = ux = 0.0
 
 # Time steps
 for nit in range(0, NT):
-    t = TT[nit];
+    t = TT[nit]
 
-    if (t > 0.):
-        if (beta == 0): # Newmark Explicit scheme (beta = 0)
+    if t > 0.0:
+        if beta == 0:  # Newmark Explicit scheme (beta = 0)
             F = Fc - K.mult(U0)
             FF = linsolve(M2, F)
-            U1 = U0 + dt*V0 + (dt*dt/2.)*FF
-            V1 = V0 + (dt*(1.-gamma))*FF
-            a = 0;
-            for i in range(1, u_degree+1): a += K[0,i]*U1[i]
-            if (version == 0):   # Pure Signorini contact
-                if (mass_matrix_type >= 1):
-                    U1[0] = max(0., -a) / K[0,0];
-                    s1 = -max(0., a); Fc[0] = -s1
-                else: assert (false), 'No explicit scheme for ' \
-                        + 'pure Signorini contact and standard mass matrix'
-            elif (version == 1): # Pure Signorini contact with P.-S. scheme
-                if (mass_matrix_type >= 1):
-                    U1[0] = max(-e_PS*Um1[0], -a) / K[0,0];
-                    s1 = min(-e_PS*Um1[0], -a);
+            U1 = U0 + dt * V0 + (dt * dt / 2.0) * FF
+            V1 = V0 + (dt * (1.0 - gamma)) * FF
+            a = 0
+            for i in range(1, u_degree + 1):
+                a += K[0, i] * U1[i]
+            if version == 0:  # Pure Signorini contact
+                if mass_matrix_type >= 1:
+                    U1[0] = max(0.0, -a) / K[0, 0]
+                    s1 = -max(0.0, a)
+                    Fc[0] = -s1
+                else:
+                    assert false, (
+                        "No explicit scheme for "
+                        + "pure Signorini contact and standard mass matrix"
+                    )
+            elif version == 1:  # Pure Signorini contact with P.-S. scheme
+                if mass_matrix_type >= 1:
+                    U1[0] = max(-e_PS * Um1[0], -a) / K[0, 0]
+                    s1 = min(-e_PS * Um1[0], -a)
                 else:
-                    s1 = 0;
-                    if ((1./(1.+e_PS))*U1[0] + (e_PS/(1.+e_PS))*Um1[0] < 0):
-                        U1_0 = np.copy(U1);
-                        B=M.mult(U0)+dt*M.mult(V0)-(dt*dt/2.)*K.mult(U0)
-                        B0 = np.copy(B); B0[0] = -e_PS*Um1[0];
-                        U1=linsolve(K_N_C, B0)
-                        F=M.mult(U1)-B; s1 = -F[0]/(dt*dt)
-                        V1 += (U1-U1_0)/dt; 
-                Fc[0] = 0;
-            elif (version == 4): # Pure Signorini with Taylor-Flanagan scheme
-                if (mass_matrix_type >= 1):
-                    U1[0] = max(0., -a) / K[0,0];
-                    s1 = min(0., -a);
+                    s1 = 0
+                    if (1.0 / (1.0 + e_PS)) * U1[0] + (e_PS / (1.0 + e_PS)) * 
Um1[
+                        0
+                    ] < 0:
+                        U1_0 = np.copy(U1)
+                        B = M.mult(U0) + dt * M.mult(V0) - (dt * dt / 2.0) * 
K.mult(U0)
+                        B0 = np.copy(B)
+                        B0[0] = -e_PS * Um1[0]
+                        U1 = linsolve(K_N_C, B0)
+                        F = M.mult(U1) - B
+                        s1 = -F[0] / (dt * dt)
+                        V1 += (U1 - U1_0) / dt
+                Fc[0] = 0
+            elif version == 4:  # Pure Signorini with Taylor-Flanagan scheme
+                if mass_matrix_type >= 1:
+                    U1[0] = max(0.0, -a) / K[0, 0]
+                    s1 = min(0.0, -a)
                 else:
-                    s1 = 0;
-                    if (U1[0] < 0):
-                        F *= 0.; F[0] = 1;
-                        F2=linsolve(M, F);
-                        s1 = V1[0]/(F2[0]*dt);
-                        F *= 0.; F[0] = -s1;
-                        F2=linsolve(M, F);
-                        U1 += dt*dt*F2;
-                        V1 += dt*F2;
-            elif (version == 2): # Penalized contact
-                if (mass_matrix_type >= 1):
-                    U1[0] = -a / K[0,0];
-                    if (U1[0] < 0): U1[0] = -a / (K[0,0] + gamma0_P/h);
-                s1 = (gamma0_P/h)*min(0., U1[0]); Fc[0] = -s1
-            else:                # Nitsche contact
-                if (mass_matrix_type >= 1):
-                    a = 0;
-                    for i in range(1, u_degree+1): a += K_Nitsche1[0,i]*U1[i]
-                    U1[0] = -a / K_Nitsche1[0,0]
-                    if (U1[0] < 0):
-                        a = 0;
-                        for i in range(1,u_degree+1): a += 
K_Nitsche2[0,i]*U1[i]
-                        U1[0] = -a / K_Nitsche2[0,0]
-                md.set_variable('u', U1); ux = 
md.interpolation('Grad_u',[0.],m)
+                    s1 = 0
+                    if U1[0] < 0:
+                        F *= 0.0
+                        F[0] = 1
+                        F2 = linsolve(M, F)
+                        s1 = V1[0] / (F2[0] * dt)
+                        F *= 0.0
+                        F[0] = -s1
+                        F2 = linsolve(M, F)
+                        U1 += dt * dt * F2
+                        V1 += dt * F2
+            elif version == 2:  # Penalized contact
+                if mass_matrix_type >= 1:
+                    U1[0] = -a / K[0, 0]
+                    if U1[0] < 0:
+                        U1[0] = -a / (K[0, 0] + gamma0_P / h)
+                s1 = (gamma0_P / h) * min(0.0, U1[0])
+                Fc[0] = -s1
+            else:  # Nitsche contact
+                if mass_matrix_type >= 1:
+                    a = 0
+                    for i in range(1, u_degree + 1):
+                        a += K_Nitsche1[0, i] * U1[i]
+                    U1[0] = -a / K_Nitsche1[0, 0]
+                    if U1[0] < 0:
+                        a = 0
+                        for i in range(1, u_degree + 1):
+                            a += K_Nitsche2[0, i] * U1[i]
+                        U1[0] = -a / K_Nitsche2[0, 0]
+                md.set_variable("u", U1)
+                ux = md.interpolation("Grad_u", [0.0], m)
                 Fc = gf.asm_generic(mim, 1, asstr_Nitsche, GAMMAC, md)
-                s1 = min(0.,(gamma0_N/h)*U1[0]+ux)
-            FF = linsolve(M2, Fc-K.mult(U1))
-            V1 += dt*gamma*FF;
-            if (mass_matrix_type >= 1): V1[0] = (U1[0] - U0[0])/dt
+                s1 = min(0.0, (gamma0_N / h) * U1[0] + ux)
+            FF = linsolve(M2, Fc - K.mult(U1))
+            V1 += dt * gamma * FF
+            if mass_matrix_type >= 1:
+                V1[0] = (U1[0] - U0[0]) / dt
         else:  # Implicit scheme (beta > 0)
-            B = M.mult(U0)+dt*MV0+(dt*dt*(1-2*beta)/2.)*MA0
+            B = M.mult(U0) + dt * MV0 + (dt * dt * (1 - 2 * beta) / 2.0) * MA0
             U1 = linsolve(K_N, B)
             MV1 = MV0
-            if (version == 0):   # Pure Signorini contact
-                if (U1[0] < 0):
-                    B2 = np.copy(B); B2[0]=0; U1=linsolve(K_N_C, B2)
-                    Fc1 = (K_N.mult(U1) - B)/(beta*dt*dt); s1 = -Fc1[0]
-                else: Fc1 = 0.*Fc; s1 = 0
-            elif (version == 1): # Pure Signorini contact with P.-S. scheme
-                if ((1./(1.+e_PS))*U1[0] + (e_PS/(1.+e_PS))*Um1[0] < 0):
-                    B2 = np.copy(B); B2[0]= -e_PS*Um1[0];
+            if version == 0:  # Pure Signorini contact
+                if U1[0] < 0:
+                    B2 = np.copy(B)
+                    B2[0] = 0
                     U1 = linsolve(K_N_C, B2)
-                    Fc1 = (K_N.mult(U1) - B)/(dt*dt); s1 = -Fc1[0]
-                    MV1 += dt*Fc1
-                else: s1 = 0;
-                Fc1 = 0.*Fc;
-            elif (version == 2): # Penalized contact
-                if (U1[0] < 0):
+                    Fc1 = (K_N.mult(U1) - B) / (beta * dt * dt)
+                    s1 = -Fc1[0]
+                else:
+                    Fc1 = 0.0 * Fc
+                    s1 = 0
+            elif version == 1:  # Pure Signorini contact with P.-S. scheme
+                if (1.0 / (1.0 + e_PS)) * U1[0] + (e_PS / (1.0 + e_PS)) * 
Um1[0] < 0:
+                    B2 = np.copy(B)
+                    B2[0] = -e_PS * Um1[0]
+                    U1 = linsolve(K_N_C, B2)
+                    Fc1 = (K_N.mult(U1) - B) / (dt * dt)
+                    s1 = -Fc1[0]
+                    MV1 += dt * Fc1
+                else:
+                    s1 = 0
+                Fc1 = 0.0 * Fc
+            elif version == 2:  # Penalized contact
+                if U1[0] < 0:
                     U1 = linsolve(K_N_C, B)
-                    Fc1 = (K_N.mult(U1) - B)/(beta*dt*dt); s1 = -Fc1[0];
-                else: Fc1 = 0.*Fc; s1 = 0
-            else:                # Nitsche contact
-                md.set_variable('u', U1); ux = 
md.interpolation('Grad_u',[0.],m)
-                if ((gamma0_N/h)*U1[0]+ux < 0):
-                    U1 = linsolve(K_N_C, B); md.set_variable('u', U1);
-                    ux = md.interpolation('Grad_u',[0.],m)
-                Fc1 = (K_N.mult(U1) - B)/(beta*dt*dt)
-                s1 = min(0.,(gamma0_N/h)*U1[0]+ux)
-            MA1 = Fc1-K.mult(U1);
-            MV1 += dt*((1.-gamma)*MA0 + gamma*MA1);
-            V1 = linsolve(M2, MV1); V1[Ndof-1] = 0.
-            if (mass_matrix_type >= 1): V1[0] = (U1[0] - U0[0])/dt
+                    Fc1 = (K_N.mult(U1) - B) / (beta * dt * dt)
+                    s1 = -Fc1[0]
+                else:
+                    Fc1 = 0.0 * Fc
+                    s1 = 0
+            else:  # Nitsche contact
+                md.set_variable("u", U1)
+                ux = md.interpolation("Grad_u", [0.0], m)
+                if (gamma0_N / h) * U1[0] + ux < 0:
+                    U1 = linsolve(K_N_C, B)
+                    md.set_variable("u", U1)
+                    ux = md.interpolation("Grad_u", [0.0], m)
+                Fc1 = (K_N.mult(U1) - B) / (beta * dt * dt)
+                s1 = min(0.0, (gamma0_N / h) * U1[0] + ux)
+            MA1 = Fc1 - K.mult(U1)
+            MV1 += dt * ((1.0 - gamma) * MA0 + gamma * MA1)
+            V1 = linsolve(M2, MV1)
+            V1[Ndof - 1] = 0.0
+            if mass_matrix_type >= 1:
+                V1[0] = (U1[0] - U0[0]) / dt
             MA0 = MA1
-        
+
         # End of time step
-        Um1 = np.copy(U0); U0 = np.copy(U1);
-        V0 = np.copy(V1); MV0 = np.copy(MV1); s0 = s1
-        md.set_variable('u', U0); md.set_variable('v', V0)
+        Um1 = np.copy(U0)
+        U0 = np.copy(U1)
+        V0 = np.copy(V1)
+        MV0 = np.copy(MV1)
+        s0 = s1
+        md.set_variable("u", U0)
+        md.set_variable("v", V0)
 
     # Compute the difference with the exact solution
-    for i in range(0,Ndof): Uex[i] = uExact(fem_nodes[0][i], t)
-    for i in range(0,Ndof): Vex[i] = uExact(fem_nodes[0][i], t, 2)
+    for i in range(0, Ndof):
+        Uex[i] = uExact(fem_nodes[0][i], t)
+    for i in range(0, Ndof):
+        Vex[i] = uExact(fem_nodes[0][i], t, 2)
 
     # Compute the Energy
-    MMV0 = M.mult(V0); KU0 = K.mult(U0)
-    E = (np.vdot(MMV0, V0) + np.vdot(KU0, U0))*0.5
+    MMV0 = M.mult(V0)
+    KU0 = K.mult(U0)
+    E = (np.vdot(MMV0, V0) + np.vdot(KU0, U0)) * 0.5
     E_org = E
-    if (version == 2): # Energy stored in the penalized contact
-        E += (gamma0_P/h)*pow(min(0., U0[0]),2)/2
-    if (version == 3): # Nitsche Energy
-        E += (0.5*theta_N)*(h/gamma0_N)*(s0*s0-ux*ux);
-    
+    if version == 2:  # Energy stored in the penalized contact
+        E += (gamma0_P / h) * pow(min(0.0, U0[0]), 2) / 2
+    if version == 3:  # Nitsche Energy
+        E += (0.5 * theta_N) * (h / gamma0_N) * (s0 * s0 - ux * ux)
+
     # Store the data to be ploted at the end
-    store_u0[nit] = U0[0]; store_u0_ex[nit] = uExact(0., t)
-    store_v0[nit] = V0[0]; store_v0_ex[nit] = uExact(0., t, 2)
+    store_u0[nit] = U0[0]
+    store_u0_ex[nit] = uExact(0.0, t)
+    store_v0[nit] = V0[0]
+    store_v0_ex[nit] = uExact(0.0, t, 2)
     store_s0[nit] = s0
-    store_s0_ex[nit] = uExact(0., t, 1);
-    store_E[nit] = E;
+    store_s0_ex[nit] = uExact(0.0, t, 1)
+    store_E[nit] = E
     store_VL2_ex[nit] = gf.compute_L2_norm(mfu, Vex, mim)
     store_UL2_ex[nit] = gf.compute_L2_norm(mfu, Uex, mim)
     store_UH1_ex[nit] = gf.compute_H1_norm(mfu, Uex, mim)
-    store_VL2[nit] = gf.compute_L2_norm(mfu, V0-Vex, mim)
-    store_UL2[nit] = gf.compute_L2_norm(mfu, U0-Uex, mim)
-    store_UH1[nit] = gf.compute_H1_norm(mfu, U0-Uex, mim)
+    store_VL2[nit] = gf.compute_L2_norm(mfu, V0 - Vex, mim)
+    store_UL2[nit] = gf.compute_L2_norm(mfu, U0 - Uex, mim)
+    store_UH1[nit] = gf.compute_H1_norm(mfu, U0 - Uex, mim)
 
-    
-        
     # Draw the approximated and exact solutions
-    if (t >= tplot-(1e-10)):
-        tplot += dtplot;
-        print(("Time %3f"% t), "/", T, end=' ')
+    if t >= tplot - (1e-10):
+        tplot += dtplot
+        print(("Time %3f" % t), "/", T, end=" ")
         print((" Energy %7f" % E), (" Mech energy %7f" % E_org))
-        
-        if (do_inter_plot):
+
+        if do_inter_plot:
             UUex = np.copy(Xdraw)
-            plt.figure(1); plt.rc('text', usetex=True)
-            plt.subplot(311) # Displacement
-            for i in range(0,Ndraw): UUex[i] = uExact(Xdraw[i], t)
-            UU = md.interpolation('u', Xdraw, m)
-            plt.cla(); plt.axis([0.,1.,-0.6,0.6])
-            plt.plot(Xdraw, UUex, 'red'); plt.plot(Xdraw, UU, 'blue')
-            plt.ylabel('u'); plt.xlabel('x')
-            plt.subplot(312) # Velocity
-            for i in range(0,Ndraw): UUex[i] = uExact(Xdraw[i], t, 2)
-            UU = md.interpolation('v', Xdraw, m)
-            plt.cla(); plt.axis([0.,1.,-0.6,0.6])
-            plt.plot(Xdraw, UUex, 'red'); plt.plot(Xdraw, UU, 'blue')
-            plt.ylabel('v'); plt.xlabel('x')
-            plt.subplot(313) # Stress
-            for i in range(0,Ndraw): UUex[i] = uExact(Xdraw[i], t, 1)
-            UU = md.interpolation('Grad_u', Xdraw, m)
-            plt.cla(); plt.axis([0.,1.,-0.6,0.6])
-            plt.plot(Xdraw, UUex, 'red'); plt.plot(Xdraw, UU, 'blue')
-            plt.ylabel('$\partial_x u$'); plt.xlabel('x')
-            plt.pause(0.01); plt.show(0)
-    
-
-    
+            plt.figure(1)
+            plt.rc("text", usetex=True)
+            plt.subplot(311)  # Displacement
+            for i in range(0, Ndraw):
+                UUex[i] = uExact(Xdraw[i], t)
+            UU = md.interpolation("u", Xdraw, m)
+            plt.cla()
+            plt.axis([0.0, 1.0, -0.6, 0.6])
+            plt.plot(Xdraw, UUex, "red")
+            plt.plot(Xdraw, UU, "blue")
+            plt.ylabel("u")
+            plt.xlabel("x")
+            plt.subplot(312)  # Velocity
+            for i in range(0, Ndraw):
+                UUex[i] = uExact(Xdraw[i], t, 2)
+            UU = md.interpolation("v", Xdraw, m)
+            plt.cla()
+            plt.axis([0.0, 1.0, -0.6, 0.6])
+            plt.plot(Xdraw, UUex, "red")
+            plt.plot(Xdraw, UU, "blue")
+            plt.ylabel("v")
+            plt.xlabel("x")
+            plt.subplot(313)  # Stress
+            for i in range(0, Ndraw):
+                UUex[i] = uExact(Xdraw[i], t, 1)
+            UU = md.interpolation("Grad_u", Xdraw, m)
+            plt.cla()
+            plt.axis([0.0, 1.0, -0.6, 0.6])
+            plt.plot(Xdraw, UUex, "red")
+            plt.plot(Xdraw, UU, "blue")
+            plt.ylabel("$\partial_x u$")
+            plt.xlabel("x")
+            plt.pause(0.01)
+            plt.show(0)
+
+
 # print the main relative errors
 LinfL2u = np.amax(store_UL2) / np.amax(store_UL2_ex)
-print('L^\intfy(0,T,L^2)-norm of the error on u: ', LinfL2u)
+print("L^\intfy(0,T,L^2)-norm of the error on u: ", LinfL2u)
 LinfH1u = np.amax(store_UH1) / np.amax(store_UH1_ex)
-print('L^\intfy(0,T,H^1)-norm of the error on u: ', LinfH1u)
+print("L^\intfy(0,T,H^1)-norm of the error on u: ", LinfH1u)
 LinfL2v = np.amax(store_VL2) / np.amax(store_VL2_ex)
-print('L^\intfy(0,T,L^2)-norm of the error on v: ', LinfL2v)
-Nor = np.sqrt(np.sum(np.square(store_UL2_ex))*dt)
-L2L2u = np.sqrt(np.sum(np.square(store_UL2))*dt) / Nor
-print('L^2(0,T,L^2)-norm of the error on u: ', L2L2u)
-Nor = np.sqrt(np.sum(np.square(store_UH1_ex))*dt)
-L2H1u = np.sqrt(np.sum(np.square(store_UH1))*dt) / Nor
-print('L^2(0,T,H^1)-norm of the error on u: ', L2H1u)
-Nor = np.sqrt(np.sum(np.square(store_VL2_ex))*dt)
-L2L2v = np.sqrt(np.sum(np.square(store_VL2))*dt) / Nor
-print('L^2(0,T)-norm of the error on v: ', L2L2v)
-Nor = np.sqrt(np.sum(np.square(store_s0_ex))*dt)
-L2sn = np.sqrt(np.sum(np.square(store_s0-store_s0_ex))*dt) / Nor
-print('L^2(0,T)-norm of the error on contact stress: ', L2sn)
-
-
-if (do_export_in_files):
-    if (not os.path.exists(output_directory)):
+print("L^\intfy(0,T,L^2)-norm of the error on v: ", LinfL2v)
+Nor = np.sqrt(np.sum(np.square(store_UL2_ex)) * dt)
+L2L2u = np.sqrt(np.sum(np.square(store_UL2)) * dt) / Nor
+print("L^2(0,T,L^2)-norm of the error on u: ", L2L2u)
+Nor = np.sqrt(np.sum(np.square(store_UH1_ex)) * dt)
+L2H1u = np.sqrt(np.sum(np.square(store_UH1)) * dt) / Nor
+print("L^2(0,T,H^1)-norm of the error on u: ", L2H1u)
+Nor = np.sqrt(np.sum(np.square(store_VL2_ex)) * dt)
+L2L2v = np.sqrt(np.sum(np.square(store_VL2)) * dt) / Nor
+print("L^2(0,T)-norm of the error on v: ", L2L2v)
+Nor = np.sqrt(np.sum(np.square(store_s0_ex)) * dt)
+L2sn = np.sqrt(np.sum(np.square(store_s0 - store_s0_ex)) * dt) / Nor
+print("L^2(0,T)-norm of the error on contact stress: ", L2sn)
+
+
+if do_export_in_files:
+    if not os.path.exists(output_directory):
         os.makedirs(output_directory)
 
     # Parameter file
-    pf = open(output_directory+'/' + root_filename + '.params', 'w')
-    pf.write('NX = %d;' % NX);            pf.write('T = %g;' % T)
-    pf.write('dt = %g;' % dt);            pf.write('u_degree = %d;' % u_degree)
-    pf.write('gamma0_N = %g;' % gamma0_N);pf.write('theta_N =  %g;' % theta_N)
-    pf.write('gamma0_P = %g;' % gamma0_P);pf.write('beta = %g;' % beta)
-    pf.write('gamma = %g;' % gamma);      pf.write('e_PS = %g;' % e_PS);
-    pf.write('version = %d;' % version)
-    pf.write('mass_matrix_type = %d;' % mass_matrix_type)
+    pf = open(output_directory + "/" + root_filename + ".params", "w")
+    pf.write("NX = %d;" % NX)
+    pf.write("T = %g;" % T)
+    pf.write("dt = %g;" % dt)
+    pf.write("u_degree = %d;" % u_degree)
+    pf.write("gamma0_N = %g;" % gamma0_N)
+    pf.write("theta_N =  %g;" % theta_N)
+    pf.write("gamma0_P = %g;" % gamma0_P)
+    pf.write("beta = %g;" % beta)
+    pf.write("gamma = %g;" % gamma)
+    pf.write("e_PS = %g;" % e_PS)
+    pf.write("version = %d;" % version)
+    pf.write("mass_matrix_type = %d;" % mass_matrix_type)
     pf.close()
 
     # Export solutions
-    np.save(output_directory+'/' + root_filename + '.u0.npy', store_u0);
-    np.save(output_directory+'/' + root_filename + '.v0.npy', store_v0);
-    np.save(output_directory+'/' + root_filename + '.s0.npy', store_s0);
-    np.save(output_directory+'/' + root_filename + '.E.npy' , store_E );
-    
+    np.save(output_directory + "/" + root_filename + ".u0.npy", store_u0)
+    np.save(output_directory + "/" + root_filename + ".v0.npy", store_v0)
+    np.save(output_directory + "/" + root_filename + ".s0.npy", store_s0)
+    np.save(output_directory + "/" + root_filename + ".E.npy", store_E)
+
     # write error norms
-    pf = open(output_directory+'/' + root_filename + '.err_norms', 'w')
-    pf.write('LinfL2u = %g;' % LinfL2u); pf.write('LinfH1u = %g;' % LinfH1u)
-    pf.write('LinfL2v = %g;' % LinfL2v); pf.write('L2L2u = %g;' % L2L2u)
-    pf.write('L2H1u = %g;' % L2H1u);     pf.write('L2L2v = %g;' % L2L2v)
-    pf.write('L2sn = %g;' % L2sn)
+    pf = open(output_directory + "/" + root_filename + ".err_norms", "w")
+    pf.write("LinfL2u = %g;" % LinfL2u)
+    pf.write("LinfH1u = %g;" % LinfH1u)
+    pf.write("LinfL2v = %g;" % LinfL2v)
+    pf.write("L2L2u = %g;" % L2L2u)
+    pf.write("L2H1u = %g;" % L2H1u)
+    pf.write("L2L2v = %g;" % L2L2v)
+    pf.write("L2sn = %g;" % L2sn)
     pf.close()
-    
-    
-
-
-
-if (do_final_plot):
-    plt.figure(2); # Displacement evolution at the contact boundary
-    plt.cla(); plt.axis([0.,T,-0.15,0.6])
-    plt.plot(TT, store_u0_ex, 'red')
-    plt.plot(TT, store_u0, 'blue')
-    plt.ylabel('u(0)'); plt.xlabel('t')
-    
-    plt.figure(3); # velocity evolution at the contact boundary
-    plt.cla(); plt.axis([0.,T,-0.6,0.6])
-    plt.plot(TT, store_v0_ex, 'red')
-    plt.plot(TT, store_v0, 'blue')
-    plt.ylabel('v(0)'); plt.xlabel('t')
-
-    plt.figure(4); # stress evolution at the contact boundary
-    plt.cla(); plt.axis([0.,T,-0.6,0.6])
-    plt.plot(TT, store_s0_ex, 'red')
-    plt.plot(TT, store_s0, 'blue')
-    plt.ylabel('contact pressure'); plt.xlabel('t')
-
-    plt.figure(5); # Energy evolution
-    plt.cla(); plt.axis([0.,T,0,0.6])
-    plt.plot([0.,T], [1./8., 1./8.], 'red')
-    plt.plot(TT, store_E, 'blue')
-    plt.ylabel('Energy'); plt.xlabel('t')
-
-    plt.figure(6);
-    plt.subplot(311) # L2-norm of the error evolution
-    plt.cla(); plt.axis([0.,T,0,0.6])
-    plt.plot(TT, store_UL2, 'blue')
-    plt.ylabel('$L^2$-error on $u$'); plt.xlabel('t')
-    plt.subplot(312) # L2-norm of the error evolution
-    plt.cla(); plt.axis([0.,T,0,0.6])
-    plt.plot(TT, store_UH1, 'blue')
-    plt.ylabel('$H^1$-error on $u$'); plt.xlabel('t')
-    plt.subplot(313) # L2-norm of the error evolution
-    plt.cla(); plt.axis([0.,T,0,0.6])
-    plt.plot(TT, store_VL2, 'blue')
-    plt.ylabel('$L^2$-error on $v$'); plt.xlabel('t')
-    
+
+
+if do_final_plot:
+    plt.figure(2)
+    # Displacement evolution at the contact boundary
+    plt.cla()
+    plt.axis([0.0, T, -0.15, 0.6])
+    plt.plot(TT, store_u0_ex, "red")
+    plt.plot(TT, store_u0, "blue")
+    plt.ylabel("u(0)")
+    plt.xlabel("t")
+
+    plt.figure(3)
+    # velocity evolution at the contact boundary
+    plt.cla()
+    plt.axis([0.0, T, -0.6, 0.6])
+    plt.plot(TT, store_v0_ex, "red")
+    plt.plot(TT, store_v0, "blue")
+    plt.ylabel("v(0)")
+    plt.xlabel("t")
+
+    plt.figure(4)
+    # stress evolution at the contact boundary
+    plt.cla()
+    plt.axis([0.0, T, -0.6, 0.6])
+    plt.plot(TT, store_s0_ex, "red")
+    plt.plot(TT, store_s0, "blue")
+    plt.ylabel("contact pressure")
+    plt.xlabel("t")
+
+    plt.figure(5)
+    # Energy evolution
+    plt.cla()
+    plt.axis([0.0, T, 0, 0.6])
+    plt.plot([0.0, T], [1.0 / 8.0, 1.0 / 8.0], "red")
+    plt.plot(TT, store_E, "blue")
+    plt.ylabel("Energy")
+    plt.xlabel("t")
+
+    plt.figure(6)
+    plt.subplot(311)  # L2-norm of the error evolution
+    plt.cla()
+    plt.axis([0.0, T, 0, 0.6])
+    plt.plot(TT, store_UL2, "blue")
+    plt.ylabel("$L^2$-error on $u$")
+    plt.xlabel("t")
+    plt.subplot(312)  # L2-norm of the error evolution
+    plt.cla()
+    plt.axis([0.0, T, 0, 0.6])
+    plt.plot(TT, store_UH1, "blue")
+    plt.ylabel("$H^1$-error on $u$")
+    plt.xlabel("t")
+    plt.subplot(313)  # L2-norm of the error evolution
+    plt.cla()
+    plt.axis([0.0, T, 0, 0.6])
+    plt.plot(TT, store_VL2, "blue")
+    plt.ylabel("$L^2$-error on $v$")
+    plt.xlabel("t")
+
     plt.show()
diff --git a/interface/tests/python/demo_elastic_ring_contact.py 
b/interface/tests/python/demo_elastic_ring_contact.py
index 26ba6fd..663a363 100644
--- a/interface/tests/python/demo_elastic_ring_contact.py
+++ b/interface/tests/python/demo_elastic_ring_contact.py
@@ -28,31 +28,31 @@ import time
 gf.util_trace_level(1)
 
 # Input data
-ri = 90.   # ring inner diameter
-t1 = 5.    # inner layer thickness
-t2 = 5.    # outer layer thickness
-Ncirc = 64 # number of elements in the ring circumferential direction
-Nt1 = 1    # number of elements in first layer thickness direction
-Nt2 = 1    # number of elements in second layer thickness direction
-lx = 260.  # length of obstacle block
-ly = 50.   # height of obstacle block
-Nx = 52    # number of elements in block length direction
-Ny = 10    # number of elements in block height direction
-
-E1 = 1e5   # Young's modulus
+ri = 90.0  # ring inner diameter
+t1 = 5.0  # inner layer thickness
+t2 = 5.0  # outer layer thickness
+Ncirc = 64  # number of elements in the ring circumferential direction
+Nt1 = 1  # number of elements in first layer thickness direction
+Nt2 = 1  # number of elements in second layer thickness direction
+lx = 260.0  # length of obstacle block
+ly = 50.0  # height of obstacle block
+Nx = 52  # number of elements in block length direction
+Ny = 10  # number of elements in block height direction
+
+E1 = 1e5  # Young's modulus
 nu1 = 0.3  # Poisson's ratio
-E2 = 1e3   # Young's modulus
+E2 = 1e3  # Young's modulus
 nu2 = 0.3  # Poisson's ratio
-E = 1e8    # Young's modulus
-nu = 0.    # Poisson's ratio
+E = 1e8  # Young's modulus
+nu = 0.0  # Poisson's ratio
 
-g0 = 20.   # initial gap between ring and block
+g0 = 20.0  # initial gap between ring and block
 dg = -0.5  # vertical displacement per load step
-steps = 80 # number of load steps
+steps = 80  # number of load steps
 
-#------------------------------------
-geotrans_R = 'GT_QK(2,2)'  # geometric transformation for the ring mesh
-geotrans_B = 'GT_QK(2,2)'  # geometric transformation for the block mesh
+# ------------------------------------
+geotrans_R = "GT_QK(2,2)"  # geometric transformation for the ring mesh
+geotrans_B = "GT_QK(2,2)"  # geometric transformation for the block mesh
 
 fem_disp_order_R = 2  # displacements finite element order for the ring
 fem_disp_order_B = 2  # displacements finite element order for the block
@@ -67,27 +67,32 @@ integration_contact_degree_B = 4
 is_master_R = False
 is_master_B = True
 
-r_aug = 300.             # Augmentation parameter
-alpha = 1.               # Alpha coefficient for "sliding velocity"
-f_coeff = 0.             # Friction coefficient
-release_dist = 5.
-
-
-#------------------------------------
-clambda1 = E1*nu1 / ((1+nu1)*(1-2*nu1))
-cmu1 = E1 / (2*(1+nu1))
-clambda2 = E2*nu2 / ((1+nu2)*(1-2*nu2))
-cmu2 = E2 / (2*(1+nu2))
-clambda = E*nu / ((1+nu)*(1-2*nu))
-cmu = E / (2*(1+nu))
-
-
-mesh_R = gf.Mesh('import', 'structured',
-                 'GT="%s";ORG=[-1,-1];SIZES=[2,1];NSUBDIV=[%i,%i]'
-                 % (geotrans_R, Ncirc, Nt1+Nt2))
-mesh_B = gf.Mesh('import', 'structured',
-                 'GT="%s";ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]'
-                 % (geotrans_B, -lx/2, -ly, lx, ly, Nx, Ny))
+r_aug = 300.0  # Augmentation parameter
+alpha = 1.0  # Alpha coefficient for "sliding velocity"
+f_coeff = 0.0  # Friction coefficient
+release_dist = 5.0
+
+
+# ------------------------------------
+clambda1 = E1 * nu1 / ((1 + nu1) * (1 - 2 * nu1))
+cmu1 = E1 / (2 * (1 + nu1))
+clambda2 = E2 * nu2 / ((1 + nu2) * (1 - 2 * nu2))
+cmu2 = E2 / (2 * (1 + nu2))
+clambda = E * nu / ((1 + nu) * (1 - 2 * nu))
+cmu = E / (2 * (1 + nu))
+
+
+mesh_R = gf.Mesh(
+    "import",
+    "structured",
+    'GT="%s";ORG=[-1,-1];SIZES=[2,1];NSUBDIV=[%i,%i]' % (geotrans_R, Ncirc, 
Nt1 + Nt2),
+)
+mesh_B = gf.Mesh(
+    "import",
+    "structured",
+    'GT="%s";ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]'
+    % (geotrans_B, -lx / 2, -ly, lx, ly, Nx, Ny),
+)
 
 N = mesh_R.dim()
 
@@ -100,61 +105,61 @@ RING2 = 12
 
 outer_R = mesh_R.outer_faces()
 normals_R = mesh_R.normal_of_faces(outer_R)
-contact_boundary_R = outer_R[:,np.nonzero(normals_R[1] < -0.95)[0]]
+contact_boundary_R = outer_R[:, np.nonzero(normals_R[1] < -0.95)[0]]
 mesh_R.set_region(CONTACT_BOUNDARY_R, contact_boundary_R)
 
-dirichlet_boundary_R = outer_R[:,np.nonzero(np.absolute(normals_R[0]) > 
0.99)[0]]
+dirichlet_boundary_R = outer_R[:, np.nonzero(np.absolute(normals_R[0]) > 
0.99)[0]]
 mesh_R.set_region(DIRICHLET_BOUNDARY_R, dirichlet_boundary_R)
 
 pts_R = mesh_R.pts()
-y_interf = -float(Nt1)/float(Nt1+Nt2)
+y_interf = -float(Nt1) / float(Nt1 + Nt2)
 
-is_in_ring1 = pts_R[1,:] > y_interf-0.001
-is_in_ring2 = pts_R[1,:] < y_interf+0.001
+is_in_ring1 = pts_R[1, :] > y_interf - 0.001
+is_in_ring2 = pts_R[1, :] < y_interf + 0.001
 
 cvids = mesh_R.cvid()
-(pid,idx) = mesh_R.pid_from_cvid(cvids)
+(pid, idx) = mesh_R.pid_from_cvid(cvids)
 cvs_ring1 = []
 cvs_ring2 = []
-for i in range(idx.size-1):
-   cv = cvids[i]
-   if all(is_in_ring1[pid[idx[i]:idx[i+1]]]):
-      cvs_ring1.append(cv)
-   elif all(is_in_ring2[pid[idx[i]:idx[i+1]]]):
-      cvs_ring2.append(cv)
+for i in range(idx.size - 1):
+    cv = cvids[i]
+    if all(is_in_ring1[pid[idx[i] : idx[i + 1]]]):
+        cvs_ring1.append(cv)
+    elif all(is_in_ring2[pid[idx[i] : idx[i + 1]]]):
+        cvs_ring2.append(cv)
 mesh_R.set_region(RING1, np.array(cvs_ring1, ndmin=2))
 mesh_R.set_region(RING2, np.array(cvs_ring2, ndmin=2))
 
 for ip in range(pts_R.shape[1]):
-   x = pts_R[0,ip]
-   y = pts_R[1,ip]
-   if y >= y_interf: # ring 1
-      y *= t1/(-y_interf);
-      r = ri
-   else:
-      y -= y_interf
-      y *= t2/(1+y_interf);
-      r = ri + t1
-   pts_R[0,ip] = (r-y) * np.sin(np.pi*x/2.)
-   pts_R[1,ip] = g0+ri+t1+t2 - (r-y) * np.cos(np.pi*x/2.)
+    x = pts_R[0, ip]
+    y = pts_R[1, ip]
+    if y >= y_interf:  # ring 1
+        y *= t1 / (-y_interf)
+        r = ri
+    else:
+        y -= y_interf
+        y *= t2 / (1 + y_interf)
+        r = ri + t1
+    pts_R[0, ip] = (r - y) * np.sin(np.pi * x / 2.0)
+    pts_R[1, ip] = g0 + ri + t1 + t2 - (r - y) * np.cos(np.pi * x / 2.0)
 mesh_R.set_pts(pts_R)
 
 outer_B = mesh_B.outer_faces()
 normals_B = mesh_B.normal_of_faces(outer_B)
-contact_boundary_B = outer_B[:,np.nonzero(normals_B[1] > 0.95)[0]]
-dirichlet_boundary_B = outer_B[:,np.nonzero(normals_B[1] < -0.95)[0]]
+contact_boundary_B = outer_B[:, np.nonzero(normals_B[1] > 0.95)[0]]
+dirichlet_boundary_B = outer_B[:, np.nonzero(normals_B[1] < -0.95)[0]]
 mesh_B.set_region(CONTACT_BOUNDARY_B, contact_boundary_B)
 mesh_B.set_region(DIRICHLET_BOUNDARY_B, dirichlet_boundary_B)
 
-#pts_B = mesh_B.pts()
-#for ip in range(pts_B.shape[1]):
+# pts_B = mesh_B.pts()
+# for ip in range(pts_B.shape[1]):
 #   x = pts_B[0,ip]
 #   y = pts_B[1,ip]
 #   pts_B[1,ip] = y + 0.02*x**2
-#mesh_B.set_pts(pts_B)
+# mesh_B.set_pts(pts_B)
 
-#mesh_R.export_to_vtk('/tmp/mesh_R.vtk')
-#mesh_B.export_to_vtk('/tmp/mesh_B.vtk')
+# mesh_R.export_to_vtk('/tmp/mesh_R.vtk')
+# mesh_B.export_to_vtk('/tmp/mesh_B.vtk')
 
 # Ring
 mfu_R = gf.MeshFem(mesh_R, N)
@@ -164,7 +169,7 @@ pre_mflambda_R = gf.MeshFem(mesh_R, N)
 pre_mflambda_R.set_classical_fem(fem_mult_order_R)
 
 mfvm_R = gf.MeshFem(mesh_R)
-mfvm_R.set_classical_discontinuous_fem(fem_disp_order_R-1)
+mfvm_R.set_classical_discontinuous_fem(fem_disp_order_R - 1)
 
 mim_R = gf.MeshIm(mesh_R, integration_degree_R)
 mim_R_contact = gf.MeshIm(mesh_R, integration_contact_degree_R)
@@ -177,121 +182,165 @@ pre_mflambda_B = gf.MeshFem(mesh_B, N)
 pre_mflambda_B.set_classical_fem(fem_mult_order_B)
 
 mfvm_B = gf.MeshFem(mesh_B)
-mfvm_B.set_classical_discontinuous_fem(fem_disp_order_B-1)
+mfvm_B.set_classical_discontinuous_fem(fem_disp_order_B - 1)
 
 mim_B = gf.MeshIm(mesh_B, integration_degree_B)
 mim_B_contact = gf.MeshIm(mesh_B, integration_contact_degree_B)
 
 # Model
-md = gf.Model('real')
+md = gf.Model("real")
 
-md.add_fem_variable('uR', mfu_R)
+md.add_fem_variable("uR", mfu_R)
 if is_master_B:
-   md.add_filtered_fem_variable('lambda_ring', pre_mflambda_R, 
CONTACT_BOUNDARY_R)
+    md.add_filtered_fem_variable("lambda_ring", pre_mflambda_R, 
CONTACT_BOUNDARY_R)
 if f_coeff > 1e-10:
-   md.add_fem_data('wR', mfu_R)
+    md.add_fem_data("wR", mfu_R)
 
-#lawname = 'neo Hookean'
-#params_R1 = [cmu1/2., clambda1/2+cmu1/3]
-#params_R2 = [cmu2/2., clambda2/2+cmu2/3]
-#params_B = [cmu/2., clambda/2+cmu/3]
+# lawname = 'neo Hookean'
+# params_R1 = [cmu1/2., clambda1/2+cmu1/3]
+# params_R2 = [cmu2/2., clambda2/2+cmu2/3]
+# params_B = [cmu/2., clambda/2+cmu/3]
 
-lawname = 'neo Hookean Ciarlet'
+lawname = "neo Hookean Ciarlet"
 params_R1 = [clambda1, cmu1]
 params_R2 = [clambda2, cmu2]
 params_B = [clambda, cmu]
 
-#lawname = 'Ciarlet Geymonat'
-#params_R1 = [clambda1, cmu1, cmu1/2-clambda1/8]
-#params_R2 = [clambda2, cmu2, cmu2/2-clambda2/8]
-#params_B = [clambda, cmu, cmu/2-clambda/8]
+# lawname = 'Ciarlet Geymonat'
+# params_R1 = [clambda1, cmu1, cmu1/2-clambda1/8]
+# params_R2 = [clambda2, cmu2, cmu2/2-clambda2/8]
+# params_B = [clambda, cmu, cmu/2-clambda/8]
 
-md.add_initialized_data('params_ring1', params_R1)
-md.add_initialized_data('params_ring2', params_R2)
-md.add_nonlinear_elasticity_brick(mim_R, 'uR', lawname, 'params_ring1', RING1)
-md.add_nonlinear_elasticity_brick(mim_R, 'uR', lawname, 'params_ring2', RING2)
+md.add_initialized_data("params_ring1", params_R1)
+md.add_initialized_data("params_ring2", params_R2)
+md.add_nonlinear_elasticity_brick(mim_R, "uR", lawname, "params_ring1", RING1)
+md.add_nonlinear_elasticity_brick(mim_R, "uR", lawname, "params_ring2", RING2)
 
-md.add_fem_variable('uB', mfu_B)
+md.add_fem_variable("uB", mfu_B)
 if is_master_R:
-   md.add_filtered_fem_variable('lambda_block', pre_mflambda_B, 
CONTACT_BOUNDARY_B)
+    md.add_filtered_fem_variable("lambda_block", pre_mflambda_B, 
CONTACT_BOUNDARY_B)
 if f_coeff > 1e-10:
-   md.add_fem_data('wB', mfu_B)
-
-md.add_initialized_data('params_block', params_B)
-md.add_nonlinear_elasticity_brick(mim_B, 'uB', lawname, 'params_block')
-
-md.add_initialized_data('dirichlet_ring', np.zeros(N))
-md.add_Dirichlet_condition_with_multipliers(mim_R, 'uR', mfu_R, 
DIRICHLET_BOUNDARY_R, 'dirichlet_ring')
-
-md.add_initialized_data('dirichlet_block', np.zeros(N))
-md.add_Dirichlet_condition_with_multipliers(mim_B, 'uB', mfu_B, 
DIRICHLET_BOUNDARY_B, 'dirichlet_block')
-
-md.add_initialized_data('r', r_aug)
-md.add_initialized_data('alpha', alpha)
-md.add_initialized_data('f', f_coeff)
-ibc = md.add_integral_large_sliding_contact_brick_raytracing('r', 
release_dist, 'f', 'alpha', 0)
-
-wR_str = ''
-wB_str = ''
+    md.add_fem_data("wB", mfu_B)
+
+md.add_initialized_data("params_block", params_B)
+md.add_nonlinear_elasticity_brick(mim_B, "uB", lawname, "params_block")
+
+md.add_initialized_data("dirichlet_ring", np.zeros(N))
+md.add_Dirichlet_condition_with_multipliers(
+    mim_R, "uR", mfu_R, DIRICHLET_BOUNDARY_R, "dirichlet_ring"
+)
+
+md.add_initialized_data("dirichlet_block", np.zeros(N))
+md.add_Dirichlet_condition_with_multipliers(
+    mim_B, "uB", mfu_B, DIRICHLET_BOUNDARY_B, "dirichlet_block"
+)
+
+md.add_initialized_data("r", r_aug)
+md.add_initialized_data("alpha", alpha)
+md.add_initialized_data("f", f_coeff)
+ibc = md.add_integral_large_sliding_contact_brick_raytracing(
+    "r", release_dist, "f", "alpha", 0
+)
+
+wR_str = ""
+wB_str = ""
 if f_coeff > 1e-10:
-   wR_str = 'wR'
-   wB_str = 'wB'
+    wR_str = "wR"
+    wB_str = "wB"
 
 if not is_master_R:
-   md.add_slave_contact_boundary_to_large_sliding_contact_brick\
-   (ibc, mim_R_contact, CONTACT_BOUNDARY_R, 'uR', 'lambda_ring', wR_str)
+    md.add_slave_contact_boundary_to_large_sliding_contact_brick(
+        ibc, mim_R_contact, CONTACT_BOUNDARY_R, "uR", "lambda_ring", wR_str
+    )
 elif is_master_R and is_master_B:
-   md.add_master_slave_contact_boundary_to_large_sliding_contact_brick\
-   (ibc, mim_R_contact, CONTACT_BOUNDARY_R, 'uR', 'lambda_ring', wR_str)
+    md.add_master_slave_contact_boundary_to_large_sliding_contact_brick(
+        ibc, mim_R_contact, CONTACT_BOUNDARY_R, "uR", "lambda_ring", wR_str
+    )
 else:
-   md.add_master_contact_boundary_to_large_sliding_contact_brick\
-   (ibc, mim_R_contact, CONTACT_BOUNDARY_R, 'uR', wR_str)
+    md.add_master_contact_boundary_to_large_sliding_contact_brick(
+        ibc, mim_R_contact, CONTACT_BOUNDARY_R, "uR", wR_str
+    )
 
 if not is_master_B:
-   md.add_slave_contact_boundary_to_large_sliding_contact_brick\
-   (ibc, mim_B_contact, CONTACT_BOUNDARY_B, 'uB', 'lambda_block', wB_str)
+    md.add_slave_contact_boundary_to_large_sliding_contact_brick(
+        ibc, mim_B_contact, CONTACT_BOUNDARY_B, "uB", "lambda_block", wB_str
+    )
 elif is_master_B and is_master_R:
-   md.add_master_slave_contact_boundary_to_large_sliding_contact_brick\
-   (ibc, mim_B_contact, CONTACT_BOUNDARY_B, 'uB', 'lambda_block', wB_str)
+    md.add_master_slave_contact_boundary_to_large_sliding_contact_brick(
+        ibc, mim_B_contact, CONTACT_BOUNDARY_B, "uB", "lambda_block", wB_str
+    )
 else:
-   md.add_master_contact_boundary_to_large_sliding_contact_brick\
-   (ibc, mim_B_contact, CONTACT_BOUNDARY_B, 'uB', wB_str)
+    md.add_master_contact_boundary_to_large_sliding_contact_brick(
+        ibc, mim_B_contact, CONTACT_BOUNDARY_B, "uB", wB_str
+    )
 
 dirichlet_R = np.zeros(N)
-for nit in range(steps+1):
-
-   if nit == 0:
-     dirichlet_R[N-1] -= g0
-   else:
-     dirichlet_R[N-1] += dg
-   md.set_variable('dirichlet_ring', dirichlet_R)
-
-   if f_coeff > 1e-10:
-      md.set_variable('wR', md.variable('uR'))
-      md.set_variable('wB', md.variable('uB'))
-
-   starttime = time.clock()
-   md.solve('noisy', 'max_iter', 40, 'max_res', 1e-8, #)[0]
-            'lsearch', 'simplest', 'alpha max ratio', 1.5, 'alpha min', 0.2, 
'alpha mult', 0.6)[0]
-   print('solution time for iteration %i is %f sec' % (nit, 
time.clock()-starttime))
-
-   U_R = md.variable('uR')
-   VM_R = md.compute_Von_Mises_or_Tresca('uR', lawname, 'params_ring1', mfvm_R)
-   mfvm_R.export_to_vtk('lsc_R_%i.vtk' % nit, mfvm_R,  VM_R,
-                        'Von Mises Stresses', mfu_R, U_R, 'Displacements')
-
-   lambda_R = md.variable('lambda_ring')
-   mf_lambda_R = md.mesh_fem_of_variable('lambda_ring')
-   sl = gf.Slice(('boundary',), mf_lambda_R, CONTACT_BOUNDARY_R)
-   sl.export_to_vtk('lsc_R_boundary_%i.vtk' % nit,
-                    mfu_R, U_R, 'BDisplacements',
-                    mf_lambda_R, lambda_R, 'BMultiplier')
-
-   U_B = md.variable('uB')
-   VM_B = md.compute_Von_Mises_or_Tresca('uB', lawname, 'params_block', mfvm_B)
-   mfvm_B.export_to_vtk('lsc_B_%i.vtk' % nit, mfvm_B,  VM_B,
-                        'Von Mises Stresses', mfu_B, U_B, 'Displacements')
-
-   sl = gf.Slice(('boundary',), mfu_B, CONTACT_BOUNDARY_B)
-   sl.export_to_vtk('lsc_B_boundary_%i.vtk' % nit,
-                    mfu_B, U_B, 'BDisplacements')
+for nit in range(steps + 1):
+
+    if nit == 0:
+        dirichlet_R[N - 1] -= g0
+    else:
+        dirichlet_R[N - 1] += dg
+    md.set_variable("dirichlet_ring", dirichlet_R)
+
+    if f_coeff > 1e-10:
+        md.set_variable("wR", md.variable("uR"))
+        md.set_variable("wB", md.variable("uB"))
+
+    starttime = time.clock()
+    md.solve(
+        "noisy",
+        "max_iter",
+        40,
+        "max_res",
+        1e-8,  # )[0]
+        "lsearch",
+        "simplest",
+        "alpha max ratio",
+        1.5,
+        "alpha min",
+        0.2,
+        "alpha mult",
+        0.6,
+    )[0]
+    print("solution time for iteration %i is %f sec" % (nit, time.clock() - 
starttime))
+
+    U_R = md.variable("uR")
+    VM_R = md.compute_Von_Mises_or_Tresca("uR", lawname, "params_ring1", 
mfvm_R)
+    mfvm_R.export_to_vtk(
+        "lsc_R_%i.vtk" % nit,
+        mfvm_R,
+        VM_R,
+        "Von Mises Stresses",
+        mfu_R,
+        U_R,
+        "Displacements",
+    )
+
+    lambda_R = md.variable("lambda_ring")
+    mf_lambda_R = md.mesh_fem_of_variable("lambda_ring")
+    sl = gf.Slice(("boundary",), mf_lambda_R, CONTACT_BOUNDARY_R)
+    sl.export_to_vtk(
+        "lsc_R_boundary_%i.vtk" % nit,
+        mfu_R,
+        U_R,
+        "BDisplacements",
+        mf_lambda_R,
+        lambda_R,
+        "BMultiplier",
+    )
+
+    U_B = md.variable("uB")
+    VM_B = md.compute_Von_Mises_or_Tresca("uB", lawname, "params_block", 
mfvm_B)
+    mfvm_B.export_to_vtk(
+        "lsc_B_%i.vtk" % nit,
+        mfvm_B,
+        VM_B,
+        "Von Mises Stresses",
+        mfu_B,
+        U_B,
+        "Displacements",
+    )
+
+    sl = gf.Slice(("boundary",), mfu_B, CONTACT_BOUNDARY_B)
+    sl.export_to_vtk("lsc_B_boundary_%i.vtk" % nit, mfu_B, U_B, 
"BDisplacements")
diff --git a/interface/tests/python/demo_fictitious_domains.py 
b/interface/tests/python/demo_fictitious_domains.py
index 67302af..d61c64b 100644
--- a/interface/tests/python/demo_fictitious_domains.py
+++ b/interface/tests/python/demo_fictitious_domains.py
@@ -29,108 +29,112 @@
 """
 import getfem as gf
 import numpy as np
-from scipy import rand,setdiff1d
+from scipy import rand, setdiff1d
 
-eps = 1.0/40
+eps = 1.0 / 40
 ls_degree = 2
 
-m = gf.Mesh('cartesian', np.arange(-.5,.5+eps,eps), np.arange(-.5,.5+eps,eps))
-#m = gf.Mesh('triangles grid', np.arange(-.5,.5+eps,eps), 
np.arange(-.5,.5+eps,eps))
-ls = gf.LevelSet(m,ls_degree)
-ls2 = gf.LevelSet(m, ls_degree, 'with_secondary')
+m = gf.Mesh(
+    "cartesian", np.arange(-0.5, 0.5 + eps, eps), np.arange(-0.5, 0.5 + eps, 
eps)
+)
+# m = gf.Mesh('triangles grid', np.arange(-.5,.5+eps,eps), 
np.arange(-.5,.5+eps,eps))
+ls = gf.LevelSet(m, ls_degree)
+ls2 = gf.LevelSet(m, ls_degree, "with_secondary")
 
 mf_ls = ls.mf()
 mf_ls2 = ls2.mf()
 
 P = mf_ls.basic_dof_nodes()
-x = P[0,:]
-y = P[1,:]
-#ULS = ((x + 0.25)**2 + (y - 0.4)**2) - 0.05**2
-#ULS = min(ULS, ((x - 0.25)**2 + (y - 0.4)**2) - 0.05**2)
+x = P[0, :]
+y = P[1, :]
+# ULS = ((x + 0.25)**2 + (y - 0.4)**2) - 0.05**2
+# ULS = min(ULS, ((x - 0.25)**2 + (y - 0.4)**2) - 0.05**2)
 
-ULS = 1000*np.ones(x.shape)
+ULS = 1000 * np.ones(x.shape)
 
 if True:
-  for ix in range(0,5):
-    for iy in range(0,5):
-      xc = (ix/4) * 0.8 - 0.4
-      yc = (iy/4) * 0.8 - 0.4
-      if (iy%2)==1:
-        xc = xc + 0.05
-      else:
-        xc = xc - 0.05
-      R = 0.03 + 0.005*iy
-      ULS = np.minimum(ULS, ((x - xc)**2 + (y - yc)**2) - R**2);
+    for ix in range(0, 5):
+        for iy in range(0, 5):
+            xc = (ix / 4) * 0.8 - 0.4
+            yc = (iy / 4) * 0.8 - 0.4
+            if (iy % 2) == 1:
+                xc = xc + 0.05
+            else:
+                xc = xc - 0.05
+            R = 0.03 + 0.005 * iy
+            ULS = np.minimum(ULS, ((x - xc) ** 2 + (y - yc) ** 2) - R ** 2)
 else:
-  for i in range(8):
-    xc = rand() - 0.5
-    yc = rand() - 0.5
-    R = rand() * 0.09 + 0.02
-    ULS = np.minimum(ULS, ((x - xc)**2 + (y - yc)**2) - R**2);
+    for i in range(8):
+        xc = rand() - 0.5
+        yc = rand() - 0.5
+        R = rand() * 0.09 + 0.02
+        ULS = np.minimum(ULS, ((x - xc) ** 2 + (y - yc) ** 2) - R ** 2)
 ls.set_values(ULS)
 
-ULS2 = 1000*np.ones(x.shape);
-ULS2s = 1000*np.ones(x.shape);
+ULS2 = 1000 * np.ones(x.shape)
+ULS2s = 1000 * np.ones(x.shape)
 for i in range(1):
-  xc = 0.0 # rand() - 0.5
-  yc = 0.0 # rand() - 0.5
-  theta = np.pi/3 # np.pi*rand()
-  n = [-np.sin(theta), np.cos(theta)]
+    xc = 0.0  # rand() - 0.5
+    yc = 0.0  # rand() - 0.5
+    theta = np.pi / 3  # np.pi*rand()
+    n = [-np.sin(theta), np.cos(theta)]
 
-  R = 0.19 #rand() * 0.09 + 0.02
-  ULS2 = np.minimum(ULS2, ((x-xc)*n[0] + (y-yc)*n[1]))
-  #ULS2s = np.minimum(ULS2s, ((x - xc)**2 + (y - yc)**2) - R**2)
-  ULS2s = np.minimum(ULS2s, (abs(y - yc)+abs(x-xc) - R))
+    R = 0.19  # rand() * 0.09 + 0.02
+    ULS2 = np.minimum(ULS2, ((x - xc) * n[0] + (y - yc) * n[1]))
+    # ULS2s = np.minimum(ULS2s, ((x - xc)**2 + (y - yc)**2) - R**2)
+    ULS2s = np.minimum(ULS2s, (abs(y - yc) + abs(x - xc) - R))
 
-ls2.set_values(ULS2, ULS2s) # '-y-x+.2') # '(y-.2)^2 - 0.04')
+ls2.set_values(ULS2, ULS2s)  # '-y-x+.2') # '(y-.2)^2 - 0.04')
 
 mls = gf.MeshLevelSet(m)
 mls.add(ls)
 mls.add(ls2)
 mls.adapt()
-mls.cut_mesh().export_to_pos('ver.pos')
+mls.cut_mesh().export_to_pos("ver.pos")
 
-mim_bound = gf.MeshIm('levelset',mls,'boundary(a+b)', 
gf.Integ('IM_TRIANGLE(6)')) #, gf.Integ('IM_QUAD(5)'))
-mim = gf.MeshIm('levelset',mls,'all(a+b)', gf.Integ('IM_TRIANGLE(6)'))
+mim_bound = gf.MeshIm(
+    "levelset", mls, "boundary(a+b)", gf.Integ("IM_TRIANGLE(6)")
+)  # , gf.Integ('IM_QUAD(5)'))
+mim = gf.MeshIm("levelset", mls, "all(a+b)", gf.Integ("IM_TRIANGLE(6)"))
 mim.set_integ(4)
 
-mfu0 = gf.MeshFem(m,2)
-mfu0.set_fem(gf.Fem('FEM_QK(2,3)'))
+mfu0 = gf.MeshFem(m, 2)
+mfu0.set_fem(gf.Fem("FEM_QK(2,3)"))
 
-mfdu = gf.MeshFem(m,1)
-mfdu.set_fem(gf.Fem('FEM_QK_DISCONTINUOUS(2,2)'))
+mfdu = gf.MeshFem(m, 1)
+mfdu.set_fem(gf.Fem("FEM_QK_DISCONTINUOUS(2,2)"))
 
-mf_mult = gf.MeshFem(m,2)
-mf_mult.set_fem(gf.Fem('FEM_QK(2,1)'))
+mf_mult = gf.MeshFem(m, 2)
+mf_mult.set_fem(gf.Fem("FEM_QK(2,1)"))
 
-A = gf.asm('volumic','V()+=comp()',mim_bound)
+A = gf.asm("volumic", "V()+=comp()", mim_bound)
 
-#mls.cut_mesh().export_to_pos('mls.pos','cut mesh')
-#mf_ls.export_to_pos('mf_ls.pos',ULS,'ULS')
+# mls.cut_mesh().export_to_pos('mls.pos','cut mesh')
+# mf_ls.export_to_pos('mf_ls.pos',ULS,'ULS')
 
 dof_out = mfu0.dof_from_im(mim)
 cv_out = mim.convex_index()
-cv_in = setdiff1d(m.cvid(),cv_out)
+cv_in = setdiff1d(m.cvid(), cv_out)
 
 # mfu = gf.MeshFem('partial', mfu0, dof_out, cv_in)
 
-md = gf.Model('real')
-md.add_fem_variable('u', mfu0)
-md.add_initialized_data('lambda', [1])
-md.add_initialized_data('mu', [1])
-md.add_isotropic_linearized_elasticity_brick(mim, 'u', 'lambda', 'mu')
-md.add_initialized_data('VolumicData', [0, 10])
-md.add_source_term_brick( mim, 'u', 'VolumicData')
-md.add_multiplier('mult_dir', mf_mult, 'u')
-md.add_Dirichlet_condition_with_multipliers(mim_bound, 'u', 'mult_dir', -1)
+md = gf.Model("real")
+md.add_fem_variable("u", mfu0)
+md.add_initialized_data("lambda", [1])
+md.add_initialized_data("mu", [1])
+md.add_isotropic_linearized_elasticity_brick(mim, "u", "lambda", "mu")
+md.add_initialized_data("VolumicData", [0, 10])
+md.add_source_term_brick(mim, "u", "VolumicData")
+md.add_multiplier("mult_dir", mf_mult, "u")
+md.add_Dirichlet_condition_with_multipliers(mim_bound, "u", "mult_dir", -1)
 md.solve()
 
-U = md.variable('u')
-VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u', 'lambda', 'mu', 
mfdu)
+U = md.variable("u")
+VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca("u", "lambda", "mu", 
mfdu)
 
-mfdu.export_to_pos('vm.pos', VM, 'Von Mises', mfu0, U, 'deformation')
+mfdu.export_to_pos("vm.pos", VM, "Von Mises", mfu0, U, "deformation")
 
-mf_ls.export_to_pos('ls.pos',ls.values(0),'ls values 0')
+mf_ls.export_to_pos("ls.pos", ls.values(0), "ls values 0")
 
-print('You can view the solution with (for instance):')
-print('gmsh vm.pos ls.pos')
+print("You can view the solution with (for instance):")
+print("gmsh vm.pos ls.pos")
diff --git a/interface/tests/python/demo_finite_strain_plasticity.py 
b/interface/tests/python/demo_finite_strain_plasticity.py
index e8bdb37..c5804d3 100644
--- a/interface/tests/python/demo_finite_strain_plasticity.py
+++ b/interface/tests/python/demo_finite_strain_plasticity.py
@@ -31,75 +31,77 @@ np.set_printoptions(threshold=np.nan)
 gf.util_trace_level(1)
 
 # Input data
-UL = 1.             # unit length
-UF = 1.             # unit force
+UL = 1.0  # unit length
+UF = 1.0  # unit force
 
-L = 2*26.667*UL     # block length
-H = 2*6.413*UL      # block height
-dH = 0.018*H        # height reduction at the center of the block
+L = 2 * 26.667 * UL  # block length
+H = 2 * 6.413 * UL  # block height
+dH = 0.018 * H  # height reduction at the center of the block
 
-N_L = 20        # number of elements in block length direction
-N_H = 10        # number of elements in block height direction
+N_L = 20  # number of elements in block length direction
+N_H = 10  # number of elements in block height direction
 
-E = 206.9e3           # Elastic Young's modulus
-nu = 0.29             # Poisson's ratio
-sigma_0 = 0.45e3      # Initial yield stress
+E = 206.9e3  # Elastic Young's modulus
+nu = 0.29  # Poisson's ratio
+sigma_0 = 0.45e3  # Initial yield stress
 sigma_inf = 0.715e3
 h1 = 16.93
-h2 = -0.012924e3      # Hardening/softening tangent modulus
+h2 = -0.012924e3  # Hardening/softening tangent modulus
 
-r_aug = 1e4       # augmentation parameter
+r_aug = 1e4  # augmentation parameter
 
 steps = 200
-#dirichlet_str = '[0,0]'
-#dirichlet_str = '[{0}*{1}*y,{0}*{1}*x]'.format('{0}',0.4/steps)  #  pure 
shearing with 0.4 the shearing angle
-#dirichlet_str = '[{0}*{1}*x*y,0]'.format('{0}',0.4/L/steps)  # symmetric xy 
shearing with 0.2 the shearing angle
-#dirichlet_str = '[0,{0}*{1}*x*y]'.format('{0}',0.4/L/steps)  # symmetric yx 
shearing with 0.2 the shearing angle
-#dirichlet_str = '[{0}*{1}*y,0]'.format('{0}',0.4/steps)  #  simple xy 
shearing with 0.4 the shearing angle
-#dirichlet_str = '[0,{0}*{1}*x]'.format('{0}',0.4/steps)  #  simple yx 
shearing with 0.4 the shearing angle
-dirichlet_str = '[{0}*{1}*x,0]'.format('{0}',10./L/steps)      # x stretching 
with 0.2 the stretching ratio
-#dirichlet_str = '[0,{0}*{1}*y]'.format('{0}',0.1/steps)      # y stretching 
with 0.8 the stretching ratio
-#dirichlet_str = '[np.cos({0}*{1})*x-np.sin({0}*{1})*y-x,'\
+# dirichlet_str = '[0,0]'
+# dirichlet_str = '[{0}*{1}*y,{0}*{1}*x]'.format('{0}',0.4/steps)  #  pure 
shearing with 0.4 the shearing angle
+# dirichlet_str = '[{0}*{1}*x*y,0]'.format('{0}',0.4/L/steps)  # symmetric xy 
shearing with 0.2 the shearing angle
+# dirichlet_str = '[0,{0}*{1}*x*y]'.format('{0}',0.4/L/steps)  # symmetric yx 
shearing with 0.2 the shearing angle
+# dirichlet_str = '[{0}*{1}*y,0]'.format('{0}',0.4/steps)  #  simple xy 
shearing with 0.4 the shearing angle
+# dirichlet_str = '[0,{0}*{1}*x]'.format('{0}',0.4/steps)  #  simple yx 
shearing with 0.4 the shearing angle
+dirichlet_str = "[{0}*{1}*x,0]".format(
+    "{0}", 10.0 / L / steps
+)  # x stretching with 0.2 the stretching ratio
+# dirichlet_str = '[0,{0}*{1}*y]'.format('{0}',0.1/steps)      # y stretching 
with 0.8 the stretching ratio
+# dirichlet_str = '[np.cos({0}*{1})*x-np.sin({0}*{1})*y-x,'\
 #                
'np.sin({0}*{1})*x+np.cos({0}*{1})*y-y]'.format('{0}',np.pi/4/steps)   # 
rotation by pi/4
-#dirichlet_str = '[np.cos({0}*{1})*(1+{0}*{2})*x-np.sin({0}*{1})*y-x,'\
+# dirichlet_str = '[np.cos({0}*{1})*(1+{0}*{2})*x-np.sin({0}*{1})*y-x,'\
 #                
'np.sin({0}*{1})*(1+{0}*{2})*x+np.cos({0}*{1})*y-y]'.format('{0}',np.pi/4/steps,1.2/steps)
   # rotation by pi/4 and stretching (0.2)
-#dirichlet_str = '[np.cos({0}*{1})*(x+{0}*{2}*y)-np.sin({0}*{1})*y-x,'\
+# dirichlet_str = '[np.cos({0}*{1})*(x+{0}*{2}*y)-np.sin({0}*{1})*y-x,'\
 #               
'np.sin({0}*{1})*(x+{0}*{2}*y)+np.cos({0}*{1})*y-y]'.format('{0}',np.pi/4/steps,0.4/steps)
   # rotation by pi/4 and shearing xy
-#dirichlet_str = '[np.cos({0}*{1})*x-np.sin({0}*{1})*(y+{0}*{2}*x)-x,'\
+# dirichlet_str = '[np.cos({0}*{1})*x-np.sin({0}*{1})*(y+{0}*{2}*x)-x,'\
 #                
'np.sin({0}*{1})*x+np.cos({0}*{1})*(y+{0}*{2}*x)-y]'.format('{0}',np.pi/4/steps,0.4/steps)
   # rotation by pi/4 and shearing yx
-#dirichlet_str = 
'[np.cos({0}*{1})*(x+{0}*{2}*y)-np.sin({0}*{1})*(y+{0}*{2}*x)-x,'\
+# dirichlet_str = 
'[np.cos({0}*{1})*(x+{0}*{2}*y)-np.sin({0}*{1})*(y+{0}*{2}*x)-x,'\
 #                
'np.sin({0}*{1})*(x+{0}*{2}*y)+np.cos({0}*{1})*(y+{0}*{2}*x)-y]'.format('{0}',np.pi/4/steps,0.4/steps)
   # rotation by pi/4 and pure shearing
 
-#dirichlet_str = '[{0}*{1}*x,-{0}*{1}/(1+{0}*{1})*y]'.format('{0}',0.1/steps)  
    # isochoric stretching
+# dirichlet_str = '[{0}*{1}*x,-{0}*{1}/(1+{0}*{1})*y]'.format('{0}',0.1/steps) 
     # isochoric stretching
 
-#------------------------------------
-geotrans = 'GT_QK(2,2)'  # geometric transformation
-#geotrans = 'GT_Q2_INCOMPLETE(2)'
+# ------------------------------------
+geotrans = "GT_QK(2,2)"  # geometric transformation
+# geotrans = 'GT_Q2_INCOMPLETE(2)'
 
-disp_fem_order = 2   # displacements finite element order
+disp_fem_order = 2  # displacements finite element order
 press_fem_order = 1  # pressure finite element order
-mult_fem_order = 2   # plastic multiplier finite element order
+mult_fem_order = 2  # plastic multiplier finite element order
 
-#integration_degree = 3 # 4 gauss points per quad
-integration_degree = 5 # 9 gauss points per quad
-#integration_degree = 7 # 16 gauss points per quad
-#integration_degree = 9 # 25 gauss points per quad
+# integration_degree = 3 # 4 gauss points per quad
+integration_degree = 5  # 9 gauss points per quad
+# integration_degree = 7 # 16 gauss points per quad
+# integration_degree = 9 # 25 gauss points per quad
 
 integration_degree_press = 5
 
 symmetric = True
 rigid_grip = False
 
-#------------------------------------
+# ------------------------------------
 
-resultspath = './results_finite_strain_plasticity_deSouzaNeto'
+resultspath = "./results_finite_strain_plasticity_deSouzaNeto"
 if not os.path.exists(resultspath):
     os.makedirs(resultspath)
 
 
 # auxiliary parameters
-K = E/(3.*(1.-2.*nu))  # Bulk modulus
-mu = E/(2.*(1.+nu))    # Shear modulus
+K = E / (3.0 * (1.0 - 2.0 * nu))  # Bulk modulus
+mu = E / (2.0 * (1.0 + nu))  # Shear modulus
 
 # auxiliary constants
 L_BOUNDARY = 3
@@ -109,27 +111,30 @@ T_BOUNDARY = 6
 DIR_BOUNDARY = 7
 OUT_BOUNDARY = 8
 
-xmin = -L/2
-ymin = -H/2
+xmin = -L / 2
+ymin = -H / 2
 dx = L
 dy = H
 if symmetric:
-   xmin = 0.
-   ymin = 0.
-   dx = L/2
-   dy = H/2
-mesh = gf.Mesh('import', 'structured',
-               'GT="%s";ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]'
-               % (geotrans, xmin, ymin, dx, dy, N_L, N_H))
+    xmin = 0.0
+    ymin = 0.0
+    dx = L / 2
+    dy = H / 2
+mesh = gf.Mesh(
+    "import",
+    "structured",
+    'GT="%s";ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]'
+    % (geotrans, xmin, ymin, dx, dy, N_L, N_H),
+)
 
 N = mesh.dim()
 
 outer_faces = mesh.outer_faces()
 outer_normals = mesh.normal_of_faces(outer_faces)
-left_boundary   = outer_faces[:,np.nonzero(outer_normals[0] < -0.95)[0]]
-right_boundary  = outer_faces[:,np.nonzero(outer_normals[0] >  0.95)[0]]
-bottom_boundary = outer_faces[:,np.nonzero(outer_normals[1] < -0.95)[0]]
-top_boundary    = outer_faces[:,np.nonzero(outer_normals[1] >  0.95)[0]]
+left_boundary = outer_faces[:, np.nonzero(outer_normals[0] < -0.95)[0]]
+right_boundary = outer_faces[:, np.nonzero(outer_normals[0] > 0.95)[0]]
+bottom_boundary = outer_faces[:, np.nonzero(outer_normals[1] < -0.95)[0]]
+top_boundary = outer_faces[:, np.nonzero(outer_normals[1] > 0.95)[0]]
 mesh.set_region(L_BOUNDARY, left_boundary)
 mesh.set_region(R_BOUNDARY, right_boundary)
 mesh.set_region(B_BOUNDARY, bottom_boundary)
@@ -141,45 +146,44 @@ mesh.set_region(DIR_BOUNDARY, right_boundary)
 mesh.set_region(OUT_BOUNDARY, outer_faces)
 
 if dH > 0:
-   pts = mesh.pts()
-   dy = 0.2   # fine element size ratio w.r.t. uniform mesh size
-   y0 = 0.04  # ratio of the finer meshed area w.r.t. the total length
-   x0 = y0/dy
-   b2 = (1-dy)/(x0-1)**2
-   b1 = dy - 2*b2*x0
-   b0 = 1 - b1 -b2
-   for i in range(pts.shape[1]):
-      x = pts[0,i]
-      y = pts[1,i]
-      t = 2*abs(x)/L
-      if t < x0:
-        x *= dy;
-      else:
-        x = (b0 + b1*t + b2*t**2) * np.sign(x)*L/2
-      pts[0,i] = x
-      pts[1,i] -= (y*dH)/(2*H) * (1 + np.cos(2.*np.pi*x/L))
-   mesh.set_pts(pts)
-
-mesh.export_to_vtk('%s/mesh.vtk' % resultspath)
+    pts = mesh.pts()
+    dy = 0.2  # fine element size ratio w.r.t. uniform mesh size
+    y0 = 0.04  # ratio of the finer meshed area w.r.t. the total length
+    x0 = y0 / dy
+    b2 = (1 - dy) / (x0 - 1) ** 2
+    b1 = dy - 2 * b2 * x0
+    b0 = 1 - b1 - b2
+    for i in range(pts.shape[1]):
+        x = pts[0, i]
+        y = pts[1, i]
+        t = 2 * abs(x) / L
+        if t < x0:
+            x *= dy
+        else:
+            x = (b0 + b1 * t + b2 * t ** 2) * np.sign(x) * L / 2
+        pts[0, i] = x
+        pts[1, i] -= (y * dH) / (2 * H) * (1 + np.cos(2.0 * np.pi * x / L))
+    mesh.set_pts(pts)
+
+mesh.export_to_vtk("%s/mesh.vtk" % resultspath)
 
 # FEM
 mf1 = gf.MeshFem(mesh, 1)
 mfN = gf.MeshFem(mesh, N)
-#if disp_fem_order == 2:
+# if disp_fem_order == 2:
 #   mf1.set_fem(gf.Fem('FEM_Q2_INCOMPLETE(2)'))
 #   mfN.set_fem(gf.Fem('FEM_Q2_INCOMPLETE(2)'))
-#else:
+# else:
 mf1.set_classical_fem(disp_fem_order)
 mfN.set_classical_fem(disp_fem_order)
 
 if symmetric:
-   xdofsL = mfN.basic_dof_on_region(L_BOUNDARY)[0::N]
-   ydofsB = mfN.basic_dof_on_region(B_BOUNDARY)[1::N]
-   kept_dofs = np.setdiff1d(np.arange(mfN.nb_basic_dof()),
-                            np.union1d(xdofsL,ydofsB))
-   mfu = gf.MeshFem('partial', mfN, kept_dofs)
+    xdofsL = mfN.basic_dof_on_region(L_BOUNDARY)[0::N]
+    ydofsB = mfN.basic_dof_on_region(B_BOUNDARY)[1::N]
+    kept_dofs = np.setdiff1d(np.arange(mfN.nb_basic_dof()), np.union1d(xdofsL, 
ydofsB))
+    mfu = gf.MeshFem("partial", mfN, kept_dofs)
 else:
-   mfu = mfN
+    mfu = mfN
 
 mfp = gf.MeshFem(mesh, 1)
 mfp.set_classical_fem(press_fem_order)
@@ -198,121 +202,241 @@ mimpress = gf.MeshIm(mesh, integration_degree_press)
 
 
 # Model
-md = gf.Model('real')
+md = gf.Model("real")
 
-md.add_fem_variable('u', mfu)        # displacements
-md.add_fem_variable('p', mfp)        # pressure
-md.add_fem_variable("ksi", mfksi)    # plastic multiplier for the current step
+md.add_fem_variable("u", mfu)  # displacements
+md.add_fem_variable("p", mfp)  # pressure
+md.add_fem_variable("ksi", mfksi)  # plastic multiplier for the current step
 
-md.add_im_data("gamma0", mimd1)      # accumulated plastic strain at previous 
time step
-md.add_im_data('invCp0', mimd4)      # Components 11, 22, 33, 12, 13, 23 of 
the plastic part
-md.set_variable('invCp0',            # of the inverse right Cauchy Green 
tensor at the
-                np.tile([1,1,1,0],   # previous step.
-                mimd4.nbpts()))      #
+md.add_im_data("gamma0", mimd1)  # accumulated plastic strain at previous time 
step
+md.add_im_data("invCp0", mimd4)  # Components 11, 22, 33, 12, 13, 23 of the 
plastic part
+md.set_variable(
+    "invCp0",  # of the inverse right Cauchy Green tensor at the
+    np.tile([1, 1, 1, 0], mimd4.nbpts()),  # previous step.
+)  #
 
 if symmetric:
-   if rigid_grip:
-      md.add_fem_data('dirichlet_data', mfN);
-      ibdir = md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfN, 
R_BOUNDARY, 'dirichlet_data')
-   else:
-      dirichlet_str = 
dirichlet_str[dirichlet_str.find('[')+1:dirichlet_str.find(',')]
-      md.add_fem_data('dirichlet_data', mf1);
-      ibdir = md.add_normal_Dirichlet_condition_with_multipliers(mim, 'u', 
mf1, R_BOUNDARY, 'dirichlet_data')
+    if rigid_grip:
+        md.add_fem_data("dirichlet_data", mfN)
+        ibdir = md.add_Dirichlet_condition_with_multipliers(
+            mim, "u", mfN, R_BOUNDARY, "dirichlet_data"
+        )
+    else:
+        dirichlet_str = dirichlet_str[
+            dirichlet_str.find("[") + 1 : dirichlet_str.find(",")
+        ]
+        md.add_fem_data("dirichlet_data", mf1)
+        ibdir = md.add_normal_Dirichlet_condition_with_multipliers(
+            mim, "u", mf1, R_BOUNDARY, "dirichlet_data"
+        )
 else:
-   if not rigid_grip:
-      print('Not rigid grip option is ignored in non-symmetric model')
-   md.add_fem_data('dirichlet_data', mfN);
-   ibdir = md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfN, 
DIR_BOUNDARY, 'dirichlet_data')
-
-
-gf.asm_define_function("hardening_law", 1,
-                       "({sigma0}+{dsigma}*(1-exp(-{delta}*t))+{H}*t)"\
-                       .format(sigma0=np.sqrt(2./3.)*sigma_0,
-                               dsigma=np.sqrt(2./3.)*(sigma_inf-sigma_0),
-                               delta=np.sqrt(2./3.)*h1,
-                               H=2./3.*h2));
+    if not rigid_grip:
+        print("Not rigid grip option is ignored in non-symmetric model")
+    md.add_fem_data("dirichlet_data", mfN)
+    ibdir = md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfN, DIR_BOUNDARY, "dirichlet_data"
+    )
+
+
+gf.asm_define_function(
+    "hardening_law",
+    1,
+    "({sigma0}+{dsigma}*(1-exp(-{delta}*t))+{H}*t)".format(
+        sigma0=np.sqrt(2.0 / 3.0) * sigma_0,
+        dsigma=np.sqrt(2.0 / 3.0) * (sigma_inf - sigma_0),
+        delta=np.sqrt(2.0 / 3.0) * h1,
+        H=2.0 / 3.0 * h2,
+    ),
+)
 
 _K_ = "{0:.17g}".format(K)  # Bulk modulus
-_mu_ = "{0:.17g}".format(mu)             # Shear modulus
-ibplast = \
-md.add_finite_strain_elastoplasticity_brick\
-  (mim, "Simo_Miehe", "displacement_and_plastic_multiplier_and_pressure",
-   "u", "ksi", "p", "gamma0", "invCp0",
-   _K_, _mu_, "hardening_law")
-
-print('Displacement dofs: %i' % mfu.nbdof())
-print('Total model dofs: %i' % md.nbdof())
+_mu_ = "{0:.17g}".format(mu)  # Shear modulus
+ibplast = md.add_finite_strain_elastoplasticity_brick(
+    mim,
+    "Simo_Miehe",
+    "displacement_and_plastic_multiplier_and_pressure",
+    "u",
+    "ksi",
+    "p",
+    "gamma0",
+    "invCp0",
+    _K_,
+    _mu_,
+    "hardening_law",
+)
+
+print("Displacement dofs: %i" % mfu.nbdof())
+print("Total model dofs: %i" % md.nbdof())
 
 dirichlet_multname = md.mult_varname_Dirichlet(ibdir)
 mf_dirichlet_mult = md.mesh_fem_of_variable(dirichlet_multname)
 mass_mat = gf.asm_mass_matrix(mim, mfout)
 
-shutil.copyfile(os.path.abspath(sys.argv[0]),resultspath+'/'+sys.argv[0])
+shutil.copyfile(os.path.abspath(sys.argv[0]), resultspath + "/" + sys.argv[0])
 starttime_overall = time.clock()
-with open('%s/finite_strain_plasticity_forces.dat' % resultspath, 'w') as f:
-   for step in range(0,steps+1):
-      print('Solving step: %i' % step)
-
-      backup = md.from_variables()
-      dirichlet_data = 
mf_dirichlet_mult.eval(dirichlet_str.format(step),globals(),locals())
-      md.set_variable('dirichlet_data', dirichlet_data)
-
-      starttime = time.clock()
-      iters = 41
-      nit = \
-      md.solve('noisy', 'lsolver', 'mumps', 'max_iter', iters, 'max_res', 
1e-10, #)[0]
-               'lsearch', 'simplest', 'alpha max ratio', 1.5, 'alpha min', 
0.05, 'alpha mult', 0.6)[0]
-      if nit > 40:
-        print('STEP %i HAS NOT CONVERGED, TRYING SUBSTEPPING' % (step))
-        md.to_variables(backup)
-        for substep in range(1,5):
-          dirichlet_data = 
mf_dirichlet_mult.eval(dirichlet_str.format(step-1.+substep/4.),globals(),locals())
-          md.set_variable('dirichlet_data', dirichlet_data)
-          md.solve('noisy', 'lsolver', 'mumps', 'max_iter', iters, 'max_res', 
1e-10, #)[0]
-                   'lsearch', 'simplest', 'alpha max ratio', 1.5, 'alpha min', 
0.05, 'alpha mult', 0.6)[0]
-      print('STEP %i COMPLETED IN %f SEC' % (step, time.clock()-starttime))
-
-      VM = md.compute_finite_strain_elastoplasticity_Von_Mises\
-         (mim, mfout, "Simo_Miehe", 
"displacement_and_plastic_multiplier_and_pressure",
-          "u", "ksi", "p", "gamma0", "invCp0", _K_, _mu_, "hardening_law")
-
-      RHS = md.rhs()
-      IU = md.interval_of_variable('u')
-      IP = md.interval_of_variable('p')
-      IKSI = md.interval_of_variable('ksi')
-
-      output = (mfu, md.variable('u'), 'Displacements',
-                mfp, md.variable('p'), 'Pressure',
-                mfksi, md.variable('ksi'), 'dksi',
-                mf_dirichlet_mult, -md.variable(dirichlet_multname), "Reaction 
stresses",
-                mfout, VM, 'Von Mises Stress',
-                mfu, RHS[IU[0]:IU[0]+IU[1]], 'residual u',
-                mfp, RHS[IP[0]:IP[0]+IP[1]], 'residual p',
-                mfksi, RHS[IKSI[0]:IKSI[0]+IKSI[1]], 'residual ksi')
-
-      md.finite_strain_elastoplasticity_next_iter\
-         (mim, "Simo_Miehe", 
"displacement_and_plastic_multiplier_and_pressure",
-          "u", "ksi", "p", "gamma0", "invCp0", _K_, _mu_, "hardening_law")
-
-      GAMMA = gf.asm_generic(mim, 1, "gamma*Test_t", -1,
-                             "gamma", False, mimd1, md.variable("gamma0"),
-                             "t", True, mfout, np.zeros(mfout.nbdof()))
-      GAMMA = np.transpose(gf.linsolve_mumps(mass_mat, GAMMA))
-      output += (mfout, GAMMA, "plastic strain")
-
-      mf1.export_to_vtk('%s/finite_strain_plasticity_%i.vtk' % (resultspath, 
step), 'ascii', *output)
-
-      DIRMULT = -md.variable(dirichlet_multname)
-      DIRMULT = np.reshape(DIRMULT,[1,DIRMULT.size])
-      if symmetric and not rigid_grip:
-         dfR = gf.asm_boundary_source(R_BOUNDARY, mim, mf1, mf_dirichlet_mult, 
DIRMULT)
-         f.write(('step=%i fR=(%f,0) sR=(%f,0)\n') %
-                 (step, dfR.sum(), dfR.sum()/H))
-      else:
-         dfR = gf.asm_boundary_source(R_BOUNDARY, mim, mfN, mf_dirichlet_mult, 
DIRMULT)
-         f.write(('step=%i fR=(%f,%f) sR=(%f,%f)\n') %
-                 (step, dfR[0::N].sum(), dfR[1::N].sum(),
-                        dfR[0::N].sum()/H, dfR[1::N].sum()/H))
-      f.flush()
-
-print('OVERALL SOLUTION TIME IS %f SEC' % (time.clock()-starttime_overall))
+with open("%s/finite_strain_plasticity_forces.dat" % resultspath, "w") as f:
+    for step in range(0, steps + 1):
+        print("Solving step: %i" % step)
+
+        backup = md.from_variables()
+        dirichlet_data = mf_dirichlet_mult.eval(
+            dirichlet_str.format(step), globals(), locals()
+        )
+        md.set_variable("dirichlet_data", dirichlet_data)
+
+        starttime = time.clock()
+        iters = 41
+        nit = md.solve(
+            "noisy",
+            "lsolver",
+            "mumps",
+            "max_iter",
+            iters,
+            "max_res",
+            1e-10,  # )[0]
+            "lsearch",
+            "simplest",
+            "alpha max ratio",
+            1.5,
+            "alpha min",
+            0.05,
+            "alpha mult",
+            0.6,
+        )[0]
+        if nit > 40:
+            print("STEP %i HAS NOT CONVERGED, TRYING SUBSTEPPING" % (step))
+            md.to_variables(backup)
+            for substep in range(1, 5):
+                dirichlet_data = mf_dirichlet_mult.eval(
+                    dirichlet_str.format(step - 1.0 + substep / 4.0),
+                    globals(),
+                    locals(),
+                )
+                md.set_variable("dirichlet_data", dirichlet_data)
+                md.solve(
+                    "noisy",
+                    "lsolver",
+                    "mumps",
+                    "max_iter",
+                    iters,
+                    "max_res",
+                    1e-10,  # )[0]
+                    "lsearch",
+                    "simplest",
+                    "alpha max ratio",
+                    1.5,
+                    "alpha min",
+                    0.05,
+                    "alpha mult",
+                    0.6,
+                )[0]
+        print("STEP %i COMPLETED IN %f SEC" % (step, time.clock() - starttime))
+
+        VM = md.compute_finite_strain_elastoplasticity_Von_Mises(
+            mim,
+            mfout,
+            "Simo_Miehe",
+            "displacement_and_plastic_multiplier_and_pressure",
+            "u",
+            "ksi",
+            "p",
+            "gamma0",
+            "invCp0",
+            _K_,
+            _mu_,
+            "hardening_law",
+        )
+
+        RHS = md.rhs()
+        IU = md.interval_of_variable("u")
+        IP = md.interval_of_variable("p")
+        IKSI = md.interval_of_variable("ksi")
+
+        output = (
+            mfu,
+            md.variable("u"),
+            "Displacements",
+            mfp,
+            md.variable("p"),
+            "Pressure",
+            mfksi,
+            md.variable("ksi"),
+            "dksi",
+            mf_dirichlet_mult,
+            -md.variable(dirichlet_multname),
+            "Reaction stresses",
+            mfout,
+            VM,
+            "Von Mises Stress",
+            mfu,
+            RHS[IU[0] : IU[0] + IU[1]],
+            "residual u",
+            mfp,
+            RHS[IP[0] : IP[0] + IP[1]],
+            "residual p",
+            mfksi,
+            RHS[IKSI[0] : IKSI[0] + IKSI[1]],
+            "residual ksi",
+        )
+
+        md.finite_strain_elastoplasticity_next_iter(
+            mim,
+            "Simo_Miehe",
+            "displacement_and_plastic_multiplier_and_pressure",
+            "u",
+            "ksi",
+            "p",
+            "gamma0",
+            "invCp0",
+            _K_,
+            _mu_,
+            "hardening_law",
+        )
+
+        GAMMA = gf.asm_generic(
+            mim,
+            1,
+            "gamma*Test_t",
+            -1,
+            "gamma",
+            False,
+            mimd1,
+            md.variable("gamma0"),
+            "t",
+            True,
+            mfout,
+            np.zeros(mfout.nbdof()),
+        )
+        GAMMA = np.transpose(gf.linsolve_mumps(mass_mat, GAMMA))
+        output += (mfout, GAMMA, "plastic strain")
+
+        mf1.export_to_vtk(
+            "%s/finite_strain_plasticity_%i.vtk" % (resultspath, step), 
"ascii", *output
+        )
+
+        DIRMULT = -md.variable(dirichlet_multname)
+        DIRMULT = np.reshape(DIRMULT, [1, DIRMULT.size])
+        if symmetric and not rigid_grip:
+            dfR = gf.asm_boundary_source(
+                R_BOUNDARY, mim, mf1, mf_dirichlet_mult, DIRMULT
+            )
+            f.write(
+                ("step=%i fR=(%f,0) sR=(%f,0)\n") % (step, dfR.sum(), 
dfR.sum() / H)
+            )
+        else:
+            dfR = gf.asm_boundary_source(
+                R_BOUNDARY, mim, mfN, mf_dirichlet_mult, DIRMULT
+            )
+            f.write(
+                ("step=%i fR=(%f,%f) sR=(%f,%f)\n")
+                % (
+                    step,
+                    dfR[0::N].sum(),
+                    dfR[1::N].sum(),
+                    dfR[0::N].sum() / H,
+                    dfR[1::N].sum() / H,
+                )
+            )
+        f.flush()
+
+print("OVERALL SOLUTION TIME IS %f SEC" % (time.clock() - starttime_overall))
diff --git a/interface/tests/python/demo_finite_strain_plasticity_3D.py 
b/interface/tests/python/demo_finite_strain_plasticity_3D.py
index 5febab2..52219b1 100644
--- a/interface/tests/python/demo_finite_strain_plasticity_3D.py
+++ b/interface/tests/python/demo_finite_strain_plasticity_3D.py
@@ -31,57 +31,59 @@ np.set_printoptions(threshold=np.nan)
 gf.util_trace_level(1)
 
 # Input data
-UL = 1.             # unit length
-UF = 1.             # unit force
+UL = 1.0  # unit length
+UF = 1.0  # unit force
 
-L = 2*26.667*UL     # bar length
-H = 2*6.413*UL      # bar diameter
-dH = 0.018*H        # diameter reduction at the center of the bar
+L = 2 * 26.667 * UL  # bar length
+H = 2 * 6.413 * UL  # bar diameter
+dH = 0.018 * H  # diameter reduction at the center of the bar
 
-N_L = 20        # number of elements in length direction
-N_R1 =  6       # number of elements in radial direction (core)
-N_R2 =  3       # number of elements in radial direction (peel)
+N_L = 20  # number of elements in length direction
+N_R1 = 6  # number of elements in radial direction (core)
+N_R2 = 3  # number of elements in radial direction (peel)
 
-E = 206.9e3           # Elastic Young's modulus
-nu = 0.29             # Poisson's ratio
-sigma_0 = 0.45e3      # Initial yield stress
+E = 206.9e3  # Elastic Young's modulus
+nu = 0.29  # Poisson's ratio
+sigma_0 = 0.45e3  # Initial yield stress
 sigma_inf = 0.715e3
 h1 = 16.93
-h2 = 0.12924e3        # Hardening/softening tangent modulus
+h2 = 0.12924e3  # Hardening/softening tangent modulus
 
-r_aug = 1e4       # augmentation parameter
+r_aug = 1e4  # augmentation parameter
 
 steps = 200
-dirichlet_str = '[{0}*{1}*x,0,0]'.format('{0}',14./L/steps)      # x 
stretching with 0.2 the stretching ratio
+dirichlet_str = "[{0}*{1}*x,0,0]".format(
+    "{0}", 14.0 / L / steps
+)  # x stretching with 0.2 the stretching ratio
 
-#------------------------------------
-geotrans2d = 'GT_QK(2,2)'  # geometric transformation
-#geotrans = 'GT_Q2_INCOMPLETE(3)'
+# ------------------------------------
+geotrans2d = "GT_QK(2,2)"  # geometric transformation
+# geotrans = 'GT_Q2_INCOMPLETE(3)'
 
-disp_fem_order = 2   # displacements finite element order
+disp_fem_order = 2  # displacements finite element order
 press_fem_order = 1  # pressure finite element order
-mult_fem_order = 2   # plastic multiplier finite element order
+mult_fem_order = 2  # plastic multiplier finite element order
 
-#integration_degree = 3 # 4 gauss points per quad
-integration_degree = 5 # 9 gauss points per quad
-#integration_degree = 7 # 16 gauss points per quad
-#integration_degree = 9 # 25 gauss points per quad
+# integration_degree = 3 # 4 gauss points per quad
+integration_degree = 5  # 9 gauss points per quad
+# integration_degree = 7 # 16 gauss points per quad
+# integration_degree = 9 # 25 gauss points per quad
 
 integration_degree_press = 5
 
 symmetric = True
 rigid_grip = False
 
-#------------------------------------
+# ------------------------------------
 
-resultspath = './results_finite_strain_plasticity_3D_deSouzaNeto'
+resultspath = "./results_finite_strain_plasticity_3D_deSouzaNeto"
 if not os.path.exists(resultspath):
     os.makedirs(resultspath)
 
 
 # auxiliary parameters
-K = E/(3.*(1.-2.*nu))  # Bulk modulus
-mu = E/(2.*(1.+nu))    # Shear modulus
+K = E / (3.0 * (1.0 - 2.0 * nu))  # Bulk modulus
+mu = E / (2.0 * (1.0 + nu))  # Shear modulus
 
 # auxiliary constants
 L_BOUNDARY = 3
@@ -93,38 +95,41 @@ OUT_BOUNDARY = 8
 
 symmetries = 0
 if symmetric:
-   symmetries = 2
-mesh2d = gf.Mesh('import', 'structured_ball',
-                 'GT="%s";ORG=[0,0];SIZES=[%f];NSUBDIV=[%i,%i];SYMMETRIES=%i'
-                 % (geotrans2d, H/2., N_R1, N_R2, symmetries))
-mesh = gf.Mesh('prismatic', mesh2d, N_L, disp_fem_order)
+    symmetries = 2
+mesh2d = gf.Mesh(
+    "import",
+    "structured_ball",
+    'GT="%s";ORG=[0,0];SIZES=[%f];NSUBDIV=[%i,%i];SYMMETRIES=%i'
+    % (geotrans2d, H / 2.0, N_R1, N_R2, symmetries),
+)
+mesh = gf.Mesh("prismatic", mesh2d, N_L, disp_fem_order)
 print(mesh.dim())
 
-trsf = np.zeros([3,3])
+trsf = np.zeros([3, 3])
 if symmetric:
-   trsf[0,2] = L/2.
+    trsf[0, 2] = L / 2.0
 else:
-   trsf[0,2] = L
-trsf[1,1] = 1
-trsf[2,0] = -1
+    trsf[0, 2] = L
+trsf[1, 1] = 1
+trsf[2, 0] = -1
 mesh.transform(trsf)
 if not symmetric:
-  mesh.translate([-L/2.,0,0.])
+    mesh.translate([-L / 2.0, 0, 0.0])
 
 N = mesh.dim()
 
 outer_faces = mesh.outer_faces()
 outer_normals = mesh.normal_of_faces(outer_faces)
-left_boundary   = outer_faces[:,np.nonzero(outer_normals[0] < -0.95)[0]]
-right_boundary  = outer_faces[:,np.nonzero(outer_normals[0] >  0.95)[0]]
+left_boundary = outer_faces[:, np.nonzero(outer_normals[0] < -0.95)[0]]
+right_boundary = outer_faces[:, np.nonzero(outer_normals[0] > 0.95)[0]]
 mesh.set_region(L_BOUNDARY, left_boundary)
 mesh.set_region(R_BOUNDARY, right_boundary)
 
 
 pids = mesh.pid_in_faces(outer_faces)
 pts = mesh.pts(pids)
-pids_symmetry_xy = pids[np.abs(pts[2,:]) < 1e-8]
-pids_symmetry_xz = pids[np.abs(pts[1,:]) < 1e-8]
+pids_symmetry_xy = pids[np.abs(pts[2, :]) < 1e-8]
+pids_symmetry_xz = pids[np.abs(pts[1, :]) < 1e-8]
 mesh.set_region(XY_SYMMETRY, mesh.faces_from_pid(pids_symmetry_xy))
 mesh.set_region(XZ_SYMMETRY, mesh.faces_from_pid(pids_symmetry_xz))
 
@@ -134,50 +139,50 @@ mesh.set_region(DIR_BOUNDARY, right_boundary)
 mesh.set_region(OUT_BOUNDARY, outer_faces)
 
 if dH > 0:
-   pts = mesh.pts()
-   dr = 0.2   # fine element size ratio w.r.t. uniform mesh size
-   r0 = 0.04  # ratio of the finer meshed area w.r.t. the total length
-   x0 = r0/dr
-   b2 = (1-dr)/(x0-1)**2
-   b1 = dr - 2*b2*x0
-   b0 = 1 - b1 -b2
-   for i in range(pts.shape[1]):
-      x = pts[0,i]
-      y = pts[1,i]
-      z = pts[2,i]
-      r = np.sqrt(y**2+z**2)
-      t = 2*abs(x)/L
-      if t < x0:
-        x *= dr;
-      else:
-        x = (b0 + b1*t + b2*t**2) * np.sign(x)*L/2
-      pts[0,i] = x
-      pts[1,i] -= (y*dH)/(2*H) * (1 + np.cos(2.*np.pi*x/L))
-      pts[2,i] -= (z*dH)/(2*H) * (1 + np.cos(2.*np.pi*x/L))
-   mesh.set_pts(pts)
-
-mesh.export_to_vtk('%s/mesh.vtk' % resultspath)
+    pts = mesh.pts()
+    dr = 0.2  # fine element size ratio w.r.t. uniform mesh size
+    r0 = 0.04  # ratio of the finer meshed area w.r.t. the total length
+    x0 = r0 / dr
+    b2 = (1 - dr) / (x0 - 1) ** 2
+    b1 = dr - 2 * b2 * x0
+    b0 = 1 - b1 - b2
+    for i in range(pts.shape[1]):
+        x = pts[0, i]
+        y = pts[1, i]
+        z = pts[2, i]
+        r = np.sqrt(y ** 2 + z ** 2)
+        t = 2 * abs(x) / L
+        if t < x0:
+            x *= dr
+        else:
+            x = (b0 + b1 * t + b2 * t ** 2) * np.sign(x) * L / 2
+        pts[0, i] = x
+        pts[1, i] -= (y * dH) / (2 * H) * (1 + np.cos(2.0 * np.pi * x / L))
+        pts[2, i] -= (z * dH) / (2 * H) * (1 + np.cos(2.0 * np.pi * x / L))
+    mesh.set_pts(pts)
+
+mesh.export_to_vtk("%s/mesh.vtk" % resultspath)
 
 # FEM
 mf1 = gf.MeshFem(mesh, 1)
 mfN = gf.MeshFem(mesh, N)
-#if disp_fem_order == 2:
+# if disp_fem_order == 2:
 #   mf1.set_fem(gf.Fem('FEM_Q2_INCOMPLETE(3)'))
 #   mfN.set_fem(gf.Fem('FEM_Q2_INCOMPLETE(3)'))
-#else:
+# else:
 mf1.set_classical_fem(disp_fem_order)
 mfN.set_classical_fem(disp_fem_order)
 
 if symmetric:
-   xdofsL = mfN.basic_dof_on_region(L_BOUNDARY)[0::N]
-   ydofsXZ = mfN.basic_dof_on_region(XZ_SYMMETRY)[1::N]
-   zdofsXY = mfN.basic_dof_on_region(XY_SYMMETRY)[2::N]
-   kept_dofs = np.setdiff1d(np.arange(mfN.nb_basic_dof()),
-                            np.union1d(xdofsL,
-                                       np.union1d(ydofsXZ,zdofsXY)))
-   mfu = gf.MeshFem('partial', mfN, kept_dofs)
+    xdofsL = mfN.basic_dof_on_region(L_BOUNDARY)[0::N]
+    ydofsXZ = mfN.basic_dof_on_region(XZ_SYMMETRY)[1::N]
+    zdofsXY = mfN.basic_dof_on_region(XY_SYMMETRY)[2::N]
+    kept_dofs = np.setdiff1d(
+        np.arange(mfN.nb_basic_dof()), np.union1d(xdofsL, np.union1d(ydofsXZ, 
zdofsXY))
+    )
+    mfu = gf.MeshFem("partial", mfN, kept_dofs)
 else:
-   mfu = mfN
+    mfu = mfN
 
 mfp = gf.MeshFem(mesh, 1)
 mfp.set_classical_fem(press_fem_order)
@@ -196,121 +201,241 @@ mimpress = gf.MeshIm(mesh, integration_degree_press)
 
 
 # Model
-md = gf.Model('real')
+md = gf.Model("real")
 
-md.add_fem_variable('u', mfu)        # displacements
-md.add_fem_variable('p', mfp)        # pressure
-md.add_fem_variable("ksi", mfksi)    # plastic multiplier for the current step
+md.add_fem_variable("u", mfu)  # displacements
+md.add_fem_variable("p", mfp)  # pressure
+md.add_fem_variable("ksi", mfksi)  # plastic multiplier for the current step
 
-md.add_im_data("gamma0", mimd1)        # accumulated plastic strain at 
previous time step
-md.add_im_data('invCp0', mimd6)        # Components 11, 22, 33, 12, 13, 23 of 
the plastic part
-md.set_variable('invCp0',              # of the inverse right Cauchy Green 
tensor at the
-                np.tile([1,1,1,0,0,0], # previous step.
-                mimd6.nbpts()))        #
+md.add_im_data("gamma0", mimd1)  # accumulated plastic strain at previous time 
step
+md.add_im_data("invCp0", mimd6)  # Components 11, 22, 33, 12, 13, 23 of the 
plastic part
+md.set_variable(
+    "invCp0",  # of the inverse right Cauchy Green tensor at the
+    np.tile([1, 1, 1, 0, 0, 0], mimd6.nbpts()),  # previous step.
+)  #
 
 if symmetric:
-   if rigid_grip:
-      md.add_fem_data('dirichlet_data', mfN);
-      ibdir = md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfN, 
R_BOUNDARY, 'dirichlet_data')
-   else:
-      dirichlet_str = 
dirichlet_str[dirichlet_str.find('[')+1:dirichlet_str.find(',')]
-      md.add_fem_data('dirichlet_data', mf1);
-      ibdir = md.add_normal_Dirichlet_condition_with_multipliers(mim, 'u', 
mf1, R_BOUNDARY, 'dirichlet_data')
+    if rigid_grip:
+        md.add_fem_data("dirichlet_data", mfN)
+        ibdir = md.add_Dirichlet_condition_with_multipliers(
+            mim, "u", mfN, R_BOUNDARY, "dirichlet_data"
+        )
+    else:
+        dirichlet_str = dirichlet_str[
+            dirichlet_str.find("[") + 1 : dirichlet_str.find(",")
+        ]
+        md.add_fem_data("dirichlet_data", mf1)
+        ibdir = md.add_normal_Dirichlet_condition_with_multipliers(
+            mim, "u", mf1, R_BOUNDARY, "dirichlet_data"
+        )
 else:
-   if not rigid_grip:
-      print('Not rigid grip option is ignored in non-symmetric model')
-   md.add_fem_data('dirichlet_data', mfN);
-   ibdir = md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfN, 
DIR_BOUNDARY, 'dirichlet_data')
-
-
-gf.asm_define_function("hardening_law", 1,
-                       "({sigma0}+{dsigma}*(1-exp(-{delta}*t))+{H}*t)"\
-                       .format(sigma0=np.sqrt(2./3.)*sigma_0,
-                               dsigma=np.sqrt(2./3.)*(sigma_inf-sigma_0),
-                               delta=np.sqrt(2./3.)*h1,
-                               H=2./3.*h2));
+    if not rigid_grip:
+        print("Not rigid grip option is ignored in non-symmetric model")
+    md.add_fem_data("dirichlet_data", mfN)
+    ibdir = md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfN, DIR_BOUNDARY, "dirichlet_data"
+    )
+
+
+gf.asm_define_function(
+    "hardening_law",
+    1,
+    "({sigma0}+{dsigma}*(1-exp(-{delta}*t))+{H}*t)".format(
+        sigma0=np.sqrt(2.0 / 3.0) * sigma_0,
+        dsigma=np.sqrt(2.0 / 3.0) * (sigma_inf - sigma_0),
+        delta=np.sqrt(2.0 / 3.0) * h1,
+        H=2.0 / 3.0 * h2,
+    ),
+)
 
 _K_ = "{0:.17g}".format(K)  # Bulk modulus
-_mu_ = "{0:.17g}".format(mu)             # Shear modulus
-ibplast = \
-md.add_finite_strain_elastoplasticity_brick\
-  (mim, "Simo_Miehe", "displacement_and_plastic_multiplier_and_pressure",
-   "u", "ksi", "p", "gamma0", "invCp0",
-   _K_, _mu_, "hardening_law")
-
-print('Displacement dofs: %i' % mfu.nbdof())
-print('Total model dofs: %i' % md.nbdof())
+_mu_ = "{0:.17g}".format(mu)  # Shear modulus
+ibplast = md.add_finite_strain_elastoplasticity_brick(
+    mim,
+    "Simo_Miehe",
+    "displacement_and_plastic_multiplier_and_pressure",
+    "u",
+    "ksi",
+    "p",
+    "gamma0",
+    "invCp0",
+    _K_,
+    _mu_,
+    "hardening_law",
+)
+
+print("Displacement dofs: %i" % mfu.nbdof())
+print("Total model dofs: %i" % md.nbdof())
 
 dirichlet_multname = md.mult_varname_Dirichlet(ibdir)
 mf_dirichlet_mult = md.mesh_fem_of_variable(dirichlet_multname)
 mass_mat = gf.asm_mass_matrix(mim, mfout)
 
-shutil.copyfile(os.path.abspath(sys.argv[0]),resultspath+'/'+sys.argv[0])
+shutil.copyfile(os.path.abspath(sys.argv[0]), resultspath + "/" + sys.argv[0])
 starttime_overall = time.clock()
-with open('%s/finite_strain_plasticity_forces.dat' % resultspath, 'w') as f:
-   for step in range(0,steps+1):
-      print('Solving step: %i' % step)
-
-      backup = md.from_variables()
-      dirichlet_data = 
mf_dirichlet_mult.eval(dirichlet_str.format(step),globals(),locals())
-      md.set_variable('dirichlet_data', dirichlet_data)
-
-      starttime = time.clock()
-      iters = 41
-      nit = \
-      md.solve('noisy', 'lsolver', 'mumps', 'max_iter', iters, 'max_res', 
1e-10, #)[0]
-               'lsearch', 'simplest', 'alpha max ratio', 1.5, 'alpha min', 
0.05, 'alpha mult', 0.6)[0]
-      if nit > 40:
-        print('STEP %i HAS NOT CONVERGED, TRYING SUBSTEPPING' % (step))
-        md.to_variables(backup)
-        for substep in range(1,5):
-          dirichlet_data = 
mf_dirichlet_mult.eval(dirichlet_str.format(step-1.+substep/4.),globals(),locals())
-          md.set_variable('dirichlet_data', dirichlet_data)
-          md.solve('noisy', 'lsolver', 'mumps', 'max_iter', iters, 'max_res', 
1e-10, #)[0]
-                   'lsearch', 'simplest', 'alpha max ratio', 1.5, 'alpha min', 
0.05, 'alpha mult', 0.6)[0]
-      print('STEP %i COMPLETED IN %f SEC' % (step, time.clock()-starttime))
-
-      VM = md.compute_finite_strain_elastoplasticity_Von_Mises\
-         (mim, mfout, "Simo_Miehe", 
"displacement_and_plastic_multiplier_and_pressure",
-          "u", "ksi", "p", "gamma0", "invCp0", _K_, _mu_, "hardening_law")
-
-      RHS = md.rhs()
-      IU = md.interval_of_variable('u')
-      IP = md.interval_of_variable('p')
-      IKSI = md.interval_of_variable('ksi')
-
-      output = (mfu, md.variable('u'), 'Displacements',
-                mfp, md.variable('p'), 'Pressure',
-                mfksi, md.variable('ksi'), 'dksi',
-                mf_dirichlet_mult, -md.variable(dirichlet_multname), "Reaction 
stresses",
-                mfout, VM, 'Von Mises Stress',
-                mfu, RHS[IU[0]:IU[0]+IU[1]], 'residual u',
-                mfp, RHS[IP[0]:IP[0]+IP[1]], 'residual p',
-                mfksi, RHS[IKSI[0]:IKSI[0]+IKSI[1]], 'residual ksi')
-
-      md.finite_strain_elastoplasticity_next_iter\
-         (mim, "Simo_Miehe", 
"displacement_and_plastic_multiplier_and_pressure",
-          "u", "ksi", "p", "gamma0", "invCp0", _K_, _mu_, "hardening_law")
-
-      GAMMA = gf.asm_generic(mim, 1, "gamma*Test_t", -1,
-                             "gamma", False, mimd1, md.variable("gamma0"),
-                             "t", True, mfout, np.zeros(mfout.nbdof()))
-      GAMMA = np.transpose(gf.linsolve_mumps(mass_mat, GAMMA))
-      output += (mfout, GAMMA, "plastic strain")
-
-      mf1.export_to_vtk('%s/finite_strain_plasticity_%i.vtk' % (resultspath, 
step), 'ascii', *output)
-
-      DIRMULT = -md.variable(dirichlet_multname)
-      DIRMULT = np.reshape(DIRMULT,[1,DIRMULT.size])
-      if symmetric and not rigid_grip:
-         dfR = gf.asm_boundary_source(R_BOUNDARY, mim, mf1, mf_dirichlet_mult, 
DIRMULT)
-         f.write(('step=%i fR=(%f,0) sR=(%f,0)\n') %
-                 (step, dfR.sum(), dfR.sum()/H))
-      else:
-         dfR = gf.asm_boundary_source(R_BOUNDARY, mim, mfN, mf_dirichlet_mult, 
DIRMULT)
-         f.write(('step=%i fR=(%f,%f) sR=(%f,%f)\n') %
-                 (step, dfR[0::N].sum(), dfR[1::N].sum(),
-                        dfR[0::N].sum()/H, dfR[1::N].sum()/H))
-      f.flush()
-
-print('OVERALL SOLUTION TIME IS %f SEC' % (time.clock()-starttime_overall))
+with open("%s/finite_strain_plasticity_forces.dat" % resultspath, "w") as f:
+    for step in range(0, steps + 1):
+        print("Solving step: %i" % step)
+
+        backup = md.from_variables()
+        dirichlet_data = mf_dirichlet_mult.eval(
+            dirichlet_str.format(step), globals(), locals()
+        )
+        md.set_variable("dirichlet_data", dirichlet_data)
+
+        starttime = time.clock()
+        iters = 41
+        nit = md.solve(
+            "noisy",
+            "lsolver",
+            "mumps",
+            "max_iter",
+            iters,
+            "max_res",
+            1e-10,  # )[0]
+            "lsearch",
+            "simplest",
+            "alpha max ratio",
+            1.5,
+            "alpha min",
+            0.05,
+            "alpha mult",
+            0.6,
+        )[0]
+        if nit > 40:
+            print("STEP %i HAS NOT CONVERGED, TRYING SUBSTEPPING" % (step))
+            md.to_variables(backup)
+            for substep in range(1, 5):
+                dirichlet_data = mf_dirichlet_mult.eval(
+                    dirichlet_str.format(step - 1.0 + substep / 4.0),
+                    globals(),
+                    locals(),
+                )
+                md.set_variable("dirichlet_data", dirichlet_data)
+                md.solve(
+                    "noisy",
+                    "lsolver",
+                    "mumps",
+                    "max_iter",
+                    iters,
+                    "max_res",
+                    1e-10,  # )[0]
+                    "lsearch",
+                    "simplest",
+                    "alpha max ratio",
+                    1.5,
+                    "alpha min",
+                    0.05,
+                    "alpha mult",
+                    0.6,
+                )[0]
+        print("STEP %i COMPLETED IN %f SEC" % (step, time.clock() - starttime))
+
+        VM = md.compute_finite_strain_elastoplasticity_Von_Mises(
+            mim,
+            mfout,
+            "Simo_Miehe",
+            "displacement_and_plastic_multiplier_and_pressure",
+            "u",
+            "ksi",
+            "p",
+            "gamma0",
+            "invCp0",
+            _K_,
+            _mu_,
+            "hardening_law",
+        )
+
+        RHS = md.rhs()
+        IU = md.interval_of_variable("u")
+        IP = md.interval_of_variable("p")
+        IKSI = md.interval_of_variable("ksi")
+
+        output = (
+            mfu,
+            md.variable("u"),
+            "Displacements",
+            mfp,
+            md.variable("p"),
+            "Pressure",
+            mfksi,
+            md.variable("ksi"),
+            "dksi",
+            mf_dirichlet_mult,
+            -md.variable(dirichlet_multname),
+            "Reaction stresses",
+            mfout,
+            VM,
+            "Von Mises Stress",
+            mfu,
+            RHS[IU[0] : IU[0] + IU[1]],
+            "residual u",
+            mfp,
+            RHS[IP[0] : IP[0] + IP[1]],
+            "residual p",
+            mfksi,
+            RHS[IKSI[0] : IKSI[0] + IKSI[1]],
+            "residual ksi",
+        )
+
+        md.finite_strain_elastoplasticity_next_iter(
+            mim,
+            "Simo_Miehe",
+            "displacement_and_plastic_multiplier_and_pressure",
+            "u",
+            "ksi",
+            "p",
+            "gamma0",
+            "invCp0",
+            _K_,
+            _mu_,
+            "hardening_law",
+        )
+
+        GAMMA = gf.asm_generic(
+            mim,
+            1,
+            "gamma*Test_t",
+            -1,
+            "gamma",
+            False,
+            mimd1,
+            md.variable("gamma0"),
+            "t",
+            True,
+            mfout,
+            np.zeros(mfout.nbdof()),
+        )
+        GAMMA = np.transpose(gf.linsolve_mumps(mass_mat, GAMMA))
+        output += (mfout, GAMMA, "plastic strain")
+
+        mf1.export_to_vtk(
+            "%s/finite_strain_plasticity_%i.vtk" % (resultspath, step), 
"ascii", *output
+        )
+
+        DIRMULT = -md.variable(dirichlet_multname)
+        DIRMULT = np.reshape(DIRMULT, [1, DIRMULT.size])
+        if symmetric and not rigid_grip:
+            dfR = gf.asm_boundary_source(
+                R_BOUNDARY, mim, mf1, mf_dirichlet_mult, DIRMULT
+            )
+            f.write(
+                ("step=%i fR=(%f,0) sR=(%f,0)\n") % (step, dfR.sum(), 
dfR.sum() / H)
+            )
+        else:
+            dfR = gf.asm_boundary_source(
+                R_BOUNDARY, mim, mfN, mf_dirichlet_mult, DIRMULT
+            )
+            f.write(
+                ("step=%i fR=(%f,%f) sR=(%f,%f)\n")
+                % (
+                    step,
+                    dfR[0::N].sum(),
+                    dfR[1::N].sum(),
+                    dfR[0::N].sum() / H,
+                    dfR[1::N].sum() / H,
+                )
+            )
+        f.flush()
+
+print("OVERALL SOLUTION TIME IS %f SEC" % (time.clock() - starttime_overall))
diff --git a/interface/tests/python/demo_laplacian.py 
b/interface/tests/python/demo_laplacian.py
index b2da830..42acf0a 100644
--- a/interface/tests/python/demo_laplacian.py
+++ b/interface/tests/python/demo_laplacian.py
@@ -31,32 +31,35 @@ import getfem as gf
 import numpy as np
 
 ## Parameters
-NX = 100                           # Mesh parameter.
+NX = 100  # Mesh parameter.
 Dirichlet_with_multipliers = True  # Dirichlet condition with multipliers
-                                   # or penalization
-dirichlet_coefficient = 1e10       # Penalization coefficient
+# or penalization
+dirichlet_coefficient = 1e10  # Penalization coefficient
 
 # Create a simple cartesian mesh
-m = gf.Mesh('regular_simplices', np.arange(0,1+1./NX,1./NX),
-            np.arange(0,1+1./NX,1./NX))
+m = gf.Mesh(
+    "regular_simplices",
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+)
 
 # Create a MeshFem for u and rhs fields of dimension 1 (i.e. a scalar field)
-mfu   = gf.MeshFem(m, 1)
+mfu = gf.MeshFem(m, 1)
 mfrhs = gf.MeshFem(m, 1)
 # assign the P2 fem to all convexes of the both MeshFem
-mfu.set_fem(gf.Fem('FEM_PK(2,2)'))
-mfrhs.set_fem(gf.Fem('FEM_PK(2,2)'))
+mfu.set_fem(gf.Fem("FEM_PK(2,2)"))
+mfrhs.set_fem(gf.Fem("FEM_PK(2,2)"))
 
 #  Integration method used
-mim = gf.MeshIm(m, gf.Integ('IM_TRIANGLE(4)'))
+mim = gf.MeshIm(m, gf.Integ("IM_TRIANGLE(4)"))
 
 # Boundary selection
-flst  = m.outer_faces()
-fnor  = m.normal_of_faces(flst)
-tleft = abs(fnor[1,:]+1) < 1e-14
-ttop  = abs(fnor[0,:]-1) < 1e-14
+flst = m.outer_faces()
+fnor = m.normal_of_faces(flst)
+tleft = abs(fnor[1, :] + 1) < 1e-14
+ttop = abs(fnor[0, :] - 1) < 1e-14
 fleft = np.compress(tleft, flst, axis=1)
-ftop  = np.compress(ttop, flst, axis=1)
+ftop = np.compress(ttop, flst, axis=1)
 fneum = np.compress(np.logical_not(ttop + tleft), flst, axis=1)
 
 # Mark it as boundary
@@ -68,53 +71,52 @@ m.set_region(DIRICHLET_BOUNDARY_NUM2, ftop)
 m.set_region(NEUMANN_BOUNDARY_NUM, fneum)
 
 # Interpolate the exact solution (Assuming mfu is a Lagrange fem)
-Ue = mfu.eval('y*(y-1)*x*(x-1)+x*x*x*x*x')
+Ue = mfu.eval("y*(y-1)*x*(x-1)+x*x*x*x*x")
 
 # Interpolate the source term
-F1 = mfrhs.eval('-(2*(x*x+y*y)-2*x-2*y+20*x*x*x)')
-F2 = mfrhs.eval('[y*(y-1)*(2*x-1) + 5*x*x*x*x, x*(x-1)*(2*y-1)]')
+F1 = mfrhs.eval("-(2*(x*x+y*y)-2*x-2*y+20*x*x*x)")
+F2 = mfrhs.eval("[y*(y-1)*(2*x-1) + 5*x*x*x*x, x*(x-1)*(2*y-1)]")
 
 # Model
-md = gf.Model('real')
+md = gf.Model("real")
 
 # Main unknown
-md.add_fem_variable('u', mfu)
+md.add_fem_variable("u", mfu)
 
 # Laplacian term on u
-md.add_Laplacian_brick(mim, 'u')
+md.add_Laplacian_brick(mim, "u")
 
 # Volumic source term
-md.add_initialized_fem_data('VolumicData', mfrhs, F1)
-md.add_source_term_brick(mim, 'u', 'VolumicData')
+md.add_initialized_fem_data("VolumicData", mfrhs, F1)
+md.add_source_term_brick(mim, "u", "VolumicData")
 
 # Neumann condition.
-md.add_initialized_fem_data('NeumannData', mfrhs, F2)
-md.add_normal_source_term_brick(mim, 'u', 'NeumannData',
-                                NEUMANN_BOUNDARY_NUM)
+md.add_initialized_fem_data("NeumannData", mfrhs, F2)
+md.add_normal_source_term_brick(mim, "u", "NeumannData", NEUMANN_BOUNDARY_NUM)
 
 # Dirichlet condition on the left.
 md.add_initialized_fem_data("DirichletData", mfu, Ue)
 
-if (Dirichlet_with_multipliers):
-  md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu,
-                                              DIRICHLET_BOUNDARY_NUM1,
-                                              'DirichletData')
+if Dirichlet_with_multipliers:
+    md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfu, DIRICHLET_BOUNDARY_NUM1, "DirichletData"
+    )
 else:
-  md.add_Dirichlet_condition_with_penalization(mim, 'u', dirichlet_coefficient,
-                                               DIRICHLET_BOUNDARY_NUM1,
-                                               'DirichletData')
+    md.add_Dirichlet_condition_with_penalization(
+        mim, "u", dirichlet_coefficient, DIRICHLET_BOUNDARY_NUM1, 
"DirichletData"
+    )
 
 # Dirichlet condition on the top.
 # Two Dirichlet brick in order to test the multiplier
 # selection in the intersection.
-if (Dirichlet_with_multipliers):
-  md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu,
-                                              DIRICHLET_BOUNDARY_NUM2,
-                                              'DirichletData')
+if Dirichlet_with_multipliers:
+    md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfu, DIRICHLET_BOUNDARY_NUM2, "DirichletData"
+    )
 else:
-  md.add_Dirichlet_condition_with_penalization(mim, 'u', dirichlet_coefficient,
-                                               DIRICHLET_BOUNDARY_NUM2,
-                                               'DirichletData')
+    md.add_Dirichlet_condition_with_penalization(
+        mim, "u", dirichlet_coefficient, DIRICHLET_BOUNDARY_NUM2, 
"DirichletData"
+    )
 gf.memstats()
 # md.listvar()
 # md.listbricks()
@@ -123,19 +125,18 @@ gf.memstats()
 md.solve()
 
 # Main unknown
-U = md.variable('u')
-L2error = gf.compute(mfu, U-Ue, 'L2 norm', mim)
-H1error = gf.compute(mfu, U-Ue, 'H1 norm', mim)
-print('Error in L2 norm : ', L2error)
-print('Error in H1 norm : ', H1error)
+U = md.variable("u")
+L2error = gf.compute(mfu, U - Ue, "L2 norm", mim)
+H1error = gf.compute(mfu, U - Ue, "H1 norm", mim)
+print("Error in L2 norm : ", L2error)
+print("Error in H1 norm : ", H1error)
 
 # Export data
-mfu.export_to_pos('laplacian.pos', Ue,'Exact solution',
-                                    U,'Computed solution')
-print('You can view the solution with (for example):')
-print('gmsh laplacian.pos')
+mfu.export_to_pos("laplacian.pos", Ue, "Exact solution", U, "Computed 
solution")
+print("You can view the solution with (for example):")
+print("gmsh laplacian.pos")
 
 
-if (H1error > 1e-3):
-    print('Error too large !')
+if H1error > 1e-3:
+    print("Error too large !")
     exit(1)
diff --git a/interface/tests/python/demo_laplacian_DG.py 
b/interface/tests/python/demo_laplacian_DG.py
index 921f769..654eb8f 100644
--- a/interface/tests/python/demo_laplacian_DG.py
+++ b/interface/tests/python/demo_laplacian_DG.py
@@ -36,34 +36,38 @@ import getfem as gf
 import numpy as np
 
 ## Parameters
-NX = 20                            # Mesh parameter.
+NX = 20  # Mesh parameter.
 Dirichlet_with_multipliers = True  # Dirichlet condition with multipliers
-                                   # or penalization
-dirichlet_coefficient = 1e10       # Penalization coefficient
-interior_penalty_factor = 1e2*NX   # Parameter of the interior penalty term
-verify_neighbour_computation = True;
+# or penalization
+dirichlet_coefficient = 1e10  # Penalization coefficient
+interior_penalty_factor = 1e2 * NX  # Parameter of the interior penalty term
+verify_neighbour_computation = True
 
 
 # Create a simple cartesian mesh
-m = gf.Mesh('regular_simplices', np.arange(0,1+1./NX,1./NX), 
np.arange(0,1+1./NX,1./NX))
+m = gf.Mesh(
+    "regular_simplices",
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+)
 
 # Create a MeshFem for u and rhs fields of dimension 1 (i.e. a scalar field)
-mfu   = gf.MeshFem(m, 1)
+mfu = gf.MeshFem(m, 1)
 mfrhs = gf.MeshFem(m, 1)
 # Assign the discontinuous P2 fem to all convexes of the both MeshFem
-mfu.set_fem(gf.Fem('FEM_PK_DISCONTINUOUS(2,2)'))
-mfrhs.set_fem(gf.Fem('FEM_PK(2,2)'))
+mfu.set_fem(gf.Fem("FEM_PK_DISCONTINUOUS(2,2)"))
+mfrhs.set_fem(gf.Fem("FEM_PK(2,2)"))
 
 # Integration method used
-mim = gf.MeshIm(m, gf.Integ('IM_TRIANGLE(4)'))
+mim = gf.MeshIm(m, gf.Integ("IM_TRIANGLE(4)"))
 
 # Boundary selection
-flst  = m.outer_faces()
-fnor  = m.normal_of_faces(flst)
-tleft = abs(fnor[1,:]+1) < 1e-14
-ttop  = abs(fnor[0,:]-1) < 1e-14
+flst = m.outer_faces()
+fnor = m.normal_of_faces(flst)
+tleft = abs(fnor[1, :] + 1) < 1e-14
+ttop = abs(fnor[0, :] - 1) < 1e-14
 fleft = np.compress(tleft, flst, axis=1)
-ftop  = np.compress(ttop, flst, axis=1)
+ftop = np.compress(ttop, flst, axis=1)
 fneum = np.compress(True - ttop - tleft, flst, axis=1)
 
 # Mark it as boundary
@@ -76,74 +80,79 @@ m.set_region(NEUMANN_BOUNDARY_NUM, fneum)
 
 # Inner edges for the interior penalty terms
 in_faces = m.inner_faces()
-INNER_FACES=4
+INNER_FACES = 4
 m.set_region(INNER_FACES, in_faces)
 
-if (verify_neighbour_computation):
-  TEST_FACES=5
-  adjf = m.adjacent_face(42, 0);
-  if (len(adjf) != 2):
-    print('No adjacent edge found, change the element number')
-    exit(1)
-  m.set_region(TEST_FACES, np.array([[42,adjf[0][0]], [0,adjf[1][0]]]));
-  
+if verify_neighbour_computation:
+    TEST_FACES = 5
+    adjf = m.adjacent_face(42, 0)
+    if len(adjf) != 2:
+        print("No adjacent edge found, change the element number")
+        exit(1)
+    m.set_region(TEST_FACES, np.array([[42, adjf[0][0]], [0, adjf[1][0]]]))
+
 
 # Interpolate the exact solution (Assuming mfu is a Lagrange fem)
-Ue = mfu.eval('y*(y-1)*x*(x-1)+x*x*x*x*x')
+Ue = mfu.eval("y*(y-1)*x*(x-1)+x*x*x*x*x")
 
 # Interpolate the source term
-F1 = mfrhs.eval('-(2*(x*x+y*y)-2*x-2*y+20*x*x*x)')
-F2 = mfrhs.eval('[y*(y-1)*(2*x-1) + 5*x*x*x*x, x*(x-1)*(2*y-1)]')
+F1 = mfrhs.eval("-(2*(x*x+y*y)-2*x-2*y+20*x*x*x)")
+F2 = mfrhs.eval("[y*(y-1)*(2*x-1) + 5*x*x*x*x, x*(x-1)*(2*y-1)]")
 
 # Model
-md = gf.Model('real')
+md = gf.Model("real")
 
 # Main unknown
-md.add_fem_variable('u', mfu)
+md.add_fem_variable("u", mfu)
 
 # Laplacian term on u
-md.add_Laplacian_brick(mim, 'u')
+md.add_Laplacian_brick(mim, "u")
 
 # Volumic source term
-md.add_initialized_fem_data('VolumicData', mfrhs, F1)
-md.add_source_term_brick(mim, 'u', 'VolumicData')
+md.add_initialized_fem_data("VolumicData", mfrhs, F1)
+md.add_source_term_brick(mim, "u", "VolumicData")
 
 # Neumann condition.
-md.add_initialized_fem_data('NeumannData', mfrhs, F2)
-md.add_normal_source_term_brick(mim, 'u', 'NeumannData',
-                                NEUMANN_BOUNDARY_NUM)
+md.add_initialized_fem_data("NeumannData", mfrhs, F2)
+md.add_normal_source_term_brick(mim, "u", "NeumannData", NEUMANN_BOUNDARY_NUM)
 
 # Dirichlet condition on the left.
 md.add_initialized_fem_data("DirichletData", mfu, Ue)
 
-if (Dirichlet_with_multipliers):
-  md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu,
-                                              DIRICHLET_BOUNDARY_NUM1,
-                                              'DirichletData')
+if Dirichlet_with_multipliers:
+    md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfu, DIRICHLET_BOUNDARY_NUM1, "DirichletData"
+    )
 else:
-  md.add_Dirichlet_condition_with_penalization(mim, 'u', dirichlet_coefficient,
-                                               DIRICHLET_BOUNDARY_NUM1,
-                                               'DirichletData')
+    md.add_Dirichlet_condition_with_penalization(
+        mim, "u", dirichlet_coefficient, DIRICHLET_BOUNDARY_NUM1, 
"DirichletData"
+    )
 
 # Dirichlet condition on the top.
 # Two Dirichlet brick in order to test the multiplier
 # selection in the intersection.
-if (Dirichlet_with_multipliers):
-  md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu,
-                                              DIRICHLET_BOUNDARY_NUM2,
-                                              'DirichletData')
+if Dirichlet_with_multipliers:
+    md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfu, DIRICHLET_BOUNDARY_NUM2, "DirichletData"
+    )
 else:
-  md.add_Dirichlet_condition_with_penalization(mim, 'u', dirichlet_coefficient,
-                                               DIRICHLET_BOUNDARY_NUM2,
-                                               'DirichletData')
+    md.add_Dirichlet_condition_with_penalization(
+        mim, "u", dirichlet_coefficient, DIRICHLET_BOUNDARY_NUM2, 
"DirichletData"
+    )
 
 # Interior penalty terms
-md.add_initialized_data('alpha', [interior_penalty_factor])
+md.add_initialized_data("alpha", [interior_penalty_factor])
 jump = "((u-Interpolate(u,neighbour_elt))*Normal)"
 test_jump = "((Test_u-Interpolate(Test_u,neighbour_elt))*Normal)"
 grad_mean = "((Grad_u+Interpolate(Grad_u,neighbour_elt))*0.5)"
 grad_test_mean = "((Grad_Test_u+Interpolate(Grad_Test_u,neighbour_elt))*0.5)"
-md.add_linear_term(mim, 
"-(({F}).({G}))-(({H}).({I}))+alpha*(({J}).({K}))".format(F=grad_mean, 
G=test_jump, H=jump, I=grad_test_mean, J=jump, K=test_jump), INNER_FACES);
+md.add_linear_term(
+    mim,
+    "-(({F}).({G}))-(({H}).({I}))+alpha*(({J}).({K}))".format(
+        F=grad_mean, G=test_jump, H=jump, I=grad_test_mean, J=jump, K=test_jump
+    ),
+    INNER_FACES,
+)
 
 gf.memstats()
 # md.listvar()
@@ -153,30 +162,44 @@ gf.memstats()
 md.solve()
 
 # Main unknown
-U = md.variable('u')
-L2error = gf.compute(mfu, U-Ue, 'L2 norm', mim)
-H1error = gf.compute(mfu, U-Ue, 'H1 norm', mim)
-print('Error in L2 norm : ', L2error)
-print('Error in H1 norm : ', H1error)
+U = md.variable("u")
+L2error = gf.compute(mfu, U - Ue, "L2 norm", mim)
+H1error = gf.compute(mfu, U - Ue, "H1 norm", mim)
+print("Error in L2 norm : ", L2error)
+print("Error in H1 norm : ", H1error)
 
 # Export data
-mfu.export_to_pos('laplacian.pos', Ue,'Exact solution',
-                                    U,'Computed solution')
-print('You can view the solution with (for example):')
-print('gmsh laplacian.pos')
-
-if (verify_neighbour_computation):
-  A=gf.asm('generic', mim, 1, 'u*Test_u*(Normal.Normal)', TEST_FACES, md)
-  B=gf.asm('generic', mim, 1, 
'-Interpolate(u,neighbour_elt)*Interpolate(Test_u,neighbour_elt)*(Interpolate(Normal,neighbour_elt).Normal)',
 TEST_FACES, md)
-  err_v = np.linalg.norm(A-B)
-  A=gf.asm('generic', mim, 1, '(Grad_u.Normal)*(Grad_Test_u.Normal)', 
TEST_FACES, md)
-  B=gf.asm('generic', mim, 1, 
'(Interpolate(Grad_u,neighbour_elt).Normal)*(Interpolate(Grad_Test_u,neighbour_elt).Normal)',
 TEST_FACES, md)
-  err_v = err_v + np.linalg.norm(A-B)
-  if (err_v > 1E-13):
-    print('Test on neighbour element computation: error to big: ', err_v)
+mfu.export_to_pos("laplacian.pos", Ue, "Exact solution", U, "Computed 
solution")
+print("You can view the solution with (for example):")
+print("gmsh laplacian.pos")
+
+if verify_neighbour_computation:
+    A = gf.asm("generic", mim, 1, "u*Test_u*(Normal.Normal)", TEST_FACES, md)
+    B = gf.asm(
+        "generic",
+        mim,
+        1,
+        
"-Interpolate(u,neighbour_elt)*Interpolate(Test_u,neighbour_elt)*(Interpolate(Normal,neighbour_elt).Normal)",
+        TEST_FACES,
+        md,
+    )
+    err_v = np.linalg.norm(A - B)
+    A = gf.asm(
+        "generic", mim, 1, "(Grad_u.Normal)*(Grad_Test_u.Normal)", TEST_FACES, 
md
+    )
+    B = gf.asm(
+        "generic",
+        mim,
+        1,
+        
"(Interpolate(Grad_u,neighbour_elt).Normal)*(Interpolate(Grad_Test_u,neighbour_elt).Normal)",
+        TEST_FACES,
+        md,
+    )
+    err_v = err_v + np.linalg.norm(A - B)
+    if err_v > 1e-13:
+        print("Test on neighbour element computation: error to big: ", err_v)
+        exit(1)
+
+if H1error > 1e-3:
+    print("Error too large !")
     exit(1)
-  
-if (H1error > 1e-3):
-    print('Error too large !')
-    exit(1)
-
diff --git a/interface/tests/python/demo_laplacian_aposteriori.py 
b/interface/tests/python/demo_laplacian_aposteriori.py
index ea229cd..4170554 100644
--- a/interface/tests/python/demo_laplacian_aposteriori.py
+++ b/interface/tests/python/demo_laplacian_aposteriori.py
@@ -31,136 +31,151 @@ import getfem as gf
 import numpy as np
 
 ## Parameters
-h = 4.                             # Mesh parameter.
+h = 4.0  # Mesh parameter.
 Dirichlet_with_multipliers = True  # Dirichlet condition with multipliers
-                                   # or penalization
-dirichlet_coefficient = 1e10       # Penalization coefficient
-export_mesh = True                 # Draw the mesh after mesh generation or not
+# or penalization
+dirichlet_coefficient = 1e10  # Penalization coefficient
+export_mesh = True  # Draw the mesh after mesh generation or not
 
 
 # Create a mesh
-mo1 = gf.MesherObject('rectangle', [0., 50.], [100., 100.])
-mo2 = gf.MesherObject('rectangle', [50., 0.], [100., 100.])
-mo3 = gf.MesherObject('union', mo1, mo2)
-mo4 = gf.MesherObject('ball', [25., 75], 8.)
-mo5 = gf.MesherObject('ball', [75., 25.], 8.)
-mo6 = gf.MesherObject('ball', [75., 75.], 8.)
-mo7 = gf.MesherObject('union', mo4, mo5, mo6)
-mo  = gf.MesherObject('set minus', mo3, mo7)
-
-gf.util('trace level', 2)   # No trace for mesh generation
-mesh = gf.Mesh('generate', mo, h, 3)
+mo1 = gf.MesherObject("rectangle", [0.0, 50.0], [100.0, 100.0])
+mo2 = gf.MesherObject("rectangle", [50.0, 0.0], [100.0, 100.0])
+mo3 = gf.MesherObject("union", mo1, mo2)
+mo4 = gf.MesherObject("ball", [25.0, 75], 8.0)
+mo5 = gf.MesherObject("ball", [75.0, 25.0], 8.0)
+mo6 = gf.MesherObject("ball", [75.0, 75.0], 8.0)
+mo7 = gf.MesherObject("union", mo4, mo5, mo6)
+mo = gf.MesherObject("set minus", mo3, mo7)
+
+gf.util("trace level", 2)  # No trace for mesh generation
+mesh = gf.Mesh("generate", mo, h, 3)
 
 #
 # Boundary selection
 #
-fb1 = mesh.outer_faces_with_direction([-1., 0.], 0.01) # Left   (Dirichlet)
-fb2 = mesh.outer_faces_with_direction([0., -1.], 0.01) # Bottom (Neumann)
-fb3 = mesh.outer_faces_in_box([-1., 10.], [101., 101.]) 
-fb4 = mesh.outer_faces_in_box([10., -1.], [101., 101.]) 
-LEFT_BOUND=1; BOTTOM_BOUND=2; AUX_BOUND1 = 3; AUX_BOUND2 = 4; 
-mesh.set_region(  LEFT_BOUND, fb1)
+fb1 = mesh.outer_faces_with_direction([-1.0, 0.0], 0.01)  # Left   (Dirichlet)
+fb2 = mesh.outer_faces_with_direction([0.0, -1.0], 0.01)  # Bottom (Neumann)
+fb3 = mesh.outer_faces_in_box([-1.0, 10.0], [101.0, 101.0])
+fb4 = mesh.outer_faces_in_box([10.0, -1.0], [101.0, 101.0])
+LEFT_BOUND = 1
+BOTTOM_BOUND = 2
+AUX_BOUND1 = 3
+AUX_BOUND2 = 4
+mesh.set_region(LEFT_BOUND, fb1)
 mesh.set_region(BOTTOM_BOUND, fb2)
-mesh.set_region(  AUX_BOUND1, fb3)
-mesh.set_region(  AUX_BOUND2, fb4)
-mesh.region_subtract(  LEFT_BOUND, AUX_BOUND2)
+mesh.set_region(AUX_BOUND1, fb3)
+mesh.set_region(AUX_BOUND2, fb4)
+mesh.region_subtract(LEFT_BOUND, AUX_BOUND2)
 mesh.region_subtract(BOTTOM_BOUND, AUX_BOUND1)
 
 # Create a MeshFem for u and rhs fields of dimension 1 (i.e. a scalar field)
-mfu  = gf.MeshFem(mesh, 1)
+mfu = gf.MeshFem(mesh, 1)
 mfP0 = gf.MeshFem(mesh, 1)
 # Assign the discontinuous P2 fem to all convexes of the both MeshFem
-mfu.set_fem(gf.Fem('FEM_PK(2,2)'))
-mfP0.set_fem(gf.Fem('FEM_PK(2,0)'))
+mfu.set_fem(gf.Fem("FEM_PK(2,2)"))
+mfP0.set_fem(gf.Fem("FEM_PK(2,0)"))
 
 # Integration method used
-mim = gf.MeshIm(mesh, gf.Integ('IM_TRIANGLE(4)'))
+mim = gf.MeshIm(mesh, gf.Integ("IM_TRIANGLE(4)"))
 
 # Inner edges for the computation of the normal derivative jump
 in_faces = mesh.inner_faces()
-INNER_FACES=18
+INNER_FACES = 18
 mesh.set_region(INNER_FACES, in_faces)
 
 # Model
-md = gf.Model('real')
+md = gf.Model("real")
 
 # Main unknown
-md.add_fem_variable('u', mfu)
+md.add_fem_variable("u", mfu)
 
 # Laplacian term on u
-md.add_Laplacian_brick(mim, 'u')
+md.add_Laplacian_brick(mim, "u")
 
 # Volumic source term
 # md.add_initialized_fem_data('VolumicData', mfrhs, F1)
 # md.add_source_term_brick(mim, 'u', 'VolumicData')
 
 # Neumann condition.
-md.add_initialized_data('NeumannData', [0.001])
-md.add_source_term_brick(mim, 'u', 'NeumannData', BOTTOM_BOUND)
+md.add_initialized_data("NeumannData", [0.001])
+md.add_source_term_brick(mim, "u", "NeumannData", BOTTOM_BOUND)
 
 # Dirichlet condition on the left.
-if (Dirichlet_with_multipliers):
-  md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, LEFT_BOUND)
+if Dirichlet_with_multipliers:
+    md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, LEFT_BOUND)
 else:
-  md.add_Dirichlet_condition_with_penalization(mim, 'u', dirichlet_coefficient,
-                                               LEFT_BOUND)
+    md.add_Dirichlet_condition_with_penalization(
+        mim, "u", dirichlet_coefficient, LEFT_BOUND
+    )
 
 for refiter in range(5):
-    
-    if (export_mesh):
-      mesh.export_to_vtk('mesh%d.vtk' % refiter)
-    
-    print('\nYou can view the mesh for instance with')
-    print('mayavi2 -d mesh%d.vtk -f ExtractEdges -m Surface \n'%refiter)
-    
+
+    if export_mesh:
+        mesh.export_to_vtk("mesh%d.vtk" % refiter)
+
+    print("\nYou can view the mesh for instance with")
+    print("mayavi2 -d mesh%d.vtk -f ExtractEdges -m Surface \n" % refiter)
+
     # Assembly of the linear system and solve.
     md.solve()
-    
+
     # Main unknown
-    U = md.variable('u')
-    
+    U = md.variable("u")
+
     # Residual a posteriori estimator
-    
-    grad_jump = '( (Grad_u-Interpolate(Grad_u,neighbour_elt)).Normal )'
-
-    bulkresidual = 'sqr(element_size*Trace(Hess_u))*Test_psi'
-    edgeresidual = '0.25*element_size*sqr(%s)*(Test_psi + 
Interpolate(Test_psi,neighbour_elt))'%grad_jump
-
-    ETA1tmp = 
gf.asm('generic',mim,1,bulkresidual,-1,md,'psi',1,mfP0,np.zeros(mfP0.nbdof()))
-    ETA1 = ETA1tmp [ ETA1tmp.size - mfP0.nbdof() : ETA1tmp.size ]
-    ETA2tmp = 
gf.asm('generic',mim,1,edgeresidual,INNER_FACES,md,'psi',1,mfP0,np.zeros(mfP0.nbdof()))
-    ETA2 = ETA2tmp [ ETA2tmp.size - mfP0.nbdof() : ETA2tmp.size ]
-    ETA  = np.sqrt ( ETA1 + ETA2 )
-    
-    # Export data
-    mfu.export_to_pos('laplacian%d.pos'%refiter, U, 'Computed solution')
-    print('You can view the solution with (for example):')
-    print('gmsh laplacian%d.pos'%refiter)
-    
-    mfP0.export_to_pos('eta1_%d.pos'%refiter, ETA1, 'Bulk residual')
-    print('You can view eta1 with (for example):')
-    print('gmsh eta1_%d.pos'%refiter)
-    
-    mfP0.export_to_pos('eta2_%d.pos'%refiter, ETA2, 'Edge residual')
-    print('You can view eta2 with (for example):')
-    print('gmsh eta2_%d.pos'%refiter)
-    
-    mfu.export_to_vtk('laplacian%d.vtk'%refiter, mfu, U, 'u', mfP0, ETA1, 
'eta1', mfP0, ETA2, 'eta2')
-    print('mayavi2 -d laplacian%d.vtk -f WarpScalar -m Surface'%refiter)
-    
-    # Refine the mesh
-    dd=mfP0.basic_dof_from_cvid()
-    
-    ETAElt = np.zeros(dd[0].size)
-    for i in range(dd[0].size):
-        ETAElt[i] = ETA[ dd[0][i] ] 
-    
-    mesh.refine(np.where( ETAElt > 0.6*np.max(ETA) ))
-    mesh.optimize_structure()
 
+    grad_jump = "( (Grad_u-Interpolate(Grad_u,neighbour_elt)).Normal )"
+
+    bulkresidual = "sqr(element_size*Trace(Hess_u))*Test_psi"
+    edgeresidual = (
+        "0.25*element_size*sqr(%s)*(Test_psi + 
Interpolate(Test_psi,neighbour_elt))"
+        % grad_jump
+    )
+
+    ETA1tmp = gf.asm(
+        "generic", mim, 1, bulkresidual, -1, md, "psi", 1, mfP0, 
np.zeros(mfP0.nbdof())
+    )
+    ETA1 = ETA1tmp[ETA1tmp.size - mfP0.nbdof() : ETA1tmp.size]
+    ETA2tmp = gf.asm(
+        "generic",
+        mim,
+        1,
+        edgeresidual,
+        INNER_FACES,
+        md,
+        "psi",
+        1,
+        mfP0,
+        np.zeros(mfP0.nbdof()),
+    )
+    ETA2 = ETA2tmp[ETA2tmp.size - mfP0.nbdof() : ETA2tmp.size]
+    ETA = np.sqrt(ETA1 + ETA2)
+
+    # Export data
+    mfu.export_to_pos("laplacian%d.pos" % refiter, U, "Computed solution")
+    print("You can view the solution with (for example):")
+    print("gmsh laplacian%d.pos" % refiter)
 
+    mfP0.export_to_pos("eta1_%d.pos" % refiter, ETA1, "Bulk residual")
+    print("You can view eta1 with (for example):")
+    print("gmsh eta1_%d.pos" % refiter)
 
+    mfP0.export_to_pos("eta2_%d.pos" % refiter, ETA2, "Edge residual")
+    print("You can view eta2 with (for example):")
+    print("gmsh eta2_%d.pos" % refiter)
 
+    mfu.export_to_vtk(
+        "laplacian%d.vtk" % refiter, mfu, U, "u", mfP0, ETA1, "eta1", mfP0, 
ETA2, "eta2"
+    )
+    print("mayavi2 -d laplacian%d.vtk -f WarpScalar -m Surface" % refiter)
 
+    # Refine the mesh
+    dd = mfP0.basic_dof_from_cvid()
 
+    ETAElt = np.zeros(dd[0].size)
+    for i in range(dd[0].size):
+        ETAElt[i] = ETA[dd[0][i]]
 
+    mesh.refine(np.where(ETAElt > 0.6 * np.max(ETA)))
+    mesh.optimize_structure()
diff --git a/interface/tests/python/demo_laplacian_pyramid.py 
b/interface/tests/python/demo_laplacian_pyramid.py
index 50abe33..a8660f3 100644
--- a/interface/tests/python/demo_laplacian_pyramid.py
+++ b/interface/tests/python/demo_laplacian_pyramid.py
@@ -34,47 +34,51 @@
 import getfem as gf
 import numpy as np
 
-export_mesh = True;
+export_mesh = True
 
 ## Parameters
-NX = 10                            # Mesh parameter.
+NX = 10  # Mesh parameter.
 Dirichlet_with_multipliers = True  # Dirichlet condition with multipliers
-                                   # or penalization
-dirichlet_coefficient = 1e10       # Penalization coefficient
+# or penalization
+dirichlet_coefficient = 1e10  # Penalization coefficient
 
 # Create a simple cartesian mesh
-m = gf.Mesh('pyramidal', np.arange(0,1+1./NX,1./NX),
-            np.arange(0,1+1./NX,1./NX), np.arange(0,1+1./NX,1./NX) )
+m = gf.Mesh(
+    "pyramidal",
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+)
 # m = gf.Mesh('regular_simplices', np.arange(0,1+1./NX,1./NX),
 #            np.arange(0,1+1./NX,1./NX), np.arange(0,1+1./NX,1./NX) )
 
 # Create a MeshFem for u and rhs fields of dimension 1 (i.e. a scalar field)
-mfu   = gf.MeshFem(m, 1)
+mfu = gf.MeshFem(m, 1)
 mfrhs = gf.MeshFem(m, 1)
 # assign the Lagrange linear fem to all pyramids of the both MeshFem
-mfu.set_fem(gf.Fem('FEM_PYRAMID_LAGRANGE(2)'))
-mfrhs.set_fem(gf.Fem('FEM_PYRAMID_LAGRANGE(2)'))
+mfu.set_fem(gf.Fem("FEM_PYRAMID_LAGRANGE(2)"))
+mfrhs.set_fem(gf.Fem("FEM_PYRAMID_LAGRANGE(2)"))
 # mfu.set_fem(gf.Fem('FEM_PK(3,1)'))
 # mfrhs.set_fem(gf.Fem('FEM_PK(3,1)'))
 
-if (export_mesh):
-  m.export_to_vtk('mesh.vtk');
-  print('\nYou can view the mesh for instance with');
-  print('mayavi2 -d mesh.vtk -f ExtractEdges -m Surface \n');
+if export_mesh:
+    m.export_to_vtk("mesh.vtk")
+    print("\nYou can view the mesh for instance with")
+    print("mayavi2 -d mesh.vtk -f ExtractEdges -m Surface \n")
 
 
 #  Integration method used
 # mim = gf.MeshIm(m, gf.Integ('IM_PYRAMID_COMPOSITE(IM_TETRAHEDRON(6))'))
-mim = gf.MeshIm(m, gf.Integ('IM_PYRAMID(IM_GAUSS_PARALLELEPIPED(3,3))'))
+mim = gf.MeshIm(m, gf.Integ("IM_PYRAMID(IM_GAUSS_PARALLELEPIPED(3,3))"))
 # mim = gf.MeshIm(m, gf.Integ('IM_TETRAHEDRON(5)'))
 
 # Boundary selection
-flst  = m.outer_faces()
-fnor  = m.normal_of_faces(flst)
-tleft = abs(fnor[1,:]+1) < 1e-14
-ttop  = abs(fnor[0,:]-1) < 1e-14
+flst = m.outer_faces()
+fnor = m.normal_of_faces(flst)
+tleft = abs(fnor[1, :] + 1) < 1e-14
+ttop = abs(fnor[0, :] - 1) < 1e-14
 fleft = np.compress(tleft, flst, axis=1)
-ftop  = np.compress(ttop, flst, axis=1)
+ftop = np.compress(ttop, flst, axis=1)
 fneum = np.compress(True - ttop - tleft, flst, axis=1)
 
 # Mark it as boundary
@@ -86,53 +90,52 @@ m.set_region(DIRICHLET_BOUNDARY_NUM2, ftop)
 m.set_region(NEUMANN_BOUNDARY_NUM, fneum)
 
 # Interpolate the exact solution (Assuming mfu is a Lagrange fem)
-Ue = mfu.eval('y*(y-1)*x*(x-1)+x*x*x*x*x')
+Ue = mfu.eval("y*(y-1)*x*(x-1)+x*x*x*x*x")
 
 # Interpolate the source term
-F1 = mfrhs.eval('-(2*(x*x+y*y)-2*x-2*y+20*x*x*x)')
-F2 = mfrhs.eval('[y*(y-1)*(2*x-1) + 5*x*x*x*x, x*(x-1)*(2*y-1), 0]')
+F1 = mfrhs.eval("-(2*(x*x+y*y)-2*x-2*y+20*x*x*x)")
+F2 = mfrhs.eval("[y*(y-1)*(2*x-1) + 5*x*x*x*x, x*(x-1)*(2*y-1), 0]")
 
 # Model
-md = gf.Model('real')
+md = gf.Model("real")
 
 # Main unknown
-md.add_fem_variable('u', mfu)
+md.add_fem_variable("u", mfu)
 
 # Laplacian term on u
-md.add_Laplacian_brick(mim, 'u')
+md.add_Laplacian_brick(mim, "u")
 
 # Volumic source term
-md.add_initialized_fem_data('VolumicData', mfrhs, F1)
-md.add_source_term_brick(mim, 'u', 'VolumicData')
+md.add_initialized_fem_data("VolumicData", mfrhs, F1)
+md.add_source_term_brick(mim, "u", "VolumicData")
 
 # Neumann condition.
-md.add_initialized_fem_data('NeumannData', mfrhs, F2)
-md.add_normal_source_term_brick(mim, 'u', 'NeumannData',
-                                NEUMANN_BOUNDARY_NUM)
+md.add_initialized_fem_data("NeumannData", mfrhs, F2)
+md.add_normal_source_term_brick(mim, "u", "NeumannData", NEUMANN_BOUNDARY_NUM)
 
 # Dirichlet condition on the left.
 md.add_initialized_fem_data("DirichletData", mfu, Ue)
 
-if (Dirichlet_with_multipliers):
-  md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu,
-                                              DIRICHLET_BOUNDARY_NUM1,
-                                              'DirichletData')
+if Dirichlet_with_multipliers:
+    md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfu, DIRICHLET_BOUNDARY_NUM1, "DirichletData"
+    )
 else:
-  md.add_Dirichlet_condition_with_penalization(mim, 'u', dirichlet_coefficient,
-                                               DIRICHLET_BOUNDARY_NUM1,
-                                               'DirichletData')
+    md.add_Dirichlet_condition_with_penalization(
+        mim, "u", dirichlet_coefficient, DIRICHLET_BOUNDARY_NUM1, 
"DirichletData"
+    )
 
 # Dirichlet condition on the top.
 # Two Dirichlet brick in order to test the multiplier
 # selection in the intersection.
-if (Dirichlet_with_multipliers):
-  md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu,
-                                              DIRICHLET_BOUNDARY_NUM2,
-                                              'DirichletData')
+if Dirichlet_with_multipliers:
+    md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfu, DIRICHLET_BOUNDARY_NUM2, "DirichletData"
+    )
 else:
-  md.add_Dirichlet_condition_with_penalization(mim, 'u', dirichlet_coefficient,
-                                               DIRICHLET_BOUNDARY_NUM2,
-                                               'DirichletData')
+    md.add_Dirichlet_condition_with_penalization(
+        mim, "u", dirichlet_coefficient, DIRICHLET_BOUNDARY_NUM2, 
"DirichletData"
+    )
 # gf.memstats()
 # md.listvar()
 # md.listbricks()
@@ -141,25 +144,37 @@ else:
 md.solve()
 
 # Main unknown
-U = md.variable('u')
-L2error = gf.compute(mfu, U-Ue, 'L2 norm', mim)
-H1error = gf.compute(mfu, U-Ue, 'H1 norm', mim)
-print('Error in L2 norm : ', L2error)
-print('Error in H1 norm : ', H1error)
-UU = np.zeros(U.size);
-UU[4] = 1.;
+U = md.variable("u")
+L2error = gf.compute(mfu, U - Ue, "L2 norm", mim)
+H1error = gf.compute(mfu, U - Ue, "H1 norm", mim)
+print("Error in L2 norm : ", L2error)
+print("Error in H1 norm : ", H1error)
+UU = np.zeros(U.size)
+UU[4] = 1.0
 
 # Export data
-mfu.export_to_pos('laplacian.pos', Ue, 'Exact solution',
-                  U, 'Computed solution', UU, 'Test field')
-print('You can view the solution with (for example):')
-print('gmsh laplacian.pos')
-
-mfu.export_to_vtk('laplacian.vtk', mfu, Ue, 'Exact solution', mfu, U, 
'Computed solution', mfu, UU, 'Test field');
-print('\nYou can view the solution for instance with');
-print('mayavi2 -d laplacian.vtk -m Surface \n');
-
-
-if (H1error > 0.09):
-    print('Error too large !')
+mfu.export_to_pos(
+    "laplacian.pos", Ue, "Exact solution", U, "Computed solution", UU, "Test 
field"
+)
+print("You can view the solution with (for example):")
+print("gmsh laplacian.pos")
+
+mfu.export_to_vtk(
+    "laplacian.vtk",
+    mfu,
+    Ue,
+    "Exact solution",
+    mfu,
+    U,
+    "Computed solution",
+    mfu,
+    UU,
+    "Test field",
+)
+print("\nYou can view the solution for instance with")
+print("mayavi2 -d laplacian.vtk -m Surface \n")
+
+
+if H1error > 0.09:
+    print("Error too large !")
     exit(1)
diff --git a/interface/tests/python/demo_large_sliding_contact.py 
b/interface/tests/python/demo_large_sliding_contact.py
index 4576514..6970963 100644
--- a/interface/tests/python/demo_large_sliding_contact.py
+++ b/interface/tests/python/demo_large_sliding_contact.py
@@ -26,69 +26,83 @@ import numpy as np
 
 gf.util_trace_level(1)
 
-test_case = 3 # 0 = 2D punch on a rigid obstacle
-              # 1 = 2D punch on a deformable obstacle (one slave, one master)
-              # 2 = 2D with two different meshes
-              # 3 = 2D with multi-body and only one mesh
-              # 4 = 3D case (sphere / parallelepiped) (two meshes)
-
-clambda1 = 1.   # Elasticity parameters
-cmu1 = 1.
-clambda2 = 1.   # Elasticity parameters
-cmu2 = 1.
-r = 0.1         # Augmentation parameter
-alpha = 1.      # Alpha coefficient for "sliding velocity"
-f_coeff = 0.    # Friction coefficient
+test_case = 3  # 0 = 2D punch on a rigid obstacle
+# 1 = 2D punch on a deformable obstacle (one slave, one master)
+# 2 = 2D with two different meshes
+# 3 = 2D with multi-body and only one mesh
+# 4 = 3D case (sphere / parallelepiped) (two meshes)
+
+clambda1 = 1.0  # Elasticity parameters
+cmu1 = 1.0
+clambda2 = 1.0  # Elasticity parameters
+cmu2 = 1.0
+r = 0.1  # Augmentation parameter
+alpha = 1.0  # Alpha coefficient for "sliding velocity"
+f_coeff = 0.0  # Friction coefficient
 
 test_tangent_matrix = False
 nonlinear_elasticity = False
 max_iter = 50
 
-if test_case in [0,1]:
-   vf = 0.
-   vf_mult = 1.
-   penalty_parameter = 0.
-   dirichlet_translation = -0.5
-   max_res = 1e-8
-   release_dist = 1.5
-   self_contact = False
-   load_steps = 40
+if test_case in [0, 1]:
+    vf = 0.0
+    vf_mult = 1.0
+    penalty_parameter = 0.0
+    dirichlet_translation = -0.5
+    max_res = 1e-8
+    release_dist = 1.5
+    self_contact = False
+    load_steps = 40
 elif test_case == 3:
-   vf = 0.01       # Vertical force
-   vf_mult = 1.01
-   penalty_parameter = 0.1
-   release_dist = 0.05
-   max_res = 1e-9
-   self_contact = True
-   load_steps = 250
-elif test_case in [2,4]:
-   vf = 0.01
-   vf_mult = 1.5
-   penalty_parameter = 0.01
-   max_res = 1e-8
-   if test_case == 2:
-      release_dist = 0.1
-   else:
-      release_dist = 5.
-   self_contact = True
-   load_steps = 10000
+    vf = 0.01  # Vertical force
+    vf_mult = 1.01
+    penalty_parameter = 0.1
+    release_dist = 0.05
+    max_res = 1e-9
+    self_contact = True
+    load_steps = 250
+elif test_case in [2, 4]:
+    vf = 0.01
+    vf_mult = 1.5
+    penalty_parameter = 0.01
+    max_res = 1e-8
+    if test_case == 2:
+        release_dist = 0.1
+    else:
+        release_dist = 5.0
+    self_contact = True
+    load_steps = 10000
 
 if test_case == 0:
-   #mesh1 = gf.Mesh("load", "../../../tests/meshes/punch2D_1.mesh")
-   mesh1 = gf.Mesh("load", "../../../tests/meshes/punch2D_2.mesh")
+    # mesh1 = gf.Mesh("load", "../../../tests/meshes/punch2D_1.mesh")
+    mesh1 = gf.Mesh("load", "../../../tests/meshes/punch2D_2.mesh")
 elif test_case == 1:
-   #mesh1 = gf.Mesh("load", "../../../tests/meshes/punch2D_1.mesh")
-   mesh1 = gf.Mesh("load", "../../../tests/meshes/punch2D_2.mesh")
-   mesh2 = gf.Mesh("import", "structured", 
"GT='GT_PK(2,1)';ORG=[-14,-5];SIZES=[28,5];NSUBDIV=[28,5]")
+    # mesh1 = gf.Mesh("load", "../../../tests/meshes/punch2D_1.mesh")
+    mesh1 = gf.Mesh("load", "../../../tests/meshes/punch2D_2.mesh")
+    mesh2 = gf.Mesh(
+        "import",
+        "structured",
+        "GT='GT_PK(2,1)';ORG=[-14,-5];SIZES=[28,5];NSUBDIV=[28,5]",
+    )
 elif test_case == 2:
-   mesh1 = gf.Mesh("load", "../../../tests/meshes/disc_with_a_hole.mesh")
-   #mesh1 = gf.Mesh("import", "structured", 
"GT='GT_PK(2,1)';ORG=[-0.5,0.1];SIZES=[1,0.1];NSUBDIV=[20,2]")
-   mesh2 = gf.Mesh("import", "structured", 
"GT='GT_PK(2,1)';ORG=[-0.5,0];SIZES=[1,0.1];NSUBDIV=[20,2]")
+    mesh1 = gf.Mesh("load", "../../../tests/meshes/disc_with_a_hole.mesh")
+    # mesh1 = gf.Mesh("import", "structured", 
"GT='GT_PK(2,1)';ORG=[-0.5,0.1];SIZES=[1,0.1];NSUBDIV=[20,2]")
+    mesh2 = gf.Mesh(
+        "import",
+        "structured",
+        "GT='GT_PK(2,1)';ORG=[-0.5,0];SIZES=[1,0.1];NSUBDIV=[20,2]",
+    )
 elif test_case == 3:
-   mesh1 = gf.Mesh("load", "../../../tests/meshes/multi_body.mesh")
+    mesh1 = gf.Mesh("load", "../../../tests/meshes/multi_body.mesh")
 elif test_case == 4:
-   mesh1 = gf.Mesh("load", 
"../../../tests/meshes/sphere_with_quadratic_tetra_400_elts.mesh")
-   mesh2 = gf.Mesh("import", "structured", 
"GT='GT_PK(3,1)';ORG=[-15,-15,-4];SIZES=[30,30,4];NSUBDIV=[10,10,2]")
+    mesh1 = gf.Mesh(
+        "load", 
"../../../tests/meshes/sphere_with_quadratic_tetra_400_elts.mesh"
+    )
+    mesh2 = gf.Mesh(
+        "import",
+        "structured",
+        "GT='GT_PK(3,1)';ORG=[-15,-15,-4];SIZES=[30,30,4];NSUBDIV=[10,10,2]",
+    )
 two_meshes = "mesh2" in locals()
 
 N = mesh1.dim()
@@ -106,16 +120,16 @@ CONTACT_BOUNDARY1 = 1
 DIRICHLET_BOUNDARY1 = 3
 border = mesh1.outer_faces()
 if test_case >= 2:
-   mesh1.set_region(CONTACT_BOUNDARY1, border)
+    mesh1.set_region(CONTACT_BOUNDARY1, border)
 else:
-   normals = mesh1.normal_of_faces(border)
-   contact_boundary = border[:,np.nonzero(normals[N-1] < -0.01)[0]]
-   mesh1.set_region(CONTACT_BOUNDARY1, contact_boundary)
-   P = mesh1.pts()  # get list of mesh points coordinates
-   ctop = (P[N-1,:] > 39.999)  # find those on top of the object
-   pidtop = np.compress(ctop, list(range(0, mesh1.nbpts())))
-   ftop = mesh1.faces_from_pid(pidtop)
-   mesh1.set_region(DIRICHLET_BOUNDARY1, ftop)
+    normals = mesh1.normal_of_faces(border)
+    contact_boundary = border[:, np.nonzero(normals[N - 1] < -0.01)[0]]
+    mesh1.set_region(CONTACT_BOUNDARY1, contact_boundary)
+    P = mesh1.pts()  # get list of mesh points coordinates
+    ctop = P[N - 1, :] > 39.999  # find those on top of the object
+    pidtop = np.compress(ctop, list(range(0, mesh1.nbpts())))
+    ftop = mesh1.faces_from_pid(pidtop)
+    mesh1.set_region(DIRICHLET_BOUNDARY1, ftop)
 
 # dol1 = pre_mflambda1.basic_dof_on_region(CONTACT_BOUNDARY1)
 # mflambda1 = gf.MeshFem("partial", pre_mflambda1, dol1)
@@ -123,109 +137,113 @@ else:
 mim1 = gf.MeshIm(mesh1, 4)
 mim1_contact = gf.MeshIm(mesh1, 4)
 
-if test_case not in [0,3]:
-   mfu2 = gf.MeshFem(mesh2, N)
-   mfu2.set_classical_fem(2)
+if test_case not in [0, 3]:
+    mfu2 = gf.MeshFem(mesh2, N)
+    mfu2.set_classical_fem(2)
 
-   pre_mflambda2 = gf.MeshFem(mesh2, N)
-   pre_mflambda2.set_classical_fem(1)
+    pre_mflambda2 = gf.MeshFem(mesh2, N)
+    pre_mflambda2.set_classical_fem(1)
 
-   mfvm2 = gf.MeshFem(mesh2)
-   mfvm2.set_classical_discontinuous_fem(1)
+    mfvm2 = gf.MeshFem(mesh2)
+    mfvm2.set_classical_discontinuous_fem(1)
 
-   CONTACT_BOUNDARY2 = 2
-   border = mesh2.outer_faces()
-   if test_case != 1:
-      mesh2.set_region(CONTACT_BOUNDARY2, border)
-   else:
-      normals = mesh2.normal_of_faces(border)
-      contact_boundary = border[:,np.nonzero(normals[N-1] > 0.01)[0]]
-      mesh2.set_region(CONTACT_BOUNDARY2, contact_boundary)
-      dirichlet_boundary = border[:,np.nonzero(normals[N-1] < -0.01)[0]]
-      DIRICHLET_BOUNDARY2 = 5
-      mesh2.set_region(DIRICHLET_BOUNDARY2, dirichlet_boundary)
+    CONTACT_BOUNDARY2 = 2
+    border = mesh2.outer_faces()
+    if test_case != 1:
+        mesh2.set_region(CONTACT_BOUNDARY2, border)
+    else:
+        normals = mesh2.normal_of_faces(border)
+        contact_boundary = border[:, np.nonzero(normals[N - 1] > 0.01)[0]]
+        mesh2.set_region(CONTACT_BOUNDARY2, contact_boundary)
+        dirichlet_boundary = border[:, np.nonzero(normals[N - 1] < -0.01)[0]]
+        DIRICHLET_BOUNDARY2 = 5
+        mesh2.set_region(DIRICHLET_BOUNDARY2, dirichlet_boundary)
 
-   mim2 = gf.MeshIm(mesh2, 4)
-   mim2_contact = gf.MeshIm(mesh2, 4)
+    mim2 = gf.MeshIm(mesh2, 4)
+    mim2_contact = gf.MeshIm(mesh2, 4)
 
 md = gf.Model("real")
 
 F = np.zeros(N)
-F[N-1] = -vf
+F[N - 1] = -vf
 
 w1_str = ""
 w2_str = ""
 
 md.add_fem_variable("u1", mfu1)
 if f_coeff > 1e-10:
-   md.add_fem_data("w1", mfu1)
-   w1_str = "w1"
+    md.add_fem_data("w1", mfu1)
+    w1_str = "w1"
 md.add_filtered_fem_variable("lambda1", pre_mflambda1, CONTACT_BOUNDARY1)
 
 if nonlinear_elasticity:
-   lawname = "Ciarlet Geymonat"
-   params1 = [clambda1, cmu1, cmu1/2-clambda1/8]
-   md.add_initialized_data("params1", params1)
-   md.add_nonlinear_elasticity_brick(mim1, "u1", lawname, "params1")
+    lawname = "Ciarlet Geymonat"
+    params1 = [clambda1, cmu1, cmu1 / 2 - clambda1 / 8]
+    md.add_initialized_data("params1", params1)
+    md.add_nonlinear_elasticity_brick(mim1, "u1", lawname, "params1")
 else:
-   md.add_initialized_data("clambda1", clambda1)
-   md.add_initialized_data("cmu1", cmu1)
-   md.add_isotropic_linearized_elasticity_brick(mim1, "u1", "clambda1", "cmu1")
+    md.add_initialized_data("clambda1", clambda1)
+    md.add_initialized_data("cmu1", cmu1)
+    md.add_isotropic_linearized_elasticity_brick(mim1, "u1", "clambda1", 
"cmu1")
 
 if test_case == 2:
-#   md.add_initialized_data("cpoints1", [0 0.5 0 1.5 0 0.5 0 1.5])
-#   md.add_initialized_data("cunitv1", [1 0 1 0 0 1 0 1])
-#   md.add_initialized_data("cdata", [0 0 -0.01 -0.01])
-#   md.add_pointwise_constraints_with_multipliers("u1", "cpoints1", "cunitv1", 
"cdata")
-   md.add_initialized_data("cpoints1", [0,0.5,0,1.5])
-   md.add_initialized_data("cunitv1", [1,0,1,0])
-   md.add_initialized_data("cdata", [0,0])
-   md.add_pointwise_constraints_with_multipliers("u1", "cpoints1", "cunitv1", 
"cdata")
+    #   md.add_initialized_data("cpoints1", [0 0.5 0 1.5 0 0.5 0 1.5])
+    #   md.add_initialized_data("cunitv1", [1 0 1 0 0 1 0 1])
+    #   md.add_initialized_data("cdata", [0 0 -0.01 -0.01])
+    #   md.add_pointwise_constraints_with_multipliers("u1", "cpoints1", 
"cunitv1", "cdata")
+    md.add_initialized_data("cpoints1", [0, 0.5, 0, 1.5])
+    md.add_initialized_data("cunitv1", [1, 0, 1, 0])
+    md.add_initialized_data("cdata", [0, 0])
+    md.add_pointwise_constraints_with_multipliers("u1", "cpoints1", "cunitv1", 
"cdata")
 
 md.add_initialized_data("penalty_param1", [penalty_parameter])
 md.add_mass_brick(mim1, "u1", "penalty_param1")
 md.add_initialized_data("data1", F)
 md.add_source_term_brick(mim1, "u1", "data1")
 
-if test_case not in [0,3]:
-   md.add_fem_variable("u2", mfu2)
-   if f_coeff > 1e-10:
-      md.add_fem_data("w2", mfu2)
-      w2_str = "w2"
-   if self_contact:
-      md.add_filtered_fem_variable("lambda2", pre_mflambda2, CONTACT_BOUNDARY2)
-
-   if nonlinear_elasticity:
-      lawname = "Ciarlet Geymonat"
-      params2 = [clambda2, cmu2, cmu2/2-clambda2/8]
-      md.add_initialized_data("params2", params2)
-      md.add_nonlinear_elasticity_brick(mim2, "u2", lawname, "params2")
-   else:
-      md.add_initialized_data("clambda2", clambda2)
-      md.add_initialized_data("cmu2", cmu2)
-
-      md.add_isotropic_linearized_elasticity_brick(mim2, "u2", "clambda2", 
"cmu2")
-
-   if test_case == 2:
-      md.add_initialized_data("cpoints2", [0,0])
-      md.add_initialized_data("cunitv2", [1,0])
-      md.add_pointwise_constraints_with_multipliers("u2", "cpoints2", 
"cunitv2")
-
-   md.add_initialized_data("penalty_param2", [penalty_parameter])
-   md.add_mass_brick(mim2, "u2", "penalty_param2")
-   md.add_initialized_data("data2", F)
-   md.add_source_term_brick(mim2, "u2", "data2")
-
-   if test_case == 1:
-      Ddata = np.zeros(N)
-      md.add_initialized_data("Ddata2", Ddata)
-      md.add_Dirichlet_condition_with_multipliers(mim2, "u2", 1, 
DIRICHLET_BOUNDARY2, "Ddata2")
+if test_case not in [0, 3]:
+    md.add_fem_variable("u2", mfu2)
+    if f_coeff > 1e-10:
+        md.add_fem_data("w2", mfu2)
+        w2_str = "w2"
+    if self_contact:
+        md.add_filtered_fem_variable("lambda2", pre_mflambda2, 
CONTACT_BOUNDARY2)
+
+    if nonlinear_elasticity:
+        lawname = "Ciarlet Geymonat"
+        params2 = [clambda2, cmu2, cmu2 / 2 - clambda2 / 8]
+        md.add_initialized_data("params2", params2)
+        md.add_nonlinear_elasticity_brick(mim2, "u2", lawname, "params2")
+    else:
+        md.add_initialized_data("clambda2", clambda2)
+        md.add_initialized_data("cmu2", cmu2)
+
+        md.add_isotropic_linearized_elasticity_brick(mim2, "u2", "clambda2", 
"cmu2")
+
+    if test_case == 2:
+        md.add_initialized_data("cpoints2", [0, 0])
+        md.add_initialized_data("cunitv2", [1, 0])
+        md.add_pointwise_constraints_with_multipliers("u2", "cpoints2", 
"cunitv2")
+
+    md.add_initialized_data("penalty_param2", [penalty_parameter])
+    md.add_mass_brick(mim2, "u2", "penalty_param2")
+    md.add_initialized_data("data2", F)
+    md.add_source_term_brick(mim2, "u2", "data2")
+
+    if test_case == 1:
+        Ddata = np.zeros(N)
+        md.add_initialized_data("Ddata2", Ddata)
+        md.add_Dirichlet_condition_with_multipliers(
+            mim2, "u2", 1, DIRICHLET_BOUNDARY2, "Ddata2"
+        )
 
 if test_case <= 1:
-   Ddata = np.zeros(N)
-   Ddata[N-1] = dirichlet_translation
-   md.add_initialized_data("Ddata1", Ddata)
-   md.add_Dirichlet_condition_with_multipliers(mim1, "u1", 1, 
DIRICHLET_BOUNDARY1, "Ddata1")
+    Ddata = np.zeros(N)
+    Ddata[N - 1] = dirichlet_translation
+    md.add_initialized_data("Ddata1", Ddata)
+    md.add_Dirichlet_condition_with_multipliers(
+        mim1, "u1", 1, DIRICHLET_BOUNDARY1, "Ddata1"
+    )
 
 md.add_initialized_data("r", r)
 md.add_initialized_data("alpha", alpha)
@@ -233,124 +251,208 @@ md.add_initialized_data("f", f_coeff)
 
 direct_generic_assembly = False
 if direct_generic_assembly:  # Direct use of high-level generic assembly
-  # TODO: account for w1, w2 when f_coeff > 0
-  md.add_raytracing_transformation("contact_trans", release_dist)
-  if two_meshes: # The definition of a variable group is not mandatory. Just 
for test.
-    md.define_variable_group("u", "u1", "u2")
-  else:
-    md.define_variable_group("u", "u1")
-
-  if self_contact:
-    
md.add_master_contact_boundary_to_raytracing_transformation("contact_trans", 
mesh1, "u", CONTACT_BOUNDARY1)
-  else:
-    
md.add_slave_contact_boundary_to_raytracing_transformation("contact_trans", 
mesh1, "u", CONTACT_BOUNDARY1)
-
-  if test_case == 0:
-    md.add_rigid_obstacle_to_raytracing_transformation("contact_trans", 
"80-sqrt(sqr(x)+sqr(y-80))", N)
-  elif test_case == 1:
-    
md.add_master_contact_boundary_to_raytracing_transformation("contact_trans", 
mesh2, "u", CONTACT_BOUNDARY2)
-  elif test_case == 2:
-    
md.add_master_contact_boundary_to_raytracing_transformation("contact_trans", 
mesh2, "u", CONTACT_BOUNDARY2)
-    md.add_rigid_obstacle_to_raytracing_transformation("contact_trans", "y+1", 
N)
-  elif test_case == 3:
-    md.add_rigid_obstacle_to_raytracing_transformation("contact_trans", 
"2-sqrt(sqr(x)+sqr(y-1))", N)
-  elif test_case == 4:
-    
md.add_master_contact_boundary_to_raytracing_transformation("contact_trans", 
mesh2, "u", CONTACT_BOUNDARY2)
-    md.add_rigid_obstacle_to_raytracing_transformation("contact_trans", "z+5", 
N)
-
-  md.add_nonlinear_term(mim1_contact, "-lambda1.Test_u1", CONTACT_BOUNDARY1) 
-  md.add_nonlinear_term(mim1_contact, "Interpolate_filter(contact_trans, 
lambda1.Interpolate(Test_u,contact_trans), 1)", CONTACT_BOUNDARY1) 
-  md.add_nonlinear_term(mim1_contact, "-(1/r)*lambda1.Test_lambda1", 
CONTACT_BOUNDARY1)
-  md.add_nonlinear_term(mim1_contact, "Interpolate_filter(contact_trans, 
(1/r)*Coulomb_friction_coupled_projection(lambda1, 
Transformed_unit_vector(Grad_u1, Normal), u1, 
(Interpolate(X,contact_trans)-X-u1).Transformed_unit_vector(Grad_u1, Normal), 
f, r).Test_lambda1, 2)", CONTACT_BOUNDARY1)
-  md.add_nonlinear_term(mim1_contact, "Interpolate_filter(contact_trans, 
(1/r)*Coulomb_friction_coupled_projection(lambda1, 
Transformed_unit_vector(Grad_u1, Normal), u1-Interpolate(u,contact_trans), 
(Interpolate(X,contact_trans)+Interpolate(u,contact_trans)-X-u1).Transformed_unit_vector(Grad_u1,
 Normal), f, r).Test_lambda1, 1)", CONTACT_BOUNDARY1)
-  
-  if two_meshes and self_contact:
-    md.add_nonlinear_term(mim2_contact, "-lambda2.Test_u2", CONTACT_BOUNDARY2) 
-    md.add_nonlinear_term(mim2_contact, "Interpolate_filter(contact_trans, 
lambda2.Interpolate(Test_u,contact_trans), 1)", CONTACT_BOUNDARY2) 
-    md.add_nonlinear_term(mim2_contact, "-(1/r)*lambda2.Test_lambda2", 
CONTACT_BOUNDARY2)
-    md.add_nonlinear_term(mim2_contact, "Interpolate_filter(contact_trans, 
(1/r)*Coulomb_friction_coupled_projection(lambda2, 
Transformed_unit_vector(Grad_u2, Normal), u2, 
(Interpolate(X,contact_trans)-X-u2).Transformed_unit_vector(Grad_u2, Normal), 
f, r).Test_lambda2, 2)", CONTACT_BOUNDARY2)
-    md.add_nonlinear_term(mim2_contact, "Interpolate_filter(contact_trans, 
(1/r)*Coulomb_friction_coupled_projection(lambda2, 
Transformed_unit_vector(Grad_u2, Normal), u2-Interpolate(u,contact_trans), 
(Interpolate(X,contact_trans)+Interpolate(u,contact_trans)-X-u2).Transformed_unit_vector(Grad_u2,
 Normal), f, r).Test_lambda2, 1)", CONTACT_BOUNDARY2)  
-
-  u_group = "u"
-  contact_trans = "contact_trans"
-else: # Use of the new contact brick which uses the high-level generic assembly
-
-  ind = md.add_integral_large_sliding_contact_brick_raytracing("r", 
release_dist, "f", "alpha", 0)
-
-  if self_contact:
-    md.add_master_slave_contact_boundary_to_large_sliding_contact_brick(ind,  
mim1_contact, CONTACT_BOUNDARY1, "u1", "lambda1", w1_str)
-  else:
-    md.add_slave_contact_boundary_to_large_sliding_contact_brick(ind,  
mim1_contact, CONTACT_BOUNDARY1, "u1", "lambda1", w1_str)
-
-  if test_case == 0:
-    md.add_rigid_obstacle_to_large_sliding_contact_brick(ind, 
"80-sqrt(sqr(x)+sqr(y-80))", N)
-  elif test_case == 1:
-    md.add_master_contact_boundary_to_large_sliding_contact_brick(ind, 
mim2_contact, CONTACT_BOUNDARY2, "u2", w2_str)
-  elif test_case == 2:
-    md.add_master_slave_contact_boundary_to_large_sliding_contact_brick(ind, 
mim2_contact, CONTACT_BOUNDARY2, "u2", "lambda2", w2_str)
-    md.add_rigid_obstacle_to_large_sliding_contact_brick(ind, "y+1", N)
-  elif test_case == 3:
-    md.add_rigid_obstacle_to_large_sliding_contact_brick(ind, 
"2-sqrt(sqr(x)+sqr(y-1))", N)
-  elif test_case == 4:
-    md.add_master_slave_contact_boundary_to_large_sliding_contact_brick(ind, 
mim2_contact, CONTACT_BOUNDARY2, "u2", "lambda2", w2_str)
-    md.add_rigid_obstacle_to_large_sliding_contact_brick(ind, "z+5", N)
-
-  u_group = md.displacement_group_name_of_large_sliding_contact_brick(ind)
-  contact_trans = md.transformation_name_of_large_sliding_contact_brick(ind)
+    # TODO: account for w1, w2 when f_coeff > 0
+    md.add_raytracing_transformation("contact_trans", release_dist)
+    if (
+        two_meshes
+    ):  # The definition of a variable group is not mandatory. Just for test.
+        md.define_variable_group("u", "u1", "u2")
+    else:
+        md.define_variable_group("u", "u1")
+
+    if self_contact:
+        md.add_master_contact_boundary_to_raytracing_transformation(
+            "contact_trans", mesh1, "u", CONTACT_BOUNDARY1
+        )
+    else:
+        md.add_slave_contact_boundary_to_raytracing_transformation(
+            "contact_trans", mesh1, "u", CONTACT_BOUNDARY1
+        )
+
+    if test_case == 0:
+        md.add_rigid_obstacle_to_raytracing_transformation(
+            "contact_trans", "80-sqrt(sqr(x)+sqr(y-80))", N
+        )
+    elif test_case == 1:
+        md.add_master_contact_boundary_to_raytracing_transformation(
+            "contact_trans", mesh2, "u", CONTACT_BOUNDARY2
+        )
+    elif test_case == 2:
+        md.add_master_contact_boundary_to_raytracing_transformation(
+            "contact_trans", mesh2, "u", CONTACT_BOUNDARY2
+        )
+        md.add_rigid_obstacle_to_raytracing_transformation("contact_trans", 
"y+1", N)
+    elif test_case == 3:
+        md.add_rigid_obstacle_to_raytracing_transformation(
+            "contact_trans", "2-sqrt(sqr(x)+sqr(y-1))", N
+        )
+    elif test_case == 4:
+        md.add_master_contact_boundary_to_raytracing_transformation(
+            "contact_trans", mesh2, "u", CONTACT_BOUNDARY2
+        )
+        md.add_rigid_obstacle_to_raytracing_transformation("contact_trans", 
"z+5", N)
+
+    md.add_nonlinear_term(mim1_contact, "-lambda1.Test_u1", CONTACT_BOUNDARY1)
+    md.add_nonlinear_term(
+        mim1_contact,
+        "Interpolate_filter(contact_trans, 
lambda1.Interpolate(Test_u,contact_trans), 1)",
+        CONTACT_BOUNDARY1,
+    )
+    md.add_nonlinear_term(
+        mim1_contact, "-(1/r)*lambda1.Test_lambda1", CONTACT_BOUNDARY1
+    )
+    md.add_nonlinear_term(
+        mim1_contact,
+        "Interpolate_filter(contact_trans, 
(1/r)*Coulomb_friction_coupled_projection(lambda1, 
Transformed_unit_vector(Grad_u1, Normal), u1, 
(Interpolate(X,contact_trans)-X-u1).Transformed_unit_vector(Grad_u1, Normal), 
f, r).Test_lambda1, 2)",
+        CONTACT_BOUNDARY1,
+    )
+    md.add_nonlinear_term(
+        mim1_contact,
+        "Interpolate_filter(contact_trans, 
(1/r)*Coulomb_friction_coupled_projection(lambda1, 
Transformed_unit_vector(Grad_u1, Normal), u1-Interpolate(u,contact_trans), 
(Interpolate(X,contact_trans)+Interpolate(u,contact_trans)-X-u1).Transformed_unit_vector(Grad_u1,
 Normal), f, r).Test_lambda1, 1)",
+        CONTACT_BOUNDARY1,
+    )
+
+    if two_meshes and self_contact:
+        md.add_nonlinear_term(mim2_contact, "-lambda2.Test_u2", 
CONTACT_BOUNDARY2)
+        md.add_nonlinear_term(
+            mim2_contact,
+            "Interpolate_filter(contact_trans, 
lambda2.Interpolate(Test_u,contact_trans), 1)",
+            CONTACT_BOUNDARY2,
+        )
+        md.add_nonlinear_term(
+            mim2_contact, "-(1/r)*lambda2.Test_lambda2", CONTACT_BOUNDARY2
+        )
+        md.add_nonlinear_term(
+            mim2_contact,
+            "Interpolate_filter(contact_trans, 
(1/r)*Coulomb_friction_coupled_projection(lambda2, 
Transformed_unit_vector(Grad_u2, Normal), u2, 
(Interpolate(X,contact_trans)-X-u2).Transformed_unit_vector(Grad_u2, Normal), 
f, r).Test_lambda2, 2)",
+            CONTACT_BOUNDARY2,
+        )
+        md.add_nonlinear_term(
+            mim2_contact,
+            "Interpolate_filter(contact_trans, 
(1/r)*Coulomb_friction_coupled_projection(lambda2, 
Transformed_unit_vector(Grad_u2, Normal), u2-Interpolate(u,contact_trans), 
(Interpolate(X,contact_trans)+Interpolate(u,contact_trans)-X-u2).Transformed_unit_vector(Grad_u2,
 Normal), f, r).Test_lambda2, 1)",
+            CONTACT_BOUNDARY2,
+        )
+
+    u_group = "u"
+    contact_trans = "contact_trans"
+else:  # Use of the new contact brick which uses the high-level generic 
assembly
+
+    ind = md.add_integral_large_sliding_contact_brick_raytracing(
+        "r", release_dist, "f", "alpha", 0
+    )
+
+    if self_contact:
+        md.add_master_slave_contact_boundary_to_large_sliding_contact_brick(
+            ind, mim1_contact, CONTACT_BOUNDARY1, "u1", "lambda1", w1_str
+        )
+    else:
+        md.add_slave_contact_boundary_to_large_sliding_contact_brick(
+            ind, mim1_contact, CONTACT_BOUNDARY1, "u1", "lambda1", w1_str
+        )
+
+    if test_case == 0:
+        md.add_rigid_obstacle_to_large_sliding_contact_brick(
+            ind, "80-sqrt(sqr(x)+sqr(y-80))", N
+        )
+    elif test_case == 1:
+        md.add_master_contact_boundary_to_large_sliding_contact_brick(
+            ind, mim2_contact, CONTACT_BOUNDARY2, "u2", w2_str
+        )
+    elif test_case == 2:
+        md.add_master_slave_contact_boundary_to_large_sliding_contact_brick(
+            ind, mim2_contact, CONTACT_BOUNDARY2, "u2", "lambda2", w2_str
+        )
+        md.add_rigid_obstacle_to_large_sliding_contact_brick(ind, "y+1", N)
+    elif test_case == 3:
+        md.add_rigid_obstacle_to_large_sliding_contact_brick(
+            ind, "2-sqrt(sqr(x)+sqr(y-1))", N
+        )
+    elif test_case == 4:
+        md.add_master_slave_contact_boundary_to_large_sliding_contact_brick(
+            ind, mim2_contact, CONTACT_BOUNDARY2, "u2", "lambda2", w2_str
+        )
+        md.add_rigid_obstacle_to_large_sliding_contact_brick(ind, "z+5", N)
+
+    u_group = md.displacement_group_name_of_large_sliding_contact_brick(ind)
+    contact_trans = md.transformation_name_of_large_sliding_contact_brick(ind)
 
 
 for nit in range(load_steps):
 
-   if test_tangent_matrix:
-      errmax = md.test_tangent_matrix(1E-8, 20, 0.0001)
-      #errmax = md.test_tangent_matrix_term("lambda1", "u1", 1E-8, 20, 0.0001)
-      print("errmax = %g" % errmax)
-      if errmax > 1e-3:
-         print("bad tangent matrix")
-
-   if w1_str:
-      md.set_variable(w1_str, md.variable("u1"))
-   if w2_str:
-      md.set_variable(w2_str, md.variable("u2"))
-
-   print("SOLVING LOAD STEP %i" % nit)
-   md.solve("noisy", "max_iter", max_iter, "max_res", max_res) # , "lsearch", 
"simplest")
-
-   U1 = md.variable("u1")
-   if nonlinear_elasticity:
-      VM1 = md.compute_Von_Mises_or_Tresca("u1", lawname, "params1", mfvm1)
-   else:
-      VM1 = md.compute_isotropic_linearized_Von_Mises_or_Tresca("u1", 
"clambda1", "cmu1", mfvm1)
-   mfvm1.export_to_vtk("lsc_1_%i.vtk" % nit, mfvm1,  VM1,
-                       "Von Mises Stresses 1", mfu1, U1, "Displacements 1")
-
-   lambda1 = md.variable("lambda1")
-   mf_lambda1 = md.mesh_fem_of_variable("lambda1")
-   sl = gf.Slice(("boundary",), mf_lambda1, CONTACT_BOUNDARY1)
-   sl.export_to_vtk("lsc_1_boundary_%i.vtk" % nit,
-                    mfu1, U1, "BDisplacements 1",
-                    mf_lambda1, lambda1, "BMultiplier 1")
-
-   if test_case not in [0,3]:
-      U2 = md.variable("u2")
-      if nonlinear_elasticity:
-         VM2 = md.compute_Von_Mises_or_Tresca("u2", lawname, "params2", mfvm2)
-      else:
-         VM2 = md.compute_isotropic_linearized_Von_Mises_or_Tresca("u2", 
"clambda2", "cmu2", mfvm2)
-      mfvm2.export_to_vtk("lsc_2_%i.vtk" % nit, mfvm2,  VM2,
-                          "Von Mises Stresses 2", mfu2, U2, "Displacements 2")
-
-      sl = gf.Slice(("boundary",), mfu2, CONTACT_BOUNDARY2)
-      sl.export_to_vtk("lsc_2_boundary_%i.vtk" % nit,
-                       mfu2, U2, "BDisplacements 2")
-
-   vf *= vf_mult
-   F[N-1] = -vf
-   md.set_variable("data1", F)
-   if test_case not in [0,3]:
-      md.set_variable("data2", F)
-
-   if test_case <= 1:
-      Ddata[N-1] -= 1.
-      md.set_variable("Ddata1", Ddata)
-
+    if test_tangent_matrix:
+        errmax = md.test_tangent_matrix(1e-8, 20, 0.0001)
+        # errmax = md.test_tangent_matrix_term("lambda1", "u1", 1E-8, 20, 
0.0001)
+        print("errmax = %g" % errmax)
+        if errmax > 1e-3:
+            print("bad tangent matrix")
+
+    if w1_str:
+        md.set_variable(w1_str, md.variable("u1"))
+    if w2_str:
+        md.set_variable(w2_str, md.variable("u2"))
+
+    print("SOLVING LOAD STEP %i" % nit)
+    md.solve(
+        "noisy", "max_iter", max_iter, "max_res", max_res
+    )  # , "lsearch", "simplest")
+
+    U1 = md.variable("u1")
+    if nonlinear_elasticity:
+        VM1 = md.compute_Von_Mises_or_Tresca("u1", lawname, "params1", mfvm1)
+    else:
+        VM1 = md.compute_isotropic_linearized_Von_Mises_or_Tresca(
+            "u1", "clambda1", "cmu1", mfvm1
+        )
+    mfvm1.export_to_vtk(
+        "lsc_1_%i.vtk" % nit,
+        mfvm1,
+        VM1,
+        "Von Mises Stresses 1",
+        mfu1,
+        U1,
+        "Displacements 1",
+    )
+
+    lambda1 = md.variable("lambda1")
+    mf_lambda1 = md.mesh_fem_of_variable("lambda1")
+    sl = gf.Slice(("boundary",), mf_lambda1, CONTACT_BOUNDARY1)
+    sl.export_to_vtk(
+        "lsc_1_boundary_%i.vtk" % nit,
+        mfu1,
+        U1,
+        "BDisplacements 1",
+        mf_lambda1,
+        lambda1,
+        "BMultiplier 1",
+    )
+
+    if test_case not in [0, 3]:
+        U2 = md.variable("u2")
+        if nonlinear_elasticity:
+            VM2 = md.compute_Von_Mises_or_Tresca("u2", lawname, "params2", 
mfvm2)
+        else:
+            VM2 = md.compute_isotropic_linearized_Von_Mises_or_Tresca(
+                "u2", "clambda2", "cmu2", mfvm2
+            )
+        mfvm2.export_to_vtk(
+            "lsc_2_%i.vtk" % nit,
+            mfvm2,
+            VM2,
+            "Von Mises Stresses 2",
+            mfu2,
+            U2,
+            "Displacements 2",
+        )
+
+        sl = gf.Slice(("boundary",), mfu2, CONTACT_BOUNDARY2)
+        sl.export_to_vtk("lsc_2_boundary_%i.vtk" % nit, mfu2, U2, 
"BDisplacements 2")
+
+    vf *= vf_mult
+    F[N - 1] = -vf
+    md.set_variable("data1", F)
+    if test_case not in [0, 3]:
+        md.set_variable("data2", F)
+
+    if test_case <= 1:
+        Ddata[N - 1] -= 1.0
+        md.set_variable("Ddata1", Ddata)
diff --git a/interface/tests/python/demo_mortar.py 
b/interface/tests/python/demo_mortar.py
index 43e6e4d..536bd0d 100644
--- a/interface/tests/python/demo_mortar.py
+++ b/interface/tests/python/demo_mortar.py
@@ -41,45 +41,53 @@ xc = 0.5
 yc = 0.5
 
 # creation of a simple cartesian mesh
-m = gf.Mesh('cartesian', np.arange(0,1+0.5/NX,1./NX), 
np.arange(0,1+0.5/NX,1./NX))
+m = gf.Mesh(
+    "cartesian",
+    np.arange(0, 1 + 0.5 / NX, 1.0 / NX),
+    np.arange(0, 1 + 0.5 / NX, 1.0 / NX),
+)
 
-(pid,idx) = m.pid_from_cvid()
+(pid, idx) = m.pid_from_cvid()
 
 P = m.pts()
 
-is_in_circle = (P[0,:]-xc)**2+(P[1,:]-yc)**2 <= radius**2
+is_in_circle = (P[0, :] - xc) ** 2 + (P[1, :] - yc) ** 2 <= radius ** 2
 
-areap = np.zeros(idx.size-1)
-for cv in range(idx.size-1):
-   if all(is_in_circle[pid[idx[cv]:idx[cv+1]]]):
-      areap[cv] = 1
+areap = np.zeros(idx.size - 1)
+for cv in range(idx.size - 1):
+    if all(is_in_circle[pid[idx[cv] : idx[cv + 1]]]):
+        areap[cv] = 1
 
-mfu = gf.MeshFem(m,2)
-mfd = gf.MeshFem(m,1)
-mfm = gf.MeshFem(m,2)
-mfdu= gf.MeshFem(m)
+mfu = gf.MeshFem(m, 2)
+mfd = gf.MeshFem(m, 1)
+mfm = gf.MeshFem(m, 2)
+mfdu = gf.MeshFem(m)
 
-mim = gf.MeshIm(m,5)
+mim = gf.MeshIm(m, 5)
 
-mfu.set_fem(gf.Fem('FEM_QK(2,2)'))
-mfd.set_fem(gf.Fem('FEM_QK(2,1)'))
-mfm.set_fem(gf.Fem('FEM_QK(2,2)'))
-mfdu.set_fem(gf.Fem('FEM_QK_DISCONTINUOUS(2,2)'))
+mfu.set_fem(gf.Fem("FEM_QK(2,2)"))
+mfd.set_fem(gf.Fem("FEM_QK(2,1)"))
+mfm.set_fem(gf.Fem("FEM_QK(2,2)"))
+mfdu.set_fem(gf.Fem("FEM_QK_DISCONTINUOUS(2,2)"))
 
 mfu.set_dof_partition(areap)
 
-b_in  = m.outer_faces(np.nonzero(areap==1))
-b_out = m.outer_faces(np.nonzero(areap==0))
+b_in = m.outer_faces(np.nonzero(areap == 1))
+b_out = m.outer_faces(np.nonzero(areap == 0))
 b_border = m.outer_faces()
-b_out = np.array(tuple(set(tuple(r) for r in b_out.transpose())-
-                       set(tuple(r) for r in 
b_border.transpose()))).transpose()
+b_out = np.array(
+    tuple(
+        set(tuple(r) for r in b_out.transpose())
+        - set(tuple(r) for r in b_border.transpose())
+    )
+).transpose()
 
-fleft = m.faces_from_pid(np.nonzero(abs(P[1])<1e-6))
-fright = m.faces_from_pid(np.nonzero(abs(P[1]-1.)<1e-6))
+fleft = m.faces_from_pid(np.nonzero(abs(P[1]) < 1e-6))
+fright = m.faces_from_pid(np.nonzero(abs(P[1] - 1.0) < 1e-6))
 
 # assign boundary numbers
-m.set_region(1,fleft)
-m.set_region(2,fright)
+m.set_region(1, fleft)
+m.set_region(2, fright)
 
 MORTAR_BOUNDARY_IN = 40
 MORTAR_BOUNDARY_OUT = 41
@@ -87,31 +95,32 @@ m.set_region(MORTAR_BOUNDARY_IN, b_in)
 m.set_region(MORTAR_BOUNDARY_OUT, b_out)
 
 indm = mfm.basic_dof_on_region(MORTAR_BOUNDARY_OUT)
-expr = 'M(#1,#2)+=comp(vBase(#1).vBase(#2))(:,i,:,i)'
-M =   gf.asm_boundary(MORTAR_BOUNDARY_IN, expr, mim, mfm, mfu)
-M = M-gf.asm_boundary(MORTAR_BOUNDARY_OUT, expr, mim, mfm, mfu)
-M = gf.Spmat('copy', M, indm, list(range(M.size()[1])))
+expr = "M(#1,#2)+=comp(vBase(#1).vBase(#2))(:,i,:,i)"
+M = gf.asm_boundary(MORTAR_BOUNDARY_IN, expr, mim, mfm, mfu)
+M = M - gf.asm_boundary(MORTAR_BOUNDARY_OUT, expr, mim, mfm, mfu)
+M = gf.Spmat("copy", M, indm, list(range(M.size()[1])))
 
-md = gf.Model('real')
-md.add_fem_variable('u', mfu);
-md.add_initialized_data('lambda', [1])
-md.add_initialized_data('mu', [1])
-md.add_isotropic_linearized_elasticity_brick(mim, 'u', 'lambda', 'mu')
+md = gf.Model("real")
+md.add_fem_variable("u", mfu)
+md.add_initialized_data("lambda", [1])
+md.add_initialized_data("mu", [1])
+md.add_isotropic_linearized_elasticity_brick(mim, "u", "lambda", "mu")
 
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, 1)
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, 1)
 
-F = mfd.eval('[0,y+2]')
+F = mfd.eval("[0,y+2]")
 
-md.add_initialized_fem_data('VolumicData', mfd, F)
-md.add_source_term_brick(mim, 'u', 'VolumicData')
-md.add_variable('mult_spec', indm.size)
-md.add_constraint_with_multipliers('u', 'mult_spec', M, np.zeros(indm.size))
+md.add_initialized_fem_data("VolumicData", mfd, F)
+md.add_source_term_brick(mim, "u", "VolumicData")
+md.add_variable("mult_spec", indm.size)
+md.add_constraint_with_multipliers("u", "mult_spec", M, np.zeros(indm.size))
 
 
-md.solve();
-U = md.get('variable', 'u')
+md.solve()
+U = md.get("variable", "u")
 
-VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u', 'lambda', 'mu', 
mfdu)
-
-mfd.export_to_vtk('mortar.vtk', 'ascii', mfdu,  VM, 'Von Mises Stress', mfu, 
U, 'Displacement')
+VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca("u", "lambda", "mu", 
mfdu)
 
+mfd.export_to_vtk(
+    "mortar.vtk", "ascii", mfdu, VM, "Von Mises Stress", mfu, U, "Displacement"
+)
diff --git a/interface/tests/python/demo_navier_stokes.py 
b/interface/tests/python/demo_navier_stokes.py
index 6dc046c..742f6cd 100644
--- a/interface/tests/python/demo_navier_stokes.py
+++ b/interface/tests/python/demo_navier_stokes.py
@@ -34,45 +34,58 @@ import getfem as gf
 import numpy as np
 
 
-W1 = 0.5         #       _____
-H1 = 0.5         #      |  W1 |
-W2 = 0.5         #      |     |H1
-H2 = 0.5         #      |     |_____
-NW1 = 10         # H1+H2|        W2 |
-NH1 = 10         #      |           |H2
-NW2 = 10         #      |___________|
-NH2 = 10         #          W1+W2
+W1 = 0.5  #       _____
+H1 = 0.5  #      |  W1 |
+W2 = 0.5  #      |     |H1
+H2 = 0.5  #      |     |_____
+NW1 = 10  # H1+H2|        W2 |
+NH1 = 10  #      |           |H2
+NW2 = 10  #      |___________|
+NH2 = 10  #          W1+W2
 
 dt = 0.01
-T = 3.
+T = 3.0
 nu = 0.01
 
 p_in_str = "np.sin(3*{0})"
 
-#Mesh and MeshRegion
+# Mesh and MeshRegion
 IN_RG = 1
 OUT_RG = 2
 INOUT_RG = 3
 WALL_RG = 4
 
 geotrans = "GT_QK(2,2)"
-m = gf.Mesh("import", "structured",
-            "GT='%s';ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]"
-            % (geotrans, 0, H2, W1, H1, NW1, NH1))
-m.merge(gf.Mesh("import", "structured",
-                "GT='%s';ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]"
-                % (geotrans, 0, 0, W1, H2, NW1, NH2)))
-m.merge(gf.Mesh("import", "structured",
-                "GT='%s';ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]"
-                % (geotrans, W1, 0, W2, H2, NW2, NH2)))
+m = gf.Mesh(
+    "import",
+    "structured",
+    "GT='%s';ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]"
+    % (geotrans, 0, H2, W1, H1, NW1, NH1),
+)
+m.merge(
+    gf.Mesh(
+        "import",
+        "structured",
+        "GT='%s';ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]"
+        % (geotrans, 0, 0, W1, H2, NW1, NH2),
+    )
+)
+m.merge(
+    gf.Mesh(
+        "import",
+        "structured",
+        "GT='%s';ORG=[%f,%f];SIZES=[%f,%f];NSUBDIV=[%i,%i]"
+        % (geotrans, W1, 0, W2, H2, NW2, NH2),
+    )
+)
 m.optimize_structure()
 
-l_rg = m.outer_faces_with_direction([-1,0], np.pi/180)
-b_rg = m.outer_faces_with_direction([0,-1], np.pi/180)
-r_rg = m.outer_faces_with_direction([1,0], np.pi/180)
-t_rg = m.outer_faces_with_direction([0,1], np.pi/180)
-in_rg = m.outer_faces_in_box([-1e-6,H1+H2-1e-6],[W1+1e-6,H1+H2+1e-6])
-out_rg = m.outer_faces_in_box([W1+W2-1e-6,-1e-6],[W1+W2+1e-6,H2+1e-6])
+l_rg = m.outer_faces_with_direction([-1, 0], np.pi / 180)
+b_rg = m.outer_faces_with_direction([0, -1], np.pi / 180)
+r_rg = m.outer_faces_with_direction([1, 0], np.pi / 180)
+t_rg = m.outer_faces_with_direction([0, 1], np.pi / 180)
+in_rg = m.outer_faces_in_box([-1e-6, H1 + H2 - 1e-6], [W1 + 1e-6, H1 + H2 + 
1e-6])
+out_rg = m.outer_faces_in_box([W1 + W2 - 1e-6, -1e-6], [W1 + W2 + 1e-6, H2 + 
1e-6])
 m.set_region(IN_RG, in_rg)
 m.set_region(OUT_RG, out_rg)
 m.extend_region(INOUT_RG, in_rg)
@@ -84,54 +97,62 @@ m.extend_region(WALL_RG, r_rg)
 m.extend_region(WALL_RG, t_rg)
 m.region_subtract(WALL_RG, INOUT_RG)
 
-#MeshFem
+# MeshFem
 mfv_ = gf.MeshFem(m, 2)
 mfv_.set_classical_fem(2)
-kept_dofs = np.setdiff1d(np.arange(mfv_.nb_basic_dof()),
-                         mfv_.basic_dof_on_region(WALL_RG))
+kept_dofs = np.setdiff1d(
+    np.arange(mfv_.nb_basic_dof()), mfv_.basic_dof_on_region(WALL_RG)
+)
 mfv = gf.MeshFem("partial", mfv_, kept_dofs)
 
 mfp_ = gf.MeshFem(m, 1)
 mfp_.set_classical_fem(1)
-kept_dofs = np.setdiff1d(np.arange(mfp_.nb_basic_dof()),
-                         mfp_.basic_dof_on_region(OUT_RG))
+kept_dofs = np.setdiff1d(
+    np.arange(mfp_.nb_basic_dof()), mfp_.basic_dof_on_region(OUT_RG)
+)
 mfp = gf.MeshFem("partial", mfp_, kept_dofs)
 
-mim = gf.MeshIm(m, 5) # 9 gauss points per quad
+mim = gf.MeshIm(m, 5)  # 9 gauss points per quad
 
 md = gf.Model("real")
 md.add_fem_variable("v", mfv)
 md.add_fem_data("v0", mfv)
 md.add_fem_variable("p", mfp)
 md.add_fem_data("p_in", mfp_)
-md.add_initialized_data("f", [0,0])
+md.add_initialized_data("f", [0, 0])
 md.add_initialized_data("dt", [dt])
 md.add_initialized_data("nu", [nu])
 
 md.add_Dirichlet_condition_with_multipliers(mim, "p", mfp, IN_RG, "p_in")
-md.add_nonlinear_term\
-(mim, "1/dt*(v-v0).Test_v + (Grad_v0*v0).Test_v + nu*Grad_v:Grad_Test_v - 
f.Test_v")
-md.add_nonlinear_term\
-(mim, "Grad_p.Grad_Test_p + 1/dt*Trace(Grad_v)*Test_p")
+md.add_nonlinear_term(
+    mim, "1/dt*(v-v0).Test_v + (Grad_v0*v0).Test_v + nu*Grad_v:Grad_Test_v - 
f.Test_v"
+)
+md.add_nonlinear_term(mim, "Grad_p.Grad_Test_p + 1/dt*Trace(Grad_v)*Test_p")
 
 mmat_v = gf.asm_mass_matrix(mim, mfv)
-#mmat_v = gf.asm_generic(mim, 2, "Test2_v.Test_v", -1, "v", 1, mfv, 
np.zeros(mfv.nbdof()))
+# mmat_v = gf.asm_generic(mim, 2, "Test2_v.Test_v", -1, "v", 1, mfv, 
np.zeros(mfv.nbdof()))
 IV = md.interval_of_variable("v")
 
 t = 0
 step = 0
-while t < T+1e-8:
-   print("Solving step at t=%f" % t)
-   md.set_variable\
-   ("p_in", mfp_.eval(p_in_str.format(t), globals(), locals()).flatten("F"))
-   md.set_variable("v0", md.variable("v"))
-   md.solve("noisy", "lsolver", "mumps", "max_res", 1e-8)
-   vv = (gf.asm_generic(mim, 1, "(v-dt*Grad_p).Test_v", -1, 
md))[IV[0]:IV[0]+IV[1]]
-   md.set_variable("v", gf.linsolve_mumps(mmat_v, vv))
-
-   mfv.export_to_vtk("results_%i.vtk" % step,
-                     mfv, md.variable("v"), "Velocity",
-                     mfp, md.variable("p"), "Pressure")
-   t += dt
-   step += 1
-
+while t < T + 1e-8:
+    print("Solving step at t=%f" % t)
+    md.set_variable(
+        "p_in", mfp_.eval(p_in_str.format(t), globals(), locals()).flatten("F")
+    )
+    md.set_variable("v0", md.variable("v"))
+    md.solve("noisy", "lsolver", "mumps", "max_res", 1e-8)
+    vv = (gf.asm_generic(mim, 1, "(v-dt*Grad_p).Test_v", -1, md))[IV[0] : 
IV[0] + IV[1]]
+    md.set_variable("v", gf.linsolve_mumps(mmat_v, vv))
+
+    mfv.export_to_vtk(
+        "results_%i.vtk" % step,
+        mfv,
+        md.variable("v"),
+        "Velocity",
+        mfp,
+        md.variable("p"),
+        "Pressure",
+    )
+    t += dt
+    step += 1
diff --git a/interface/tests/python/demo_nonlinear_elasticity.py 
b/interface/tests/python/demo_nonlinear_elasticity.py
index 82ccf94..29cd9ba 100644
--- a/interface/tests/python/demo_nonlinear_elasticity.py
+++ b/interface/tests/python/demo_nonlinear_elasticity.py
@@ -27,216 +27,225 @@ from numpy import linalg as npla
 
 gf.util_trace_level(1)
 
-dirichlet_version = 2          # 1 = simplification, 2 = penalisation
-test_tangent_matrix = False    # Test or not tangent system validity
-incompressible = False;        # Incompressibility option
-explicit_potential = False;    # Elasticity law with explicit potential
+dirichlet_version = 2  # 1 = simplification, 2 = penalisation
+test_tangent_matrix = False  # Test or not tangent system validity
+incompressible = False
+# Incompressibility option
+explicit_potential = False
+# Elasticity law with explicit potential
 
 # lawname = 'Ciarlet Geymonat'
 # params = [1.,1.,0.25]
-lawname = 'SaintVenant Kirchhoff'
-params = [1.,1.]
-if (incompressible):
-    lawname = 'Incompressible Mooney Rivlin'
-    params = [1.,1.]
-
-N1 = 2; N2 = 4; h = 20.; DX = 1./N1; DY = (1.*h)/N2;
-m = gf.Mesh('cartesian', np.arange(-0.5, 0.5+DX,DX), np.arange(0., h+DY,DY),
-            np.arange(-1.5, 1.5+3*DX,3*DX))
-mfu  = gf.MeshFem(m, 3)            # mesh-fem supporting a 3D-vector field
-mfdu = gf.MeshFem(m,1)
+lawname = "SaintVenant Kirchhoff"
+params = [1.0, 1.0]
+if incompressible:
+    lawname = "Incompressible Mooney Rivlin"
+    params = [1.0, 1.0]
+
+N1 = 2
+N2 = 4
+h = 20.0
+DX = 1.0 / N1
+DY = (1.0 * h) / N2
+m = gf.Mesh(
+    "cartesian",
+    np.arange(-0.5, 0.5 + DX, DX),
+    np.arange(0.0, h + DY, DY),
+    np.arange(-1.5, 1.5 + 3 * DX, 3 * DX),
+)
+mfu = gf.MeshFem(m, 3)  # mesh-fem supporting a 3D-vector field
+mfdu = gf.MeshFem(m, 1)
 # The mesh_im stores the integration methods for each tetrahedron
-mim = gf.MeshIm(m, gf.Integ('IM_GAUSS_PARALLELEPIPED(3,4)'))
+mim = gf.MeshIm(m, gf.Integ("IM_GAUSS_PARALLELEPIPED(3,4)"))
 # We choose a P2 fem for the main unknown
-mfu.set_fem(gf.Fem('FEM_QK(3,2)'))
+mfu.set_fem(gf.Fem("FEM_QK(3,2)"))
 
-if (dirichlet_version == 1):
-  mfd = mfu;
+if dirichlet_version == 1:
+    mfd = mfu
 else:
-  mfd = gf.MeshFem(m,1)
-  mfd.set_fem(gf.Fem('FEM_QK(3,1)'))
+    mfd = gf.MeshFem(m, 1)
+    mfd.set_fem(gf.Fem("FEM_QK(3,1)"))
 
 # The P2 fem is not derivable across elements, hence we use a discontinuous
 # fem for the derivative of U.
-mfdu.set_fem(gf.Fem('FEM_QK_DISCONTINUOUS(3,2)'));
+mfdu.set_fem(gf.Fem("FEM_QK_DISCONTINUOUS(3,2)"))
 
 # Display some information about the mesh
-print('nbcvs=%d, nbpts=%d, nbdof=%d' % (m.nbcvs(), m.nbpts(), mfu.nbdof()))
+print("nbcvs=%d, nbpts=%d, nbdof=%d" % (m.nbcvs(), m.nbpts(), mfu.nbdof()))
 
 # Assign boundary numbers
 
-ftop = m.outer_faces_with_direction([0.,  1., 0.], 0.5)
-fbot = m.outer_faces_with_direction([0., -1., 0.], 0.5)
+ftop = m.outer_faces_with_direction([0.0, 1.0, 0.0], 0.5)
+fbot = m.outer_faces_with_direction([0.0, -1.0, 0.0], 0.5)
 
-m.set_region(1, ftop);
-m.set_region(2, fbot);
-m.set_region(3, np.append(ftop,fbot,axis=1));
+m.set_region(1, ftop)
+m.set_region(2, fbot)
+m.set_region(3, np.append(ftop, fbot, axis=1))
 
 # Model definition
 
-md=gf.Model('real')
-md.add_fem_variable('u', mfu)
-md.add_initialized_data('params', params)
+md = gf.Model("real")
+md.add_fem_variable("u", mfu)
+md.add_initialized_data("params", params)
 
-if (not(explicit_potential)):
-    md.add_finite_strain_elasticity_brick(mim, lawname, 'u', 'params')
+if not (explicit_potential):
+    md.add_finite_strain_elasticity_brick(mim, lawname, "u", "params")
 else:
     print("Explicit elastic potential")
-    K = 1.2; mu = 3.0;
+    K = 1.2
+    mu = 3.0
     _F_ = "(Id(3)+Grad_u)"
-    _J_= "Det{F}".format(F=_F_)
+    _J_ = "Det{F}".format(F=_F_)
     _be_ = "(Left_Cauchy_Green{F})".format(F=_F_)
 
-    _expr_1 = "{K_over_2}*sqr(log({J}))+{mu_over_2}*(Matrix_j1{be}-3)"\
-              .format(K_over_2=K/2., J=_J_, mu_over_2=mu/2., be=_be_)
+    _expr_1 = "{K_over_2}*sqr(log({J}))+{mu_over_2}*(Matrix_j1{be}-3)".format(
+        K_over_2=K / 2.0, J=_J_, mu_over_2=mu / 2.0, be=_be_
+    )
 
-    _expr_2 = 
"{K_over_2}*sqr(log({J}))+{mu_over_2}*(pow(Det{be},-1./3.)*Trace{be}-3)"\
-              .format(K_over_2=K/2., J=_J_, mu_over_2=mu/2., be=_be_)
+    _expr_2 = 
"{K_over_2}*sqr(log({J}))+{mu_over_2}*(pow(Det{be},-1./3.)*Trace{be}-3)".format(
+        K_over_2=K / 2.0, J=_J_, mu_over_2=mu / 2.0, be=_be_
+    )
 
-    md.add_nonlinear_term(mim, _expr_2);
+    md.add_nonlinear_term(mim, _expr_2)
 
 
 # md.add_nonlinear_term(mim, 
'sqr(Trace(Green_Lagrangian(Id(meshdim)+Grad_u)))/8 + 
Norm_sqr(Green_Lagrangian(Id(meshdim)+Grad_u))/4')
 # md.add_nonlinear_term(mim, 
'((Id(meshdim)+Grad_u)*(params(1)*Trace(Green_Lagrangian(Id(meshdim)+Grad_u))*Id(meshdim)+2*params(2)*Green_Lagrangian(Id(meshdim)+Grad_u))):Grad_Test_u')
 # md.add_nonlinear_term(mim, 'Saint_Venant_Kirchhoff_potential(Grad_u,params)')
-    
-if (incompressible):
-    mfp = gf.MeshFem(m,1)
+
+if incompressible:
+    mfp = gf.MeshFem(m, 1)
     mfp.set_classical_discontinuous_fem(1)
-    md.add_fem_variable('p', mfp)
-    md.add_finite_strain_incompressibility_brick(mim, 'u', 'p')
+    md.add_fem_variable("p", mfp)
+    md.add_finite_strain_incompressibility_brick(mim, "u", "p")
     # md.add_nonlinear_term(mim, 'p*(1-Det(Id(meshdim)+Grad_u))')
     # md.add_nonlinear_term(mim, 
'-p*Det(Id(meshdim)+Grad_u)*(Inv(Id(meshdim)+Grad_u))'':Grad_Test_u + 
Test_p*(1-Det(Id(meshdim)+Grad_u))')
 
 
-if (dirichlet_version == 1):
-    md.add_fem_data('DirichletData', mfu)
-    md.add_Dirichlet_condition_with_simplification('u', 3, 'DirichletData')
+if dirichlet_version == 1:
+    md.add_fem_data("DirichletData", mfu)
+    md.add_Dirichlet_condition_with_simplification("u", 3, "DirichletData")
 else:
-    md.add_fem_data('DirichletData', mfd, 3)
-    md.add_Dirichlet_condition_with_penalization(mim, 'u', 1e4, 3, 
'DirichletData')
+    md.add_fem_data("DirichletData", mfd, 3)
+    md.add_Dirichlet_condition_with_penalization(mim, "u", 1e4, 3, 
"DirichletData")
 
 
-VM=np.zeros(mfdu.nbdof());
-UU=np.zeros(0);
-VVM=np.zeros(0);
-nbstep=40;
+VM = np.zeros(mfdu.nbdof())
+UU = np.zeros(0)
+VVM = np.zeros(0)
+nbstep = 40
 
 
 P = mfd.basic_dof_nodes()
-r = np.sqrt(np.square(P[0 ,:]) + np.square(P[2, :]))
-theta = np.arctan2(P[2,:], P[0,:]);
+r = np.sqrt(np.square(P[0, :]) + np.square(P[2, :]))
+theta = np.arctan2(P[2, :], P[0, :])
 
 
 def axrot_matrix(A, B, theta):
-    n=(np.array(B)-np.array(A)); n = n/npla.norm(n)
-    a=n[0]; b=n[1]; c=n[2]
-    d=np.sqrt(b*b+c*c)
-    T=np.eye(4); T[0:3,3]=-np.array(A)
-    Rx=np.eye(4)
-    if (npla.norm(n[1:3])>1e-6):
-        Rx[1:3,1:3]=np.array([[c/d,-b/d],[b/d,c/d]])
-    Ry=np.eye(4); Ry[[[0],[2]],[0,2]]=[[d,-a],[a,d]]
-    Rz=np.eye(4)
-    Rz[0:2,0:2]=np.array([[np.cos(theta),np.sin(theta)],
-                          [-np.sin(theta),np.cos(theta)]])
-    R = np.dot(np.dot(np.dot(npla.inv(T),npla.inv(Rx)),
-                      np.dot(npla.inv(Ry),Rz)),np.dot(np.dot(Ry,Rx),T))
-    return R;
-  
-
-
-
-for step in range(1,nbstep+1):
-    w = (3.*step)/nbstep
+    n = np.array(B) - np.array(A)
+    n = n / npla.norm(n)
+    a = n[0]
+    b = n[1]
+    c = n[2]
+    d = np.sqrt(b * b + c * c)
+    T = np.eye(4)
+    T[0:3, 3] = -np.array(A)
+    Rx = np.eye(4)
+    if npla.norm(n[1:3]) > 1e-6:
+        Rx[1:3, 1:3] = np.array([[c / d, -b / d], [b / d, c / d]])
+    Ry = np.eye(4)
+    Ry[[[0], [2]], [0, 2]] = [[d, -a], [a, d]]
+    Rz = np.eye(4)
+    Rz[0:2, 0:2] = np.array(
+        [[np.cos(theta), np.sin(theta)], [-np.sin(theta), np.cos(theta)]]
+    )
+    R = np.dot(
+        np.dot(np.dot(npla.inv(T), npla.inv(Rx)), np.dot(npla.inv(Ry), Rz)),
+        np.dot(np.dot(Ry, Rx), T),
+    )
+    return R
+
+
+for step in range(1, nbstep + 1):
+    w = (3.0 * step) / nbstep
 
     # Computation of the rotation for Dirichlet's condition
-    dtheta =  np.pi
-    dtheta2 = np.pi/2.
-      
-    if (dirichlet_version == 1):
-        R=np.zeros(mfd.nbdof())
+    dtheta = np.pi
+    dtheta2 = np.pi / 2.0
+
+    if dirichlet_version == 1:
+        R = np.zeros(mfd.nbdof())
     else:
-        R=np.zeros((3, mfd.nbdof()))
-    
+        R = np.zeros((3, mfd.nbdof()))
+
     i_top = mfd.basic_dof_on_region(1)
     i_bot = mfd.basic_dof_on_region(2)
-    
-    dd = np.amax(P[1,i_top]*np.sin(w*dtheta))
-    
-    if (w < 1): 
-        RT1 = axrot_matrix([0, h*.75, 0], [0, h*.75, 1], w*dtheta)
-        RT2 = axrot_matrix([0, 0, 0], [0, 1, 0], np.sqrt(w)*dtheta2)
-        RB1 = axrot_matrix([0, h*.25, 0], [0, h*.25, 1], -w*dtheta)
+
+    dd = np.amax(P[1, i_top] * np.sin(w * dtheta))
+
+    if w < 1:
+        RT1 = axrot_matrix([0, h * 0.75, 0], [0, h * 0.75, 1], w * dtheta)
+        RT2 = axrot_matrix([0, 0, 0], [0, 1, 0], np.sqrt(w) * dtheta2)
+        RB1 = axrot_matrix([0, h * 0.25, 0], [0, h * 0.25, 1], -w * dtheta)
         RB2 = RT2.transpose()
-    elif (w < 2):
-        RT1 = axrot_matrix([0, h*.75, 0], [0, h*.75, 1], (2-w)*dtheta);
-        RT2 = axrot_matrix([0, 0, 0], [0, 1, 0], w*dtheta2);
-        RB1 = axrot_matrix([0, h*.25, 0], [0, h*.25, 1], -(2-w)*dtheta);
+    elif w < 2:
+        RT1 = axrot_matrix([0, h * 0.75, 0], [0, h * 0.75, 1], (2 - w) * 
dtheta)
+        RT2 = axrot_matrix([0, 0, 0], [0, 1, 0], w * dtheta2)
+        RB1 = axrot_matrix([0, h * 0.25, 0], [0, h * 0.25, 1], -(2 - w) * 
dtheta)
         RB2 = RT2.transpose()
     else:
-        RT1 = axrot_matrix([0, h*.75, 0], [0, h*.75, 1], 0);
-        RT2 = axrot_matrix([0, 0, 0], [0, 1, 0], (3-w)*2*dtheta2);
-        RB1 = axrot_matrix([0, h*.25, 0], [0, h*.25, 1], 0);
+        RT1 = axrot_matrix([0, h * 0.75, 0], [0, h * 0.75, 1], 0)
+        RT2 = axrot_matrix([0, 0, 0], [0, 1, 0], (3 - w) * 2 * dtheta2)
+        RB1 = axrot_matrix([0, h * 0.25, 0], [0, h * 0.25, 1], 0)
         RB2 = RT2.transpose()
 
-    if (dirichlet_version == 1):
+    if dirichlet_version == 1:
         for i in i_top:
-            ro = np.dot(RT1, np.dot(RT2,np.append(P[:,i],[1])))
-            R[i] = ro[mod(i,3)] - P[mod(i,3),i]
+            ro = np.dot(RT1, np.dot(RT2, np.append(P[:, i], [1])))
+            R[i] = ro[mod(i, 3)] - P[mod(i, 3), i]
         for i in i_bot:
-            ro = np.dot(RB1,np.dot(RB2,np.append(P[:,i],[1])))
-            R[i] = ro[mod(i,3)] - P[mod(i,3),i] 
+            ro = np.dot(RB1, np.dot(RB2, np.append(P[:, i], [1])))
+            R[i] = ro[mod(i, 3)] - P[mod(i, 3), i]
     else:
         for i in i_top:
-            ro = np.dot(RT1,np.dot(RT2,np.append(P[:,i],[1])))
-            R[:, i] = ro[0:3] - P[:,i]
+            ro = np.dot(RT1, np.dot(RT2, np.append(P[:, i], [1])))
+            R[:, i] = ro[0:3] - P[:, i]
         for i in i_bot:
-            ro = np.dot(RB1,np.dot(RB2,np.append(P[:,i],[1])))
-            R[:, i] = ro[0:3] - P[:,i]
-    
-    md.set_variable('DirichletData', R)
+            ro = np.dot(RB1, np.dot(RB2, np.append(P[:, i], [1])))
+            R[:, i] = ro[0:3] - P[:, i]
+
+    md.set_variable("DirichletData", R)
 
     # Nonlinear solve
-    md.solve('very noisy', 'max_iter', 50, 'max_res', 1e-7, 'lsearch',
-             'simplest')
+    md.solve("very noisy", "max_iter", 50, "max_res", 1e-7, "lsearch", 
"simplest")
 
     print("Iteration %d done" % step)
 
-    if (test_tangent_matrix):
-       md.test_tangent_matrix(1E-8, 10, 0.0001)
+    if test_tangent_matrix:
+        md.test_tangent_matrix(1e-8, 10, 0.0001)
 
-    U = md.variable('u')
+    U = md.variable("u")
 
-    VM0 = md.compute_Von_Mises_or_Tresca('u', lawname, 'params', mfdu)
+    VM0 = md.compute_Von_Mises_or_Tresca("u", lawname, "params", mfdu)
 
     # Direct interpolation of the Von Mises stress
     # VM = 
md.interpolation('(sqrt(3/2)/Det(Id(meshdim)+Grad_u))*Norm((Id(meshdim)+Grad_u)*Saint_Venant_Kirchhoff_PK2(Grad_u,params)*(Id(meshdim)+Grad_u'')
 - 
Id(meshdim)*Trace((Id(meshdim)+Grad_u)*Saint_Venant_Kirchhoff_PK2(Grad_u,params)*(Id(meshdim)+Grad_u''))/meshdim)',
 mfdu);
 
-    VM = md.compute_finite_strain_elasticity_Von_Mises(lawname, 'u', 'params', 
mfdu)
-    print(npla.norm(VM-VM0))
-    
-    sl=gf.Slice(('boundary',), mfu, 4)
-    sl.export_to_vtk('demo_nonlinear_elasticity_iter_%d.vtk' % step, 'ascii',
-                     mfdu,  VM, 'Von Mises Stress', mfu, U, 'Displacement')
-
-
-
-print('You can vizualize the loading steps by launching for instance')
-print('mayavi2 -d demo_nonlinear_elasticity_iter_1.vtk -f WarpVector -m 
Surface')
-
-
-
-
-
-
-
-
-
-
-
-
-
+    VM = md.compute_finite_strain_elasticity_Von_Mises(lawname, "u", "params", 
mfdu)
+    print(npla.norm(VM - VM0))
 
+    sl = gf.Slice(("boundary",), mfu, 4)
+    sl.export_to_vtk(
+        "demo_nonlinear_elasticity_iter_%d.vtk" % step,
+        "ascii",
+        mfdu,
+        VM,
+        "Von Mises Stress",
+        mfu,
+        U,
+        "Displacement",
+    )
 
 
+print("You can vizualize the loading steps by launching for instance")
+print("mayavi2 -d demo_nonlinear_elasticity_iter_1.vtk -f WarpVector -m 
Surface")
diff --git a/interface/tests/python/demo_parallel_laplacian.py 
b/interface/tests/python/demo_parallel_laplacian.py
index 5a01ed0..def0771 100644
--- a/interface/tests/python/demo_parallel_laplacian.py
+++ b/interface/tests/python/demo_parallel_laplacian.py
@@ -36,42 +36,46 @@ import getfem as gf
 import time
 
 rank = mpi.COMM_WORLD.rank
-if (rank == 0):
-  print('Running Parallel Getfem with python interface')
+if rank == 0:
+    print("Running Parallel Getfem with python interface")
 
-print('Hello from thread ', rank)
+print("Hello from thread ", rank)
 
 ## Parameters
-NX = 100                           # Mesh parameter.
+NX = 100  # Mesh parameter.
 Dirichlet_with_multipliers = True  # Dirichlet condition with multipliers
-                                   # or penalization
-dirichlet_coefficient = 1e10       # Penalization coefficient
+# or penalization
+dirichlet_coefficient = 1e10  # Penalization coefficient
 
 t = time.clock()
 
 # creation of a simple cartesian mesh
-m = gf.Mesh('regular_simplices', np.arange(0,1+1./NX,1./NX), 
np.arange(0,1+1./NX,1./NX))
-if (rank == 0):
-  print('Time for building mesh', time.clock()-t)
+m = gf.Mesh(
+    "regular_simplices",
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+)
+if rank == 0:
+    print("Time for building mesh", time.clock() - t)
 t = time.clock()
 
 # create a MeshFem for u and rhs fields of dimension 1 (i.e. a scalar field)
-mfu   = gf.MeshFem(m, 1)
+mfu = gf.MeshFem(m, 1)
 mfrhs = gf.MeshFem(m, 1)
 # assign the P2 fem to all convexes of the both MeshFem
-mfu.set_fem(gf.Fem('FEM_PK(2,2)'))
-mfrhs.set_fem(gf.Fem('FEM_PK(2,2)'))
+mfu.set_fem(gf.Fem("FEM_PK(2,2)"))
+mfrhs.set_fem(gf.Fem("FEM_PK(2,2)"))
 
 # an exact integration will be used
-mim = gf.MeshIm(m, gf.Integ('IM_TRIANGLE(4)'))
+mim = gf.MeshIm(m, gf.Integ("IM_TRIANGLE(4)"))
 
 # boundary selection
-flst  = m.outer_faces()
-fnor  = m.normal_of_faces(flst)
-tleft = abs(fnor[1,:]+1) < 1e-14
-ttop  = abs(fnor[0,:]-1) < 1e-14
+flst = m.outer_faces()
+fnor = m.normal_of_faces(flst)
+tleft = abs(fnor[1, :] + 1) < 1e-14
+ttop = abs(fnor[0, :] - 1) < 1e-14
 fleft = np.compress(tleft, flst, axis=1)
-ftop  = np.compress(ttop, flst, axis=1)
+ftop = np.compress(ttop, flst, axis=1)
 fneum = np.compress(True - ttop - tleft, flst, axis=1)
 
 # mark it as boundary
@@ -82,103 +86,102 @@ m.set_region(DIRICHLET_BOUNDARY_NUM1, fleft)
 m.set_region(DIRICHLET_BOUNDARY_NUM2, ftop)
 m.set_region(NEUMANN_BOUNDARY_NUM, fneum)
 
-if (rank == 0):
-  print('Time for building fem and im', time.clock()-t)
+if rank == 0:
+    print("Time for building fem and im", time.clock() - t)
 t = time.clock()
 
 nb_dof = mfu.nbdof()
-if (rank == 0):
-  print('Nb dof for the main unknown: ', nb_dof)
+if rank == 0:
+    print("Nb dof for the main unknown: ", nb_dof)
 
-if (rank == 0):
-  print('Time for dof numbering', time.clock()-t)
+if rank == 0:
+    print("Time for dof numbering", time.clock() - t)
 t = time.clock()
-  
+
 
 # interpolate the exact solution (Assuming mfu is a Lagrange fem)
-Ue = mfu.eval('y*(y-1)*x*(x-1)+x*x*x*x*x')
+Ue = mfu.eval("y*(y-1)*x*(x-1)+x*x*x*x*x")
 
 # interpolate the source term
-F1 = mfrhs.eval('-(2*(x*x+y*y)-2*x-2*y+20*x*x*x)')
-F2 = mfrhs.eval('[y*(y-1)*(2*x-1) + 5*x*x*x*x, x*(x-1)*(2*y-1)]')
+F1 = mfrhs.eval("-(2*(x*x+y*y)-2*x-2*y+20*x*x*x)")
+F2 = mfrhs.eval("[y*(y-1)*(2*x-1) + 5*x*x*x*x, x*(x-1)*(2*y-1)]")
 
-if (rank == 0):
-  print('Time for python interpolation', time.clock()-t)
+if rank == 0:
+    print("Time for python interpolation", time.clock() - t)
 t = time.clock()
 
 # model
-md = gf.Model('real')
+md = gf.Model("real")
 
 # main unknown
-md.add_fem_variable('u', mfu)
+md.add_fem_variable("u", mfu)
 
 # laplacian term on u
-md.add_Laplacian_brick(mim, 'u')
+md.add_Laplacian_brick(mim, "u")
 
 # volumic source term
-md.add_initialized_fem_data('VolumicData', mfrhs, F1)
-md.add_source_term_brick(mim, 'u', 'VolumicData')
+md.add_initialized_fem_data("VolumicData", mfrhs, F1)
+md.add_source_term_brick(mim, "u", "VolumicData")
 
 # Neumann condition.
-md.add_initialized_fem_data('NeumannData', mfrhs, F2)
-md.add_normal_source_term_brick(mim, 'u', 'NeumannData',
-                                NEUMANN_BOUNDARY_NUM)
+md.add_initialized_fem_data("NeumannData", mfrhs, F2)
+md.add_normal_source_term_brick(mim, "u", "NeumannData", NEUMANN_BOUNDARY_NUM)
 
 # Dirichlet condition on the left.
 md.add_initialized_fem_data("DirichletData", mfu, Ue)
 
-if (Dirichlet_with_multipliers):
-  md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu,
-                                              DIRICHLET_BOUNDARY_NUM1,
-                                              'DirichletData')
+if Dirichlet_with_multipliers:
+    md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfu, DIRICHLET_BOUNDARY_NUM1, "DirichletData"
+    )
 else:
-  md.add_Dirichlet_condition_with_penalization(mim, 'u', dirichlet_coefficient,
-                                               DIRICHLET_BOUNDARY_NUM1,
-                                               'DirichletData')
+    md.add_Dirichlet_condition_with_penalization(
+        mim, "u", dirichlet_coefficient, DIRICHLET_BOUNDARY_NUM1, 
"DirichletData"
+    )
 
 # Dirichlet condition on the top.
 # Two Dirichlet brick in order to test the multiplier
 # selection in the intersection.
-if (Dirichlet_with_multipliers):
-  md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu,
-                                              DIRICHLET_BOUNDARY_NUM2,
-                                              'DirichletData')
+if Dirichlet_with_multipliers:
+    md.add_Dirichlet_condition_with_multipliers(
+        mim, "u", mfu, DIRICHLET_BOUNDARY_NUM2, "DirichletData"
+    )
 else:
-  md.add_Dirichlet_condition_with_penalization(mim, 'u', dirichlet_coefficient,
-                                               DIRICHLET_BOUNDARY_NUM2,
-                                               'DirichletData')
+    md.add_Dirichlet_condition_with_penalization(
+        mim, "u", dirichlet_coefficient, DIRICHLET_BOUNDARY_NUM2, 
"DirichletData"
+    )
 
-if (rank == 0):
-  print('Time for model building', time.clock()-t)
+if rank == 0:
+    print("Time for model building", time.clock() - t)
 t = time.clock()
 
 md.nbdof
 nb_dof = md.nbdof()
-if (rank == 0):
-  print('Nb dof for the model: ', nb_dof)
+if rank == 0:
+    print("Nb dof for the model: ", nb_dof)
 
-if (rank == 0):
-  print('Time for model actualize sizes', time.clock()-t)
+if rank == 0:
+    print("Time for model actualize sizes", time.clock() - t)
 t = time.clock()
 
 # assembly of the linear system and solve.
 md.solve()
 
-if (rank == 0):
-  print('Time for model solve', time.clock()-t)
+if rank == 0:
+    print("Time for model solve", time.clock() - t)
 t = time.clock()
 
 # main unknown
-U = md.variable('u')
-L2error = gf.compute(mfu, U-Ue, 'L2 norm', mim)
-H1error = gf.compute(mfu, U-Ue, 'H1 norm', mim)
+U = md.variable("u")
+L2error = gf.compute(mfu, U - Ue, "L2 norm", mim)
+H1error = gf.compute(mfu, U - Ue, "H1 norm", mim)
 
-if (rank == 0):
-  print('Error in L2 norm : ', L2error)
-  print('Error in H1 norm : ', H1error)
+if rank == 0:
+    print("Error in L2 norm : ", L2error)
+    print("Error in H1 norm : ", H1error)
 
-if (rank == 0):
-  print('Time for error computation', time.clock()-t)
+if rank == 0:
+    print("Time for error computation", time.clock() - t)
 t = time.clock()
 
 
@@ -188,4 +191,3 @@ t = time.clock()
 #                     U,'Computed solution')
 #   print('You can view the solution with (for example):')
 #   print('gmsh laplacian.pos')
-
diff --git a/interface/tests/python/demo_phase_field.py 
b/interface/tests/python/demo_phase_field.py
index c74ec26..0dd812b 100644
--- a/interface/tests/python/demo_phase_field.py
+++ b/interface/tests/python/demo_phase_field.py
@@ -28,71 +28,85 @@ np.set_printoptions(threshold=np.nan)
 gf.util_trace_level(1)
 
 # Input data
-NX = 60         # number of elements in horizontal direction
-NY = 60         # number of elements in verical direction
+NX = 60  # number of elements in horizontal direction
+NY = 60  # number of elements in verical direction
 
-LX = 1.         # [mm] Length
-LY = 1.         # [mm] Height
+LX = 1.0  # [mm] Length
+LY = 1.0  # [mm] Height
 
-E = 210e3       # [N/mm^2]
+E = 210e3  # [N/mm^2]
 nu = 0.3
 
-Gc0 = 2.7e0     # [N/mm]
+Gc0 = 2.7e0  # [N/mm]
 
-ll = 0.015      # [mm] length scale
+ll = 0.015  # [mm] length scale
 
 strain_rate = 2e-4
-init_time_step = 1.
+init_time_step = 1.0
 
 steps = 100
 
-#------------------------------------
+# ------------------------------------
 geotrans = "GT_QK(2,2)"  # geometric transformation
-disp_fem_order = 2       # displacements finite element order
-phi_fem_order = 2        # phase field finite element order
+disp_fem_order = 2  # displacements finite element order
+phi_fem_order = 2  # phase field finite element order
 
-integration_degree = 5   # 9 gauss points per quad
+integration_degree = 5  # 9 gauss points per quad
 
-#------------------------------------
+# ------------------------------------
 
-NX = 2*((NX+1)/2)
-NY = 2*((NY+1)/2)
+NX = 2 * ((NX + 1) / 2)
+NY = 2 * ((NY + 1) / 2)
 
 resultspath = "./demo_phase_field_results"
 if not os.path.exists(resultspath):
-   os.makedirs(resultspath)
+    os.makedirs(resultspath)
 
 # auxiliary constants
 B_BOUNDARY = 4
 T_BOUNDARY = 6
 TB_BOUNDARY = 7
 
-NX_seed1 = np.linspace(-1, 0, NX/3+1)
-NX_seed2 = np.linspace(0, 1, (NX-NX/3)+1)[1:]
-NY_seed = np.linspace(-1, 1, NY+1)
-X_seed1 = 
LX/2*(0.2*NX_seed1+0.8*np.sign(NX_seed1)*np.power(np.abs(NX_seed1),1.5))
-X_seed2 = 
LX/2*(0.6*NX_seed2+0.4*np.sign(NX_seed2)*np.power(np.abs(NX_seed2),1.5))
-X_seed = np.concatenate((X_seed1,X_seed2))
-Y_seed = LY/2*(0.2*NY_seed+0.8*np.sign(NY_seed)*np.power(np.abs(NY_seed),1.5))
-m1 = gf.Mesh("cartesian", X_seed, Y_seed[0:NY/2+1])
-m2 = gf.Mesh("cartesian", X_seed, Y_seed[NY/2:])
+NX_seed1 = np.linspace(-1, 0, NX / 3 + 1)
+NX_seed2 = np.linspace(0, 1, (NX - NX / 3) + 1)[1:]
+NY_seed = np.linspace(-1, 1, NY + 1)
+X_seed1 = (
+    LX
+    / 2
+    * (0.2 * NX_seed1 + 0.8 * np.sign(NX_seed1) * np.power(np.abs(NX_seed1), 
1.5))
+)
+X_seed2 = (
+    LX
+    / 2
+    * (0.6 * NX_seed2 + 0.4 * np.sign(NX_seed2) * np.power(np.abs(NX_seed2), 
1.5))
+)
+X_seed = np.concatenate((X_seed1, X_seed2))
+Y_seed = (
+    LY / 2 * (0.2 * NY_seed + 0.8 * np.sign(NY_seed) * 
np.power(np.abs(NY_seed), 1.5))
+)
+m1 = gf.Mesh("cartesian", X_seed, Y_seed[0 : NY / 2 + 1])
+m2 = gf.Mesh("cartesian", X_seed, Y_seed[NY / 2 :])
 gap = 1e-5
 pts = m1.pts()
 for i in range(pts.shape[1]):
-  if pts[0,i] < -1e-10:
-    pts[1,i] -=  gap/2*(1+pts[1,i]/(LY/2))
+    if pts[0, i] < -1e-10:
+        pts[1, i] -= gap / 2 * (1 + pts[1, i] / (LY / 2))
 m1.set_pts(pts)
 pts = m2.pts()
 for i in range(pts.shape[1]):
-  if pts[0,i] < -1e-10:
-    pts[1,i] +=  gap/2*(1-pts[1,i]/(LY/2))
+    if pts[0, i] < -1e-10:
+        pts[1, i] += gap / 2 * (1 - pts[1, i] / (LY / 2))
 m2.set_pts(pts)
 mesh = m1
 mesh.merge(m2)
 N = mesh.dim()
 
-bottom_faces = 
mesh.outer_faces_in_box([-LX/2-1e-5,-LY/2-1e-5],[LX/2+1e-5,-LY/2+1e-5])
-top_faces = 
mesh.outer_faces_in_box([-LX/2-1e-5,LY/2-1e-5],[LX/2+1e-5,LY/2+1e-5])
+bottom_faces = mesh.outer_faces_in_box(
+    [-LX / 2 - 1e-5, -LY / 2 - 1e-5], [LX / 2 + 1e-5, -LY / 2 + 1e-5]
+)
+top_faces = mesh.outer_faces_in_box(
+    [-LX / 2 - 1e-5, LY / 2 - 1e-5], [LX / 2 + 1e-5, LY / 2 + 1e-5]
+)
 
 mesh.set_region(B_BOUNDARY, bottom_faces)
 mesh.set_region(T_BOUNDARY, top_faces)
@@ -120,34 +134,42 @@ mimd1 = gf.MeshImData(mim, -1)
 # Model
 md = gf.Model("real")
 
-md.add_fem_variable("u", mfu)          # displacements
-md.add_fem_variable("phi", mfphi)      # phase field
+md.add_fem_variable("u", mfu)  # displacements
+md.add_fem_variable("phi", mfphi)  # phase field
 
 md.add_fem_data("u_stored", mfu)
 md.add_fem_data("phi_stored", mfphi)
 
 md.add_im_data("psi0_max", mimd1)
 
-md.add_initialized_data("kappa", E/(3.*(1.-2.*nu)))
-md.add_initialized_data("mu", E/(2*(1+nu)))
+md.add_initialized_data("kappa", E / (3.0 * (1.0 - 2.0 * nu)))
+md.add_initialized_data("mu", E / (2 * (1 + nu)))
 
 md.add_initialized_data("Gc0", Gc0)
 md.add_initialized_data("l", ll)
 
 md.add_macro("damage", "max(1e-7,sqr(1-phi))")
-md.add_macro("psi0", 
"(0.5*kappa*sqr(Trace(Grad_u))+mu*Norm_sqr((Sym(Grad_u)-Trace(Grad_u)/3*Id(2))))")
+md.add_macro(
+    "psi0",
+    
"(0.5*kappa*sqr(Trace(Grad_u))+mu*Norm_sqr((Sym(Grad_u)-Trace(Grad_u)/3*Id(2))))",
+)
 md.add_macro("Gc", "Gc0")
 
 _sigma_ = 
"damage*(kappa*Trace(Grad_u)*Id(2)+2*mu*(Sym(Grad_u)-Trace(Grad_u)/3*Id(2)))"
-md.add_nonlinear_term(mim, _sigma_+":Grad_Test_u")
-md.add_nonlinear_term(mim, 
"(-2*(1-phi)*max(psi0_max,psi0)*Test_phi+Gc*(phi/l*Test_phi+l*Grad_phi.Grad_Test_phi))")
+md.add_nonlinear_term(mim, _sigma_ + ":Grad_Test_u")
+md.add_nonlinear_term(
+    mim,
+    
"(-2*(1-phi)*max(psi0_max,psi0)*Test_phi+Gc*(phi/l*Test_phi+l*Grad_phi.Grad_Test_phi))",
+)
 
 md.add_initialized_data("MM", 0)
 md.add_nonlinear_term(mim, 
"MM*((u-u_stored).Test_u+1e2*(phi-phi_stored)*Test_phi)")
 
 # Load
-md.add_fem_data("dirichlet_data", mfu);
-ibdir = md.add_Dirichlet_condition_with_multipliers(mim, "u", mfdir, 
TB_BOUNDARY, "dirichlet_data")
+md.add_fem_data("dirichlet_data", mfu)
+ibdir = md.add_Dirichlet_condition_with_multipliers(
+    mim, "u", mfdir, TB_BOUNDARY, "dirichlet_data"
+)
 dirmultname = md.mult_varname_Dirichlet(ibdir)
 
 mass_mat = gf.asm_mass_matrix(mim, mfout)
@@ -156,79 +178,104 @@ print("Displacement dofs: %i" % mfu.nbdof())
 print("Total model dofs: %i" % md.nbdof())
 
 time_step = init_time_step
-eps = 0.
+eps = 0.0
 pseudodynamic = False
-MM = 0.
+MM = 0.0
 with open("%s/demo_phase_field_forces.dat" % resultspath, "w") as f:
-  for step in range(steps):
-    eps_old = eps
-    while True:
-      if step > 0:
-        eps = eps_old + strain_rate*time_step
-
-      X = md.from_variables()
-      print("Step %i with eps=%e" % (step, eps))
-      md.set_variable("dirichlet_data", 
md.interpolation("{eps}*[0;X(2)]".format(eps=eps), mfu, -1))
-      if pseudodynamic:
-        print("With damping %e" % MM)
-      md.set_variable("MM",[MM])
-
-      iters = 20
-      try:
-        nit = \
-        md.solve("noisy", "lsolver", "mumps", "max_iter", iters, "max_res", 
1e-7, #)[0]
-                 "lsearch", "simplest", "alpha max ratio", 1.5, "alpha min", 
0.4, "alpha mult", 0.6,
-                  "alpha threshold res", 2)[0]
-      except (KeyboardInterrupt, SystemExit):
-        raise
-      except:
-        nit = iters
-
-      if nit >= iters:
-        if step == 0:
-          break
-        md.to_variables(X)
-        eps = eps_old
-        if time_step > init_time_step/50.:
-          time_step *= 0.5
-        else:
-          if pseudodynamic:
-            MM *= 100.
-          else:
-            pseudodynamic = True
-            MM = 10000.
-      else:
-        md.set_variable("u_stored", md.variable("u"))
-        md.set_variable("phi_stored", md.variable("phi"))
-        if pseudodynamic:
-          if MM < 1e-4:
-            MM = 0.
-            pseudodynamic = False
-          elif nit <= 6:
-            MM /= 2.
-        else:
-          TMP = md.interpolation("max(psi0_max,psi0)", mimd1, -1)
-          md.set_variable("psi0_max", TMP)
-          break
-
-    out = (mfu, md.variable("u"), "Displacements",
-           mfphi, md.variable("phi"), "phi")
-    for i,j in [[1,1],[2,2],[1,2]]:
-      sigma = gf.asm_generic(mim, 1, 
"{sigma}({i},{j})*Test_t".format(sigma=_sigma_, i=i, j=j),
-                             -1, md, "t", True, mfout, 
np.zeros(mfout.nbdof()))\
-              [md.nbdof():]
-      sigma = np.transpose(gf.linsolve_mumps(mass_mat, sigma))
-      out += (mfout, sigma, "Cauchy Stress {i}{j}".format(i=i, j=j))
-
-    mfout.export_to_vtk("%s/demo_phase_field_%i.vtk" % (resultspath, step), 
*out)
-
-    DIRMULT = -md.variable(dirmultname)
-    DIRMULT = np.reshape(DIRMULT,[1,DIRMULT.size])
-    dfT = gf.asm_boundary_source(T_BOUNDARY, mim, mfu, 
md.mesh_fem_of_variable(dirmultname), DIRMULT)
-    f.write(("step=%i eps=%e fR=(%e,%e)\n") %
-            (step, eps, dfT[0::N].sum(), dfT[1::N].sum()))
-    f.flush()
-
-
-
-
+    for step in range(steps):
+        eps_old = eps
+        while True:
+            if step > 0:
+                eps = eps_old + strain_rate * time_step
+
+            X = md.from_variables()
+            print("Step %i with eps=%e" % (step, eps))
+            md.set_variable(
+                "dirichlet_data",
+                md.interpolation("{eps}*[0;X(2)]".format(eps=eps), mfu, -1),
+            )
+            if pseudodynamic:
+                print("With damping %e" % MM)
+            md.set_variable("MM", [MM])
+
+            iters = 20
+            try:
+                nit = md.solve(
+                    "noisy",
+                    "lsolver",
+                    "mumps",
+                    "max_iter",
+                    iters,
+                    "max_res",
+                    1e-7,  # )[0]
+                    "lsearch",
+                    "simplest",
+                    "alpha max ratio",
+                    1.5,
+                    "alpha min",
+                    0.4,
+                    "alpha mult",
+                    0.6,
+                    "alpha threshold res",
+                    2,
+                )[0]
+            except (KeyboardInterrupt, SystemExit):
+                raise
+            except:
+                nit = iters
+
+            if nit >= iters:
+                if step == 0:
+                    break
+                md.to_variables(X)
+                eps = eps_old
+                if time_step > init_time_step / 50.0:
+                    time_step *= 0.5
+                else:
+                    if pseudodynamic:
+                        MM *= 100.0
+                    else:
+                        pseudodynamic = True
+                        MM = 10000.0
+            else:
+                md.set_variable("u_stored", md.variable("u"))
+                md.set_variable("phi_stored", md.variable("phi"))
+                if pseudodynamic:
+                    if MM < 1e-4:
+                        MM = 0.0
+                        pseudodynamic = False
+                    elif nit <= 6:
+                        MM /= 2.0
+                else:
+                    TMP = md.interpolation("max(psi0_max,psi0)", mimd1, -1)
+                    md.set_variable("psi0_max", TMP)
+                    break
+
+        out = (mfu, md.variable("u"), "Displacements", mfphi, 
md.variable("phi"), "phi")
+        for i, j in [[1, 1], [2, 2], [1, 2]]:
+            sigma = gf.asm_generic(
+                mim,
+                1,
+                "{sigma}({i},{j})*Test_t".format(sigma=_sigma_, i=i, j=j),
+                -1,
+                md,
+                "t",
+                True,
+                mfout,
+                np.zeros(mfout.nbdof()),
+            )[md.nbdof() :]
+            sigma = np.transpose(gf.linsolve_mumps(mass_mat, sigma))
+            out += (mfout, sigma, "Cauchy Stress {i}{j}".format(i=i, j=j))
+
+        mfout.export_to_vtk("%s/demo_phase_field_%i.vtk" % (resultspath, 
step), *out)
+
+        DIRMULT = -md.variable(dirmultname)
+        DIRMULT = np.reshape(DIRMULT, [1, DIRMULT.size])
+        dfT = gf.asm_boundary_source(
+            T_BOUNDARY, mim, mfu, md.mesh_fem_of_variable(dirmultname), DIRMULT
+        )
+        f.write(
+            ("step=%i eps=%e fR=(%e,%e)\n")
+            % (step, eps, dfT[0::N].sum(), dfT[1::N].sum())
+        )
+        f.flush()
diff --git a/interface/tests/python/demo_plasticity.py 
b/interface/tests/python/demo_plasticity.py
index d411aae..39ef250 100644
--- a/interface/tests/python/demo_plasticity.py
+++ b/interface/tests/python/demo_plasticity.py
@@ -32,84 +32,123 @@ import getfem as gf
 import numpy as np
 
 
-with_graphics=False
+with_graphics = False
 try:
     import getfem_tvtk
 except:
     print("\n** Could NOT import getfem_tvtk -- graphical output disabled 
**\n")
     import time
+
     time.sleep(2)
-    with_graphics=False
+    with_graphics = False
 
-L=100
-H=20
+L = 100
+H = 20
 
-gf.util('trace_level', 1);
+gf.util("trace_level", 1)
 
-m=gf.Mesh('triangles grid', np.arange(0, L + 0.01, 4), np.arange(0, H + 0.01, 
2))
+m = gf.Mesh("triangles grid", np.arange(0, L + 0.01, 4), np.arange(0, H + 
0.01, 2))
 
-mim=gf.MeshIm(m, gf.Integ('IM_TRIANGLE(6)'))
+mim = gf.MeshIm(m, gf.Integ("IM_TRIANGLE(6)"))
 mim_data = gf.MeshImData(mim, -1, [2, 2])
-mfu=gf.MeshFem(m,2)
-mfxi=gf.MeshFem(m,1)
-mfd=gf.MeshFem(m)
-mfdu=gf.MeshFem(m)
+mfu = gf.MeshFem(m, 2)
+mfxi = gf.MeshFem(m, 1)
+mfd = gf.MeshFem(m)
+mfdu = gf.MeshFem(m)
 
-mfu.set_fem(gf.Fem('FEM_PK(2,2)'))
-mfxi.set_fem(gf.Fem('FEM_PK_DISCONTINUOUS(2,2)'))
-mfd.set_fem(gf.Fem('FEM_PK(2,2)'))
-mfdu.set_fem(gf.Fem('FEM_PK_DISCONTINUOUS(2,1)'))
+mfu.set_fem(gf.Fem("FEM_PK(2,2)"))
+mfxi.set_fem(gf.Fem("FEM_PK_DISCONTINUOUS(2,2)"))
+mfd.set_fem(gf.Fem("FEM_PK(2,2)"))
+mfdu.set_fem(gf.Fem("FEM_PK_DISCONTINUOUS(2,1)"))
 
-Lambda=121150
-Mu=80769
-sigma_y=4000
+Lambda = 121150
+Mu = 80769
+sigma_y = 4000
 
-P=m.pts()
-pidleft=np.compress((abs(P[0,:])<1e-6), list(range(0, m.nbpts())))
-pidright=np.compress((abs(P[0,:] - L)<1e-6), list(range(0, m.nbpts())))
+P = m.pts()
+pidleft = np.compress((abs(P[0, :]) < 1e-6), list(range(0, m.nbpts())))
+pidright = np.compress((abs(P[0, :] - L) < 1e-6), list(range(0, m.nbpts())))
 
-fleft  = m.faces_from_pid(pidleft)
+fleft = m.faces_from_pid(pidleft)
 fright = m.faces_from_pid(pidright)
 
 # assign boundary numbers
-m.set_region(1,fleft)
-m.set_region(2,fright)
-
-md = gf.Model('real')
-md.add_fem_variable('u', mfu)
-md.add_fem_data('Previous_u', mfu)
-md.add_im_data('Previous_Ep', mim_data)
-md.add_fem_data('xi', mfxi)
-md.add_fem_data('Previous_xi', mfxi)
-md.add_initialized_data('lambda', Lambda)
-md.add_initialized_data('mu', Mu)
-md.add_initialized_data('sigma_y', sigma_y)
-md.add_small_strain_elastoplasticity_brick(mim, 'plane strain Prandtl Reuss',
-                                           'displacement only', 'u', 'xi', 
'Previous_Ep', 'lambda', 'mu', 'sigma_y')
-md.add_initialized_data('VolumicData', [0,0])
-md.add_source_term_brick(mim, 'u', 'VolumicData')
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, 1)
-
-
-F=np.array([[0,-4.],[0, -5.], [0, -4.], [0, 2.], [0, 0]])
+m.set_region(1, fleft)
+m.set_region(2, fright)
+
+md = gf.Model("real")
+md.add_fem_variable("u", mfu)
+md.add_fem_data("Previous_u", mfu)
+md.add_im_data("Previous_Ep", mim_data)
+md.add_fem_data("xi", mfxi)
+md.add_fem_data("Previous_xi", mfxi)
+md.add_initialized_data("lambda", Lambda)
+md.add_initialized_data("mu", Mu)
+md.add_initialized_data("sigma_y", sigma_y)
+md.add_small_strain_elastoplasticity_brick(
+    mim,
+    "plane strain Prandtl Reuss",
+    "displacement only",
+    "u",
+    "xi",
+    "Previous_Ep",
+    "lambda",
+    "mu",
+    "sigma_y",
+)
+md.add_initialized_data("VolumicData", [0, 0])
+md.add_source_term_brick(mim, "u", "VolumicData")
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, 1)
+
+
+F = np.array([[0, -4.0], [0, -5.0], [0, -4.0], [0, 2.0], [0, 0]])
 nbstep = F.shape[0]
 
-print('nbstep:', nbstep)
+print("nbstep:", nbstep)
 for step in range(0, nbstep):
-    print('step %d' % (step,))
-    md.set_variable('VolumicData', [F[step,0],F[step,1]])
-    md.solve('noisy', 'lsearch', 'simplest',  'alpha min', 0.8, 'max_iter', 
100, 'max_res', 1e-6)
-    U = md.variable('u')
-    md.small_strain_elastoplasticity_next_iter\
-      (mim, 'plane strain Prandtl Reuss', 'displacement only', 'u', 'xi', 
'Previous_Ep', 'lambda', 'mu', 'sigma_y')
-    
-    VM = md.small_strain_elastoplasticity_Von_Mises\
-         (mim, mfdu, 'plane strain Prandtl Reuss', 'displacement only', 'u', 
'xi', 'Previous_Ep', 'lambda', 'mu', 'sigma_y')
+    print("step %d" % (step,))
+    md.set_variable("VolumicData", [F[step, 0], F[step, 1]])
+    md.solve(
+        "noisy",
+        "lsearch",
+        "simplest",
+        "alpha min",
+        0.8,
+        "max_iter",
+        100,
+        "max_res",
+        1e-6,
+    )
+    U = md.variable("u")
+    md.small_strain_elastoplasticity_next_iter(
+        mim,
+        "plane strain Prandtl Reuss",
+        "displacement only",
+        "u",
+        "xi",
+        "Previous_Ep",
+        "lambda",
+        "mu",
+        "sigma_y",
+    )
+
+    VM = md.small_strain_elastoplasticity_Von_Mises(
+        mim,
+        mfdu,
+        "plane strain Prandtl Reuss",
+        "displacement only",
+        "u",
+        "xi",
+        "Previous_Ep",
+        "lambda",
+        "mu",
+        "sigma_y",
+    )
 
     ERR = gf.compute_error_estimate(mfu, U, mim)
 
     if with_graphics:
         fig = getfem_tvtk.Figure()
-        fig.show(mfu, deformation=U, deformation_scale=1, data=(mfdu,VM))
+        fig.show(mfu, deformation=U, deformation_scale=1, data=(mfdu, VM))
         print("Press Q to continue..")
         fig.loop()
diff --git a/interface/tests/python/demo_plate.py 
b/interface/tests/python/demo_plate.py
index d8a26ce..84b988a 100644
--- a/interface/tests/python/demo_plate.py
+++ b/interface/tests/python/demo_plate.py
@@ -30,67 +30,67 @@ import getfem as gf
 import numpy as np
 
 
-NX=10.0
-thickness = 0.01;
-f = -5.*pow(thickness,3.);
+NX = 10.0
+thickness = 0.01
+f = -5.0 * pow(thickness, 3.0)
 
-m=gf.Mesh('regular simplices', np.arange(0,1.01,1/NX), np.arange(0,1.01,1/NX))
-mfu3 = gf.MeshFem(m,1)
-mfth = gf.MeshFem(m,2)
-mfd  = gf.MeshFem(m,1)
+m = gf.Mesh("regular simplices", np.arange(0, 1.01, 1 / NX), np.arange(0, 
1.01, 1 / NX))
+mfu3 = gf.MeshFem(m, 1)
+mfth = gf.MeshFem(m, 2)
+mfd = gf.MeshFem(m, 1)
 
-mfu3.set_fem(gf.Fem('FEM_PK(2,1)'))
-mfth.set_fem(gf.Fem('FEM_PK(2,2)'))
-mfd.set_fem(gf.Fem('FEM_PK(2,2)'))
+mfu3.set_fem(gf.Fem("FEM_PK(2,1)"))
+mfth.set_fem(gf.Fem("FEM_PK(2,2)"))
+mfd.set_fem(gf.Fem("FEM_PK(2,2)"))
 
-mim = gf.MeshIm(m, gf.Integ('IM_TRIANGLE(5)'))
+mim = gf.MeshIm(m, gf.Integ("IM_TRIANGLE(5)"))
 
 
-#get the list of faces whose normal is [-1,0]
-flst = m.outer_faces();
-fnor = m.normal_of_faces(flst);
-fleft = np.compress(abs(fnor[1,:]+1) < 1e-14, flst, axis=1);
-fright= np.compress(abs(fnor[1,:]-1) < 1e-14, flst, axis=1);
-CLAMPED_BOUNDARY = 1;
-m.set_region(CLAMPED_BOUNDARY, fleft);
+# get the list of faces whose normal is [-1,0]
+flst = m.outer_faces()
+fnor = m.normal_of_faces(flst)
+fleft = np.compress(abs(fnor[1, :] + 1) < 1e-14, flst, axis=1)
+fright = np.compress(abs(fnor[1, :] - 1) < 1e-14, flst, axis=1)
+CLAMPED_BOUNDARY = 1
+m.set_region(CLAMPED_BOUNDARY, fleft)
 SIMPLE_SUPPORT_BOUNDARY = 2
-m.set_region(SIMPLE_SUPPORT_BOUNDARY, fright);
+m.set_region(SIMPLE_SUPPORT_BOUNDARY, fright)
 
-E=1e3
-Nu=0.3
+E = 1e3
+Nu = 0.3
 
 
-md = gf.Model('real')
-md.add_fem_variable('u3', mfu3)
-md.add_fem_variable('theta', mfth)
-md.add_initialized_data('E', E)
-md.add_initialized_data('nu', Nu)
-md.add_initialized_data('epsilon', thickness)
-md.add_initialized_data('kappa', 5./6.)
-md.add_Mindlin_Reissner_plate_brick(mim, mim, 'u3', 'theta', 'E', 'nu', 
'epsilon', 'kappa', 2)
-md.add_initialized_data('VolumicData', f)
-md.add_source_term_brick(mim, 'u3', 'VolumicData')
+md = gf.Model("real")
+md.add_fem_variable("u3", mfu3)
+md.add_fem_variable("theta", mfth)
+md.add_initialized_data("E", E)
+md.add_initialized_data("nu", Nu)
+md.add_initialized_data("epsilon", thickness)
+md.add_initialized_data("kappa", 5.0 / 6.0)
+md.add_Mindlin_Reissner_plate_brick(
+    mim, mim, "u3", "theta", "E", "nu", "epsilon", "kappa", 2
+)
+md.add_initialized_data("VolumicData", f)
+md.add_source_term_brick(mim, "u3", "VolumicData")
 
-md.add_Dirichlet_condition_with_multipliers(mim, 'u3', mfu3, CLAMPED_BOUNDARY);
-md.add_Dirichlet_condition_with_multipliers(mim, 'theta', mfth, 
CLAMPED_BOUNDARY);
-md.add_Dirichlet_condition_with_multipliers(mim, 'u3', mfu3, 
SIMPLE_SUPPORT_BOUNDARY);
-                                              
-                                             
+md.add_Dirichlet_condition_with_multipliers(mim, "u3", mfu3, CLAMPED_BOUNDARY)
+md.add_Dirichlet_condition_with_multipliers(mim, "theta", mfth, 
CLAMPED_BOUNDARY)
+md.add_Dirichlet_condition_with_multipliers(mim, "u3", mfu3, 
SIMPLE_SUPPORT_BOUNDARY)
 
 
-print('running solve...')
+print("running solve...")
 md.solve()
-print('solve done!')
+print("solve done!")
 
 
-u3 = md.variable('u3')
+u3 = md.variable("u3")
 
 
-sl=gf.Slice(('none',), mfu3, 4)
-sl.export_to_vtk('plate.vtk', mfu3, u3, 'Displacement')
-sl.export_to_pos('plate.pos', mfu3, u3, 'Displacement')
+sl = gf.Slice(("none",), mfu3, 4)
+sl.export_to_vtk("plate.vtk", mfu3, u3, "Displacement")
+sl.export_to_pos("plate.pos", mfu3, u3, "Displacement")
 
-print('You can view the solution with (for example):')
-print('mayavi2 -d plate.vtk -f WarpScalar -m Surface')
-print('or')
-print('gmsh plate.pos')
+print("You can view the solution with (for example):")
+print("mayavi2 -d plate.vtk -f WarpScalar -m Surface")
+print("or")
+print("gmsh plate.pos")
diff --git a/interface/tests/python/demo_static_contact.py 
b/interface/tests/python/demo_static_contact.py
index 17e0808..ac1a034 100644
--- a/interface/tests/python/demo_static_contact.py
+++ b/interface/tests/python/demo_static_contact.py
@@ -31,7 +31,7 @@ import numpy as np
 
 # Import the mesh : disc
 # m = gf.Mesh('load', '../../../tests/meshes/disc_P2_h4.mesh')
-#m = gf.Mesh('load', '../../../tests/meshes/disc_P2_h2.mesh')
+# m = gf.Mesh('load', '../../../tests/meshes/disc_P2_h2.mesh')
 # m = gf.Mesh('load', '../../../tests/meshes/disc_P2_h1.mesh')
 # m = gf.Mesh('load', '../../../tests/meshes/disc_P2_h0_5.mesh')
 # m = gf.Mesh('load', '../../../tests/meshes/disc_P2_h0_3.mesh')
@@ -39,71 +39,71 @@ import numpy as np
 # Import the mesh : sphere
 # m = gf.Mesh('load', 
'../../../tests/meshes/sphere_with_quadratic_tetra_8_elts.mesh')
 # m = gf.Mesh('load', 
'../../../tests/meshes/sphere_with_quadratic_tetra_80_elts.mesh')
-m = gf.Mesh('load', 
'../../../tests/meshes/sphere_with_quadratic_tetra_400_elts.mesh')
+m = gf.Mesh("load", 
"../../../tests/meshes/sphere_with_quadratic_tetra_400_elts.mesh")
 # m = gf.Mesh('load', 
'../../../tests/meshes/sphere_with_quadratic_tetra_2000_elts.mesh')
 # m = gf.Mesh('load', 
'../../../tests/meshes/sphere_with_quadratic_tetra_16000_elts.mesh')
 
-d = m.dim() # Mesh dimension
+d = m.dim()  # Mesh dimension
 
 # Parameters of the model
-clambda = 1.          # Lame coefficient
-cmu = 1.              # Lame coefficient
+clambda = 1.0  # Lame coefficient
+cmu = 1.0  # Lame coefficient
 friction_coeff = 0.4  # coefficient of friction
-vertical_force = 0.05 # Volumic load in the vertical direction
-r = 10.               # Augmentation parameter
-condition_type = 0 # 0 = Explicitely kill horizontal rigid displacements
-                   # 1 = Kill rigid displacements using a global penalization
-                   # 2 = Add a Dirichlet condition on the top of the structure
-penalty_parameter = 1E-6    # Penalization coefficient for the global 
penalization
+vertical_force = 0.05  # Volumic load in the vertical direction
+r = 10.0  # Augmentation parameter
+condition_type = 0  # 0 = Explicitely kill horizontal rigid displacements
+# 1 = Kill rigid displacements using a global penalization
+# 2 = Add a Dirichlet condition on the top of the structure
+penalty_parameter = 1e-6  # Penalization coefficient for the global 
penalization
 
 if d == 2:
-   cpoints = [0, 0]   # constrained points for 2d
-   cunitv  = [1, 0]   # corresponding constrained directions for 2d
+    cpoints = [0, 0]  # constrained points for 2d
+    cunitv = [1, 0]  # corresponding constrained directions for 2d
 else:
-   cpoints = [0, 0, 0,   0, 0, 0,   5, 0, 5]  # constrained points for 3d
-   cunitv  = [1, 0, 0,   0, 1, 0,   0, 1, 0]  # corresponding constrained 
directions for 3d
+    cpoints = [0, 0, 0, 0, 0, 0, 5, 0, 5]  # constrained points for 3d
+    cunitv = [1, 0, 0, 0, 1, 0, 0, 1, 0]  # corresponding constrained 
directions for 3d
 
 niter = 100  # Maximum number of iterations for Newton's algorithm.
 version = 13  # 1 : frictionless contact and the basic contact brick
-              # 2 : contact with 'static' Coulomb friction and basic contact 
brick
-              # 3 : frictionless contact and the contact with a
-              #     rigid obstacle brick
-              # 4 : contact with 'static' Coulomb friction and the contact 
with a
-              #     rigid obstacle brick
-              # 5 : frictionless contact and the integral brick
-              #     Newton and Alart-Curnier augmented lagrangian,
-              #     unsymmetric version
-              # 6 : frictionless contact and the integral brick
-              #     Newton and Alart-Curnier augmented lagrangian, symmetric
-              #     version.
-              # 7 : frictionless contact and the integral brick
-              #     Newton and Alart-Curnier augmented lagrangian,
-              #     unsymmetric version with an additional augmentation.
-              # 8 : frictionless contact and the integral brick
-              #     New unsymmetric method.
-              # 9 : frictionless contact and the integral brick : Uzawa
-              #     on the Lagrangian augmented by the penalization term.
-              # 10 : contact with 'static' Coulomb friction and the integral 
brick
-              #     Newton and Alart-Curnier augmented lagrangian,
-              #     unsymmetric version.
-              # 11 : contact with 'static' Coulomb friction and the integral 
brick
-              #     Newton and Alart-Curnier augmented lagrangian,
-              #     nearly symmetric version.
-              # 12 : contact with 'static' Coulomb friction and the integral 
brick
-              #     Newton and Alart-Curnier augmented lagrangian,
-              #     unsymmetric version with an additional augmentation.
-              # 13 : contact with 'static' Coulomb friction and the integral 
brick
-              #     New unsymmetric method.
-              # 14 : contact with 'static' Coulomb friction and the integral 
brick : Uzawa
-              #     on the Lagrangian augmented by the penalization term.
-              # 15 : penalized contact with 'static' Coulomb friction (r is 
the penalization
-              #     coefficient).
+# 2 : contact with 'static' Coulomb friction and basic contact brick
+# 3 : frictionless contact and the contact with a
+#     rigid obstacle brick
+# 4 : contact with 'static' Coulomb friction and the contact with a
+#     rigid obstacle brick
+# 5 : frictionless contact and the integral brick
+#     Newton and Alart-Curnier augmented lagrangian,
+#     unsymmetric version
+# 6 : frictionless contact and the integral brick
+#     Newton and Alart-Curnier augmented lagrangian, symmetric
+#     version.
+# 7 : frictionless contact and the integral brick
+#     Newton and Alart-Curnier augmented lagrangian,
+#     unsymmetric version with an additional augmentation.
+# 8 : frictionless contact and the integral brick
+#     New unsymmetric method.
+# 9 : frictionless contact and the integral brick : Uzawa
+#     on the Lagrangian augmented by the penalization term.
+# 10 : contact with 'static' Coulomb friction and the integral brick
+#     Newton and Alart-Curnier augmented lagrangian,
+#     unsymmetric version.
+# 11 : contact with 'static' Coulomb friction and the integral brick
+#     Newton and Alart-Curnier augmented lagrangian,
+#     nearly symmetric version.
+# 12 : contact with 'static' Coulomb friction and the integral brick
+#     Newton and Alart-Curnier augmented lagrangian,
+#     unsymmetric version with an additional augmentation.
+# 13 : contact with 'static' Coulomb friction and the integral brick
+#     New unsymmetric method.
+# 14 : contact with 'static' Coulomb friction and the integral brick : Uzawa
+#     on the Lagrangian augmented by the penalization term.
+# 15 : penalized contact with 'static' Coulomb friction (r is the penalization
+#     coefficient).
 
 # Signed distance representing the obstacle
 if d == 2:
-   obstacle = 'y'
+    obstacle = "y"
 else:
-   obstacle = 'z'
+    obstacle = "z"
 
 # Selection of the contact and Dirichlet boundaries
 GAMMAC = 1
@@ -111,9 +111,9 @@ GAMMAD = 2
 
 border = m.outer_faces()
 normals = m.normal_of_faces(border)
-contact_boundary = border[:,np.nonzero(normals[d-1] < -0.01)[0]]
+contact_boundary = border[:, np.nonzero(normals[d - 1] < -0.01)[0]]
 m.set_region(GAMMAC, contact_boundary)
-contact_boundary = border[:,np.nonzero(normals[d-1] > 0.01)[0]]
+contact_boundary = border[:, np.nonzero(normals[d - 1] > 0.01)[0]]
 m.set_region(GAMMAD, contact_boundary)
 
 # Finite element methods
@@ -126,50 +126,50 @@ mfu.set_classical_fem(u_degree)
 mfd = gf.MeshFem(m, 1)
 mfd.set_classical_fem(u_degree)
 
-mflambda = gf.MeshFem(m, 1) # used only by version 5 to 13
+mflambda = gf.MeshFem(m, 1)  # used only by version 5 to 13
 mflambda.set_classical_fem(lambda_degree)
 
 mfvm = gf.MeshFem(m, 1)
-mfvm.set_classical_discontinuous_fem(u_degree-1)
+mfvm.set_classical_discontinuous_fem(u_degree - 1)
 
 # Integration method
 mim = gf.MeshIm(m, 4)
 if d == 2:
-   mim_friction = gf.MeshIm(m,
-     gf.Integ('IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(4),4)'))
+    mim_friction = gf.MeshIm(m, 
gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(4),4)"))
 else:
-   mim_friction = gf.MeshIm(m,
-     gf.Integ('IM_STRUCTURED_COMPOSITE(IM_TETRAHEDRON(5),4)'))
+    mim_friction = gf.MeshIm(
+        m, gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TETRAHEDRON(5),4)")
+    )
 
 # Volumic density of force
 nbdofd = mfd.nbdof()
 nbdofu = mfu.nbdof()
-F = np.zeros(nbdofd*d)
-F[d-1:nbdofd*d:d] = -vertical_force;
+F = np.zeros(nbdofd * d)
+F[d - 1 : nbdofd * d : d] = -vertical_force
 
 # Elasticity model
-md = gf.Model('real')
-md.add_fem_variable('u', mfu)
-md.add_initialized_data('cmu', [cmu])
-md.add_initialized_data('clambda', [clambda])
-md.add_isotropic_linearized_elasticity_brick(mim, 'u', 'clambda', 'cmu')
-md.add_initialized_fem_data('volumicload', mfd, F)
-md.add_source_term_brick(mim, 'u', 'volumicload')
+md = gf.Model("real")
+md.add_fem_variable("u", mfu)
+md.add_initialized_data("cmu", [cmu])
+md.add_initialized_data("clambda", [clambda])
+md.add_isotropic_linearized_elasticity_brick(mim, "u", "clambda", "cmu")
+md.add_initialized_fem_data("volumicload", mfd, F)
+md.add_source_term_brick(mim, "u", "volumicload")
 
 if condition_type == 2:
-   Ddata = np.zeros(d)
-   Ddata[d-1] = -5
-   md.add_initialized_data('Ddata', Ddata)
-   md.add_Dirichlet_condition_with_multipliers(mim, 'u', u_degree, GAMMAD, 
'Ddata')
+    Ddata = np.zeros(d)
+    Ddata[d - 1] = -5
+    md.add_initialized_data("Ddata", Ddata)
+    md.add_Dirichlet_condition_with_multipliers(mim, "u", u_degree, GAMMAD, 
"Ddata")
 elif condition_type == 0:
-   md.add_initialized_data('cpoints', cpoints)
-   md.add_initialized_data('cunitv', cunitv)
-   md.add_pointwise_constraints_with_multipliers('u', 'cpoints', 'cunitv')
+    md.add_initialized_data("cpoints", cpoints)
+    md.add_initialized_data("cunitv", cunitv)
+    md.add_pointwise_constraints_with_multipliers("u", "cpoints", "cunitv")
 elif condition_type == 1:
-   # Small penalty term to avoid rigid motion (should be replaced by an
-   # explicit treatment of the rigid motion with a constraint matrix)
-   md.add_initialized_data('penalty_param', [penalty_parameter])
-   md.add_mass_brick(mim, 'u', 'penalty_param')
+    # Small penalty term to avoid rigid motion (should be replaced by an
+    # explicit treatment of the rigid motion with a constraint matrix)
+    md.add_initialized_data("penalty_param", [penalty_parameter])
+    md.add_mass_brick(mim, "u", "penalty_param")
 
 # The contact condition
 
@@ -177,151 +177,199 @@ cdof = mfu.dof_on_region(GAMMAC)
 nbc = cdof.shape[0] / d
 
 solved = False
-if version == 1 or version == 2: # defining the matrices BN and BT by hand
-   contact_dof = cdof[d-1:nbc*d:d]
-   contact_nodes = mfu.basic_dof_nodes(contact_dof)
-   BN = gf.Spmat('empty', nbc, nbdofu)
-   ngap = np.zeros(nbc)
-   for i in range(nbc):
-      BN[i, contact_dof[i]] = -1.
-      ngap[i] = contact_nodes[d-1, i]
-
-   if version == 2:
-      BT = gf.Spmat('empty', nbc*(d-1), nbdofu)
-      for i in range(nbc):
-         for j in range(d-1):
-            BT[j+i*(d-1), contact_dof[i]-d+j+1] = 1.0
-
-   md.add_variable('lambda_n', nbc)
-   md.add_initialized_data('r', [r])
-   if version == 2:
-      md.add_variable('lambda_t', nbc * (d-1))
-      md.add_initialized_data('friction_coeff', [friction_coeff])
-
-   md.add_initialized_data('ngap', ngap)
-   md.add_initialized_data('alpha', np.ones(nbc))
-   if version == 1:
-      md.add_basic_contact_brick('u', 'lambda_n', 'r', BN, 'ngap', 'alpha', 1)
-   else:
-      md.add_basic_contact_brick('u', 'lambda_n', 'lambda_t', 'r', BN, BT, 
'friction_coeff', 'ngap', 'alpha', 1);
-
-elif version == 3 or version == 4: # BN and BT defined by the contact brick
-
-   md.add_variable('lambda_n', nbc)
-   md.add_initialized_data('r', [r])
-   if version == 3:
-      md.add_nodal_contact_with_rigid_obstacle_brick(mim, 'u', 'lambda_n', 
'r', GAMMAC, obstacle, 1);
-   else:
-      md.add_variable('lambda_t', nbc*(d-1))
-      md.add_initialized_data('friction_coeff', [friction_coeff])
-      md.add_nodal_contact_with_rigid_obstacle_brick(mim, 'u', 'lambda_n', 
'lambda_t', 'r',
-                                                     'friction_coeff', GAMMAC, 
obstacle, 1)
-
-elif version >= 5 and version <= 8: # The integral version, Newton
-
-   ldof = mflambda.dof_on_region(GAMMAC)
-   mflambda_partial = gf.MeshFem('partial', mflambda, ldof)
-   md.add_fem_variable('lambda_n', mflambda_partial)
-   md.add_initialized_data('r', [r])
-   OBS = mfd.eval(obstacle)
-   md.add_initialized_fem_data('obstacle', mfd, OBS)
-   md.add_integral_contact_with_rigid_obstacle_brick(mim_friction, 'u', 
'lambda_n',
-                                                      'obstacle', 'r', GAMMAC, 
version-4);
-
-elif version == 9: # The integral version, Uzawa on the augmented Lagrangian
-
-   ldof = mflambda.dof_on_region(GAMMAC)
-   mflambda_partial = gf.MeshFem('partial', mflambda, ldof)
-   nbc = mflambda_partial.nbdof()
-   M = gf.asm_mass_matrix(mim, mflambda_partial, mflambda_partial, GAMMAC)
-   lambda_n = np.zeros(nbc)
-   md.add_initialized_fem_data('lambda_n', mflambda_partial, lambda_n)
-   md.add_initialized_data('r', [r])
-   OBS = mfd.eval(obstacle) # np.array([mfd.eval(obstacle)])
-   md.add_initialized_fem_data('obstacle', mfd, OBS)
-   md.add_penalized_contact_with_rigid_obstacle_brick \
-     (mim_friction, 'u', 'obstacle', 'r', GAMMAC, 2, 'lambda_n')
-
-   for ii in range(100):
-      print('iteration %d' % (ii+1))
-      md.solve('max_res', 1E-9, 'max_iter', niter)
-      U = md.get('variable', 'u')
-      lambda_n_old = lambda_n
-      sol = gf.linsolve_superlu(M, 
gf.asm_integral_contact_Uzawa_projection(GAMMAC, mim_friction, mfu, U, 
mflambda_partial, lambda_n, mfd, OBS, r))
-      lambda_n = sol[0].transpose()
-      md.set_variable('lambda_n', lambda_n)
-      difff = max(abs(lambda_n-lambda_n_old))[0]/max(abs(lambda_n))[0]
-      print('diff : %g' % difff)
-      if difff < penalty_parameter:
-         break
-
-   solved = True
-
-elif version >= 10 and version <= 13: # The integral version with friction, 
Newton
-
-   mflambda.set_qdim(d);
-   ldof = mflambda.dof_on_region(GAMMAC)
-   mflambda_partial = gf.MeshFem('partial', mflambda, ldof)
-   md.add_fem_variable('lambda', mflambda_partial)
-   md.add_initialized_data('r', [r])
-   md.add_initialized_data('friction_coeff', [friction_coeff])
-   OBS = mfd.eval(obstacle)
-   md.add_initialized_fem_data('obstacle', mfd, OBS)
-   md.add_integral_contact_with_rigid_obstacle_brick \
-     (mim_friction, 'u', 'lambda', 'obstacle', 'r', 'friction_coeff', GAMMAC, 
version-9)
-
-elif version == 14: # The integral version, Uzawa on the augmented Lagrangian 
with friction
-  
-   mflambda.set_qdim(d)
-   ldof = mflambda.dof_on_region(GAMMAC)
-   mflambda_partial = gf.MeshFem('partial', mflambda, ldof)
-   nbc = mflambda_partial.nbdof()
-   md.add_initialized_data('friction_coeff', [friction_coeff])
-   M = gf.asm_mass_matrix(mim, mflambda_partial, mflambda_partial, GAMMAC)
-   lambda_nt = np.zeros(nbc)
-   md.add_initialized_fem_data('lambda', mflambda_partial, lambda_nt)
-   md.add_initialized_data('r', [r])
-   OBS = mfd.eval(obstacle)
-   md.add_initialized_fem_data('obstacle', mfd, OBS)
-   md.add_penalized_contact_with_rigid_obstacle_brick \
-     (mim_friction, 'u', 'obstacle', 'r', 'friction_coeff', GAMMAC, 2, 
'lambda')
-
-   for ii in range(100):
-      print('iteration %d' % (ii+1))
-      md.solve('max_res', 1E-9, 'max_iter', niter)
-      U = md.get('variable', 'u')
-      lambda_nt_old = lambda_nt
-      sol = gf.linsolve_superlu(M,
-        gf.asm_integral_contact_Uzawa_projection(
-        GAMMAC, mim_friction, mfu, U, mflambda_partial, lambda_nt, mfd, OBS, 
r, friction_coeff))
-      lambda_nt = sol[0].transpose()
-      md.set_variable('lambda', lambda_nt)
-      difff = max(abs(lambda_nt-lambda_nt_old))[0]/max(abs(lambda_nt))[0]
-      print('diff : %g' % difff)
-      if difff < penalty_parameter:
-         break
- 
-   solved = True
+if version == 1 or version == 2:  # defining the matrices BN and BT by hand
+    contact_dof = cdof[d - 1 : nbc * d : d]
+    contact_nodes = mfu.basic_dof_nodes(contact_dof)
+    BN = gf.Spmat("empty", nbc, nbdofu)
+    ngap = np.zeros(nbc)
+    for i in range(nbc):
+        BN[i, contact_dof[i]] = -1.0
+        ngap[i] = contact_nodes[d - 1, i]
+
+    if version == 2:
+        BT = gf.Spmat("empty", nbc * (d - 1), nbdofu)
+        for i in range(nbc):
+            for j in range(d - 1):
+                BT[j + i * (d - 1), contact_dof[i] - d + j + 1] = 1.0
+
+    md.add_variable("lambda_n", nbc)
+    md.add_initialized_data("r", [r])
+    if version == 2:
+        md.add_variable("lambda_t", nbc * (d - 1))
+        md.add_initialized_data("friction_coeff", [friction_coeff])
+
+    md.add_initialized_data("ngap", ngap)
+    md.add_initialized_data("alpha", np.ones(nbc))
+    if version == 1:
+        md.add_basic_contact_brick("u", "lambda_n", "r", BN, "ngap", "alpha", 
1)
+    else:
+        md.add_basic_contact_brick(
+            "u",
+            "lambda_n",
+            "lambda_t",
+            "r",
+            BN,
+            BT,
+            "friction_coeff",
+            "ngap",
+            "alpha",
+            1,
+        )
+
+elif version == 3 or version == 4:  # BN and BT defined by the contact brick
+
+    md.add_variable("lambda_n", nbc)
+    md.add_initialized_data("r", [r])
+    if version == 3:
+        md.add_nodal_contact_with_rigid_obstacle_brick(
+            mim, "u", "lambda_n", "r", GAMMAC, obstacle, 1
+        )
+    else:
+        md.add_variable("lambda_t", nbc * (d - 1))
+        md.add_initialized_data("friction_coeff", [friction_coeff])
+        md.add_nodal_contact_with_rigid_obstacle_brick(
+            mim, "u", "lambda_n", "lambda_t", "r", "friction_coeff", GAMMAC, 
obstacle, 1
+        )
+
+elif version >= 5 and version <= 8:  # The integral version, Newton
+
+    ldof = mflambda.dof_on_region(GAMMAC)
+    mflambda_partial = gf.MeshFem("partial", mflambda, ldof)
+    md.add_fem_variable("lambda_n", mflambda_partial)
+    md.add_initialized_data("r", [r])
+    OBS = mfd.eval(obstacle)
+    md.add_initialized_fem_data("obstacle", mfd, OBS)
+    md.add_integral_contact_with_rigid_obstacle_brick(
+        mim_friction, "u", "lambda_n", "obstacle", "r", GAMMAC, version - 4
+    )
+
+elif version == 9:  # The integral version, Uzawa on the augmented Lagrangian
+
+    ldof = mflambda.dof_on_region(GAMMAC)
+    mflambda_partial = gf.MeshFem("partial", mflambda, ldof)
+    nbc = mflambda_partial.nbdof()
+    M = gf.asm_mass_matrix(mim, mflambda_partial, mflambda_partial, GAMMAC)
+    lambda_n = np.zeros(nbc)
+    md.add_initialized_fem_data("lambda_n", mflambda_partial, lambda_n)
+    md.add_initialized_data("r", [r])
+    OBS = mfd.eval(obstacle)  # np.array([mfd.eval(obstacle)])
+    md.add_initialized_fem_data("obstacle", mfd, OBS)
+    md.add_penalized_contact_with_rigid_obstacle_brick(
+        mim_friction, "u", "obstacle", "r", GAMMAC, 2, "lambda_n"
+    )
+
+    for ii in range(100):
+        print("iteration %d" % (ii + 1))
+        md.solve("max_res", 1e-9, "max_iter", niter)
+        U = md.get("variable", "u")
+        lambda_n_old = lambda_n
+        sol = gf.linsolve_superlu(
+            M,
+            gf.asm_integral_contact_Uzawa_projection(
+                GAMMAC, mim_friction, mfu, U, mflambda_partial, lambda_n, mfd, 
OBS, r
+            ),
+        )
+        lambda_n = sol[0].transpose()
+        md.set_variable("lambda_n", lambda_n)
+        difff = max(abs(lambda_n - lambda_n_old))[0] / max(abs(lambda_n))[0]
+        print("diff : %g" % difff)
+        if difff < penalty_parameter:
+            break
+
+    solved = True
+
+elif version >= 10 and version <= 13:  # The integral version with friction, 
Newton
+
+    mflambda.set_qdim(d)
+    ldof = mflambda.dof_on_region(GAMMAC)
+    mflambda_partial = gf.MeshFem("partial", mflambda, ldof)
+    md.add_fem_variable("lambda", mflambda_partial)
+    md.add_initialized_data("r", [r])
+    md.add_initialized_data("friction_coeff", [friction_coeff])
+    OBS = mfd.eval(obstacle)
+    md.add_initialized_fem_data("obstacle", mfd, OBS)
+    md.add_integral_contact_with_rigid_obstacle_brick(
+        mim_friction,
+        "u",
+        "lambda",
+        "obstacle",
+        "r",
+        "friction_coeff",
+        GAMMAC,
+        version - 9,
+    )
+
+elif (
+    version == 14
+):  # The integral version, Uzawa on the augmented Lagrangian with friction
+
+    mflambda.set_qdim(d)
+    ldof = mflambda.dof_on_region(GAMMAC)
+    mflambda_partial = gf.MeshFem("partial", mflambda, ldof)
+    nbc = mflambda_partial.nbdof()
+    md.add_initialized_data("friction_coeff", [friction_coeff])
+    M = gf.asm_mass_matrix(mim, mflambda_partial, mflambda_partial, GAMMAC)
+    lambda_nt = np.zeros(nbc)
+    md.add_initialized_fem_data("lambda", mflambda_partial, lambda_nt)
+    md.add_initialized_data("r", [r])
+    OBS = mfd.eval(obstacle)
+    md.add_initialized_fem_data("obstacle", mfd, OBS)
+    md.add_penalized_contact_with_rigid_obstacle_brick(
+        mim_friction, "u", "obstacle", "r", "friction_coeff", GAMMAC, 2, 
"lambda"
+    )
+
+    for ii in range(100):
+        print("iteration %d" % (ii + 1))
+        md.solve("max_res", 1e-9, "max_iter", niter)
+        U = md.get("variable", "u")
+        lambda_nt_old = lambda_nt
+        sol = gf.linsolve_superlu(
+            M,
+            gf.asm_integral_contact_Uzawa_projection(
+                GAMMAC,
+                mim_friction,
+                mfu,
+                U,
+                mflambda_partial,
+                lambda_nt,
+                mfd,
+                OBS,
+                r,
+                friction_coeff,
+            ),
+        )
+        lambda_nt = sol[0].transpose()
+        md.set_variable("lambda", lambda_nt)
+        difff = max(abs(lambda_nt - lambda_nt_old))[0] / max(abs(lambda_nt))[0]
+        print("diff : %g" % difff)
+        if difff < penalty_parameter:
+            break
+
+    solved = True
 
 elif version == 15:
- 
-   md.add_initialized_data('r', [r])
-   md.add_initialized_data('friction_coeff', [friction_coeff])
-   OBS = mfd.eval(obstacle)
-   md.add_initialized_fem_data('obstacle', mfd, OBS);
-   md.add_penalized_contact_with_rigid_obstacle_brick \
-     (mim_friction, 'u', 'obstacle', 'r', 'friction_coeff', GAMMAC)
+
+    md.add_initialized_data("r", [r])
+    md.add_initialized_data("friction_coeff", [friction_coeff])
+    OBS = mfd.eval(obstacle)
+    md.add_initialized_fem_data("obstacle", mfd, OBS)
+    md.add_penalized_contact_with_rigid_obstacle_brick(
+        mim_friction, "u", "obstacle", "r", "friction_coeff", GAMMAC
+    )
 
 else:
-   print('Inexistent version')
+    print("Inexistent version")
 
 # Solve the problem
 if not solved:
-   md.solve('max_res', 1E-9, 'very noisy', 'max_iter', niter, 'lsearch', 
'default') #, 'with pseudo potential')
+    md.solve(
+        "max_res", 1e-9, "very noisy", "max_iter", niter, "lsearch", "default"
+    )  # , 'with pseudo potential')
 
-U = md.get('variable', 'u')
+U = md.get("variable", "u")
 # LAMBDA = md.get('variable', 'lambda_n')
-VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u', 'clambda', 
'cmu', mfvm)
-
-mfd.export_to_vtk('static_contact.vtk', 'ascii', mfvm,  VM, 'Von Mises 
Stress', mfu, U, 'Displacement')
+VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca("u", "clambda", 
"cmu", mfvm)
 
+mfd.export_to_vtk(
+    "static_contact.vtk", "ascii", mfvm, VM, "Von Mises Stress", mfu, U, 
"Displacement"
+)
diff --git a/interface/tests/python/demo_step_by_step.py 
b/interface/tests/python/demo_step_by_step.py
index d8347d0..0f9a875 100644
--- a/interface/tests/python/demo_step_by_step.py
+++ b/interface/tests/python/demo_step_by_step.py
@@ -25,18 +25,18 @@ import getfem as gf
 import numpy as np
 
 # creation of a simple cartesian mesh
-m = gf.Mesh('cartesian', np.arange(0,1.1,0.1), np.arange(0,1.1,0.1))
+m = gf.Mesh("cartesian", np.arange(0, 1.1, 0.1), np.arange(0, 1.1, 0.1))
 
 # create a MeshFem of for a field of dimension 1 (i.e. a scalar field)
 mf = gf.MeshFem(m, 1)
 # assign the Q2 fem to all convexes of the MeshFem
-mf.set_fem(gf.Fem('FEM_QK(2,2)'))
+mf.set_fem(gf.Fem("FEM_QK(2,2)"))
 
 # view the expression of its basis functions on the reference convex
-print(gf.Fem('FEM_QK(2,2)').poly_str())
+print(gf.Fem("FEM_QK(2,2)").poly_str())
 
 # an exact integration will be used
-mim = gf.MeshIm(m, gf.Integ('IM_GAUSS_PARALLELEPIPED(2,4)'))
+mim = gf.MeshIm(m, gf.Integ("IM_GAUSS_PARALLELEPIPED(2,4)"))
 
 # detect the border of the mesh
 border = m.outer_faces()
@@ -44,30 +44,30 @@ border = m.outer_faces()
 m.set_region(42, border)
 
 # empty real model
-md = gf.Model('real')
+md = gf.Model("real")
 
 # declare that "u" is an unknown of the system
 # on the finite element method `mf`
-md.add_fem_variable('u', mf)
+md.add_fem_variable("u", mf)
 
 # add generic elliptic brick on "u"
-md.add_Laplacian_brick(mim, 'u');
+md.add_Laplacian_brick(mim, "u")
 
 # add Dirichlet condition
-g = mf.eval('x*(x-1) - y*(y-1)')
-md.add_initialized_fem_data('DirichletData', mf, g)
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mf, 42, 'DirichletData')
+g = mf.eval("x*(x-1) - y*(y-1)")
+md.add_initialized_fem_data("DirichletData", mf, g)
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mf, 42, "DirichletData")
 
 # add source term
-#f = mf.eval('0')
-#md.add_initialized_fem_data('VolumicData', mf, f)
-#md.add_source_term_brick(mim, 'u', 'VolumicData')
+# f = mf.eval('0')
+# md.add_initialized_fem_data('VolumicData', mf, f)
+# md.add_source_term_brick(mim, 'u', 'VolumicData')
 
 # solve the linear system
 md.solve()
 
 # extracted solution
-u = md.variable('u')
+u = md.variable("u")
 
 # export computed solution
-mf.export_to_pos('u.pos',u,'Computed solution')
+mf.export_to_pos("u.pos", u, "Computed solution")
diff --git a/interface/tests/python/demo_stokes_3D_tank.py 
b/interface/tests/python/demo_stokes_3D_tank.py
index 603b52d..5e8879e 100644
--- a/interface/tests/python/demo_stokes_3D_tank.py
+++ b/interface/tests/python/demo_stokes_3D_tank.py
@@ -22,37 +22,39 @@
 from getfem import *
 from numpy import *
 
-print('3D stokes demonstration on a quadratic mesh')
+print("3D stokes demonstration on a quadratic mesh")
 
 viscosity = 10
 
 
-m=Mesh('import','GiD','../meshes/tank_quadratic_2500.GiD.msh')
-print('mesh loaded!')
-mfu=MeshFem(m,3) # velocity
-mfulag=MeshFem(m,3)
-mfp=MeshFem(m,1) # pressure
-mfd=MeshFem(m,1) # data
-mfe=MeshFem(m,1)
-mim=MeshIm(m, Integ('IM_TETRAHEDRON(5)'))
+m = Mesh("import", "GiD", "../meshes/tank_quadratic_2500.GiD.msh")
+print("mesh loaded!")
+mfu = MeshFem(m, 3)  # velocity
+mfulag = MeshFem(m, 3)
+mfp = MeshFem(m, 1)  # pressure
+mfd = MeshFem(m, 1)  # data
+mfe = MeshFem(m, 1)
+mim = MeshIm(m, Integ("IM_TETRAHEDRON(5)"))
 
-mfu.set_fem(Fem('FEM_PK(3,2)'))
-mfd.set_fem(Fem('FEM_PK(3,2)'))
-mfp.set_fem(Fem('FEM_PK(3,1)'))
-mfe.set_fem(Fem('FEM_PK_DISCONTINUOUS(3,1,0.01)'))
+mfu.set_fem(Fem("FEM_PK(3,2)"))
+mfd.set_fem(Fem("FEM_PK(3,2)"))
+mfp.set_fem(Fem("FEM_PK(3,1)"))
+mfe.set_fem(Fem("FEM_PK_DISCONTINUOUS(3,1,0.01)"))
 
-print('nbcvs=%d, nbpts=%d, qdim=%d, fem = %s, nbdof=%d' % \
-      (m.nbcvs(), m.nbpts(), mfu.qdim(), mfu.fem()[0].char(), mfu.nbdof()))
+print(
+    "nbcvs=%d, nbpts=%d, qdim=%d, fem = %s, nbdof=%d"
+    % (m.nbcvs(), m.nbpts(), mfu.qdim(), mfu.fem()[0].char(), mfu.nbdof())
+)
 
 
-P=m.pts()
-r = list(range(0, m.nbpts()));
-INpid=compress(abs(P[0,:]+25) < 1e-4, r)
-OUTpid=compress(abs(P[0,:]-25) < 1e-4, r)
-TOPpid=compress(abs(P[2,:]-20) < 1e-4, r)
-INfaces=m.faces_from_pid(INpid)
-OUTfaces=m.faces_from_pid(OUTpid)
-TOPfaces=m.faces_from_pid(TOPpid)
+P = m.pts()
+r = list(range(0, m.nbpts()))
+INpid = compress(abs(P[0, :] + 25) < 1e-4, r)
+OUTpid = compress(abs(P[0, :] - 25) < 1e-4, r)
+TOPpid = compress(abs(P[2, :] - 20) < 1e-4, r)
+INfaces = m.faces_from_pid(INpid)
+OUTfaces = m.faces_from_pid(OUTpid)
+TOPfaces = m.faces_from_pid(TOPpid)
 
 m.set_region(1, INfaces)
 m.set_region(2, OUTfaces)
@@ -63,47 +65,49 @@ m.region_subtract(4, 2)
 m.region_subtract(4, 3)
 
 
-
-md=Model('real');
-md.add_fem_variable('u', mfu);
-md.add_initialized_data('lambda', [0]);
-md.add_initialized_data('mu', [viscosity]);
-md.add_isotropic_linearized_elasticity_brick(mim, 'u', 'lambda', 'mu');
-md.add_fem_variable('p', mfp);
-md.add_linear_incompressibility_brick(mim, 'u', 'p');
-md.add_variable('mult_spec', 1);
-M = Spmat('empty', 1, mfp.nbdof());
-M.add(list(range(1)), list(range(mfp.nbdof())), ones((1, mfp.nbdof())));
-md.add_constraint_with_multipliers('p', 'mult_spec', M, [0]);
-md.add_initialized_data('NeumannData', [0, -10, 0]);
-md.add_source_term_brick(mim, 'u', 'NeumannData', 1);
-
-D = mfd.basic_dof_nodes();
-x = D[0,:]
-y = D[1,:]
-z = D[2,:]
-md.add_initialized_fem_data('Dir1data', mfd, [9-(y*y+(z-6)*(z-6)),0*x,0*x]);
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, 1, 'Dir1data');
-md.add_initialized_fem_data('Dir2data',  mfd, [9-(y*y+(z-6)*(z-6)),0*x,0*x]);
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, 2, 'Dir2data');
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, 3);
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, 4);
-
-print('running solve...')
-md.solve('noisy', 'lsolver','superlu')
-print('solve done!')
-
-
-U = md.variable('u');
-P = md.variable('p');
-VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u', 'lambda',
-                                                         'mu', mfe);
-
-mfu.save('tank_3D.mfu', 'with_mesh')
-mfp.save('tank_3D.mfp', 'with_mesh')
-U.tofile('tank_3D.U')
-P.tofile('tank_3D.P')
-
-mfe.save('tank_3D.mfe')
-VM.tofile('tank_3D.VM')
-#memstats()
+md = Model("real")
+md.add_fem_variable("u", mfu)
+md.add_initialized_data("lambda", [0])
+md.add_initialized_data("mu", [viscosity])
+md.add_isotropic_linearized_elasticity_brick(mim, "u", "lambda", "mu")
+md.add_fem_variable("p", mfp)
+md.add_linear_incompressibility_brick(mim, "u", "p")
+md.add_variable("mult_spec", 1)
+M = Spmat("empty", 1, mfp.nbdof())
+M.add(list(range(1)), list(range(mfp.nbdof())), ones((1, mfp.nbdof())))
+md.add_constraint_with_multipliers("p", "mult_spec", M, [0])
+md.add_initialized_data("NeumannData", [0, -10, 0])
+md.add_source_term_brick(mim, "u", "NeumannData", 1)
+
+D = mfd.basic_dof_nodes()
+x = D[0, :]
+y = D[1, :]
+z = D[2, :]
+md.add_initialized_fem_data(
+    "Dir1data", mfd, [9 - (y * y + (z - 6) * (z - 6)), 0 * x, 0 * x]
+)
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, 1, "Dir1data")
+md.add_initialized_fem_data(
+    "Dir2data", mfd, [9 - (y * y + (z - 6) * (z - 6)), 0 * x, 0 * x]
+)
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, 2, "Dir2data")
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, 3)
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, 4)
+
+print("running solve...")
+md.solve("noisy", "lsolver", "superlu")
+print("solve done!")
+
+
+U = md.variable("u")
+P = md.variable("p")
+VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca("u", "lambda", "mu", 
mfe)
+
+mfu.save("tank_3D.mfu", "with_mesh")
+mfp.save("tank_3D.mfp", "with_mesh")
+U.tofile("tank_3D.U")
+P.tofile("tank_3D.P")
+
+mfe.save("tank_3D.mfe")
+VM.tofile("tank_3D.VM")
+# memstats()
diff --git a/interface/tests/python/demo_stokes_3D_tank_draw.py 
b/interface/tests/python/demo_stokes_3D_tank_draw.py
index a6e2e65..e4789a8 100644
--- a/interface/tests/python/demo_stokes_3D_tank_draw.py
+++ b/interface/tests/python/demo_stokes_3D_tank_draw.py
@@ -22,47 +22,70 @@
 import getfem
 from numpy import *
 
-mfu=getfem.MeshFem('load','tank_3D.mfu')
-m=mfu.linked_mesh()
-mfp=getfem.MeshFem('load','tank_3D.mfp',m)
-U = fromfile('tank_3D.U', 'd')
-P = fromfile('tank_3D.P', 'd')
-
-sl=getfem.Slice(('boundary',('intersection',('planar',+1,[0,0,0],[0,1,0]),('planar',+1,[0,0,0],[1,0,0]))),m,3);
+mfu = getfem.MeshFem("load", "tank_3D.mfu")
+m = mfu.linked_mesh()
+mfp = getfem.MeshFem("load", "tank_3D.mfp", m)
+U = fromfile("tank_3D.U", "d")
+P = fromfile("tank_3D.P", "d")
+
+sl = getfem.Slice(
+    (
+        "boundary",
+        (
+            "intersection",
+            ("planar", +1, [0, 0, 0], [0, 1, 0]),
+            ("planar", +1, [0, 0, 0], [1, 0, 0]),
+        ),
+    ),
+    m,
+    3,
+)
 
 print("importing tvtk..")
 import getfem_tvtk
+
 print("import done")
 
-fig = getfem_tvtk.Figure(gui='tvtk')
+fig = getfem_tvtk.Figure(gui="tvtk")
 
-fig.show(sl, data=(mfp, P), vdata=(mfu,U), edges=False)
+fig.show(sl, data=(mfp, P), vdata=(mfu, U), edges=False)
 
 fig.show(sl, data=(mfp, P), edges=False)
 
 
-old=fig.scalar_range()
-
-sl=getfem.Slice(('boundary',('intersection',('planar',+1,[0,0,6],[0,0,-1]),
-                             ('planar',+1,[0,0,0],[0,1,0]))),m,3);
+old = fig.scalar_range()
+
+sl = getfem.Slice(
+    (
+        "boundary",
+        (
+            "intersection",
+            ("planar", +1, [0, 0, 6], [0, 0, -1]),
+            ("planar", +1, [0, 0, 0], [0, 1, 0]),
+        ),
+    ),
+    m,
+    3,
+)
 fig.show(sl, data=(mfp, P), scalar_bar=True, edges=False)
-fig.scalar_range((-40,40));
+fig.scalar_range((-40, 40))
 
-#print(fig.scalar_range())
+# print(fig.scalar_range())
 
-m.set_region(42, m.outer_faces());
-m.region_subtract(42, 3);
+m.set_region(42, m.outer_faces())
+m.region_subtract(42, 3)
 
-sl2=getfem.Slice(('boundary',('planar',+1,[0,0,0],[0,1,0])),m,3, m.region(42))
-fig.show(sl2, faces=False, edges_color=(1,1,1))
+sl2 = getfem.Slice(
+    ("boundary", ("planar", +1, [0, 0, 0], [0, 1, 0])), m, 3, m.region(42)
+)
+fig.show(sl2, faces=False, edges_color=(1, 1, 1))
 
 
-hh=array([[1, 5, 9, 12.5, 16, 19.5]]);
-H=concatenate((zeros((2,hh.size)), hh));
+hh = array([[1, 5, 9, 12.5, 16, 19.5]])
+H = concatenate((zeros((2, hh.size)), hh))
 
-tsl=getfem.Slice('streamlines', mfu, U, H);
+tsl = getfem.Slice("streamlines", mfu, U, H)
 
-fig.show(tsl, tube_color=(1,1,1));
+fig.show(tsl, tube_color=(1, 1, 1))
 
 fig.loop()
-
diff --git 
a/interface/tests/python/demo_thermo_elasticity_electrical_coupling.py 
b/interface/tests/python/demo_thermo_elasticity_electrical_coupling.py
index cf6b44c..b9f3b32 100644
--- a/interface/tests/python/demo_thermo_elasticity_electrical_coupling.py
+++ b/interface/tests/python/demo_thermo_elasticity_electrical_coupling.py
@@ -34,7 +34,7 @@ import numpy as np
 #   /|       |    |   |    |   |    |       |-> F
 #   /|        \__/     \__/     \__/        |->
 #   /|______________________________________|->
-#     
+#
 #
 # Elastic problem: The plate is clamped at rhe left boundary and a
 #   traction density of force F is prescribed at the right boundary.
@@ -60,68 +60,74 @@ import numpy as np
 #
 # Physical parameters
 #
-epsilon = 1.       # Thickness of the plate (cm)
-E = 21E6           # Young Modulus (N/cm^2)
-nu = 0.3           # Poisson ratio
-clambda = E*nu/((1+nu)*(1-2*nu)) # First Lame coefficient (N/cm^2)
-cmu = E/(2*(1+nu))               # Second Lame coefficient (N/cm^2)
-clambdastar = 2*clambda*cmu/(clambda+2*cmu) # Lame coefficient for Plane 
stress (N/cm^2)
-F = 100E2          # Force density at the right boundary (N/cm^2)
-kappa = 4.         # Thermal conductivity (W/(cm K))
-D = 10.            # Heat transfer coefficient (W/(K cm^2))
-air_temp = 20.     # Temperature of the air in oC.
-alpha_th = 16.6E-6 # Thermal expansion coefficient (/K).
-T0 = 20.           # Reference temperature in oC.
-rho_0 = 1.754E-8   # Resistance temperature coefficient at T0 = 20oC
-alpha = 0.0039     # Second resistance temperature coefficient.
+epsilon = 1.0  # Thickness of the plate (cm)
+E = 21e6  # Young Modulus (N/cm^2)
+nu = 0.3  # Poisson ratio
+clambda = E * nu / ((1 + nu) * (1 - 2 * nu))  # First Lame coefficient (N/cm^2)
+cmu = E / (2 * (1 + nu))  # Second Lame coefficient (N/cm^2)
+clambdastar = (
+    2 * clambda * cmu / (clambda + 2 * cmu)
+)  # Lame coefficient for Plane stress (N/cm^2)
+F = 100e2  # Force density at the right boundary (N/cm^2)
+kappa = 4.0  # Thermal conductivity (W/(cm K))
+D = 10.0  # Heat transfer coefficient (W/(K cm^2))
+air_temp = 20.0  # Temperature of the air in oC.
+alpha_th = 16.6e-6  # Thermal expansion coefficient (/K).
+T0 = 20.0  # Reference temperature in oC.
+rho_0 = 1.754e-8  # Resistance temperature coefficient at T0 = 20oC
+alpha = 0.0039  # Second resistance temperature coefficient.
 
 #
 # Numerical parameters
 #
-h = 2.                     # Approximate mesh size
-elements_degree = 2        # Degree of the finite element methods
-export_mesh = True         # Draw the mesh after mesh generation or not
+h = 2.0  # Approximate mesh size
+elements_degree = 2  # Degree of the finite element methods
+export_mesh = True  # Draw the mesh after mesh generation or not
 solve_in_two_steps = True  # Solve the elasticity problem separately or not
 
 #
 # Mesh generation. Meshes can also been imported from several formats.
 #
-mo1 = gf.MesherObject('rectangle', [0., 0.], [100., 25.])
-mo2 = gf.MesherObject('ball', [25., 12.5], 8.)
-mo3 = gf.MesherObject('ball', [50., 12.5], 8.)
-mo4 = gf.MesherObject('ball', [75., 12.5], 8.)
-mo5 = gf.MesherObject('union', mo2, mo3, mo4)
-mo  = gf.MesherObject('set minus', mo1, mo5)
+mo1 = gf.MesherObject("rectangle", [0.0, 0.0], [100.0, 25.0])
+mo2 = gf.MesherObject("ball", [25.0, 12.5], 8.0)
+mo3 = gf.MesherObject("ball", [50.0, 12.5], 8.0)
+mo4 = gf.MesherObject("ball", [75.0, 12.5], 8.0)
+mo5 = gf.MesherObject("union", mo2, mo3, mo4)
+mo = gf.MesherObject("set minus", mo1, mo5)
 
-print('Mesh generation')
-gf.util('trace level', 2)   # No trace for mesh generation
-mesh = gf.Mesh('generate', mo, h, 2)
+print("Mesh generation")
+gf.util("trace level", 2)  # No trace for mesh generation
+mesh = gf.Mesh("generate", mo, h, 2)
 
 #
 # Boundary selection
 #
-fb1 = mesh.outer_faces_in_box([1., 1.], [99., 24.])    # Boundary of the holes
-fb2 = mesh.outer_faces_with_direction([ 1., 0.], 0.01) # Right boundary
-fb3 = mesh.outer_faces_with_direction([-1., 0.], 0.01) # Left boundary
-fb4 = mesh.outer_faces_with_direction([0.,  1.], 0.01) # Top boundary
-fb5 = mesh.outer_faces_with_direction([0., -1.], 0.01) # Bottom boundary
-
-RIGHT_BOUND=1; LEFT_BOUND=2; TOP_BOUND=3; BOTTOM_BOUND=4; HOLE_BOUND=5;
-
-mesh.set_region( RIGHT_BOUND, fb2)
-mesh.set_region(  LEFT_BOUND, fb3)
-mesh.set_region(   TOP_BOUND, fb4)
+fb1 = mesh.outer_faces_in_box([1.0, 1.0], [99.0, 24.0])  # Boundary of the 
holes
+fb2 = mesh.outer_faces_with_direction([1.0, 0.0], 0.01)  # Right boundary
+fb3 = mesh.outer_faces_with_direction([-1.0, 0.0], 0.01)  # Left boundary
+fb4 = mesh.outer_faces_with_direction([0.0, 1.0], 0.01)  # Top boundary
+fb5 = mesh.outer_faces_with_direction([0.0, -1.0], 0.01)  # Bottom boundary
+
+RIGHT_BOUND = 1
+LEFT_BOUND = 2
+TOP_BOUND = 3
+BOTTOM_BOUND = 4
+HOLE_BOUND = 5
+
+mesh.set_region(RIGHT_BOUND, fb2)
+mesh.set_region(LEFT_BOUND, fb3)
+mesh.set_region(TOP_BOUND, fb4)
 mesh.set_region(BOTTOM_BOUND, fb5)
-mesh.set_region(  HOLE_BOUND, fb1)
-mesh.region_subtract( RIGHT_BOUND, HOLE_BOUND)
-mesh.region_subtract(  LEFT_BOUND, HOLE_BOUND)
-mesh.region_subtract(   TOP_BOUND, HOLE_BOUND)
+mesh.set_region(HOLE_BOUND, fb1)
+mesh.region_subtract(RIGHT_BOUND, HOLE_BOUND)
+mesh.region_subtract(LEFT_BOUND, HOLE_BOUND)
+mesh.region_subtract(TOP_BOUND, HOLE_BOUND)
 mesh.region_subtract(BOTTOM_BOUND, HOLE_BOUND)
 
-if (export_mesh):
-    mesh.export_to_vtk('mesh.vtk');
-    print('\nYou can view the mesh for instance with');
-    print('mayavi2 -d mesh.vtk -f ExtractEdges -m Surface \n');
+if export_mesh:
+    mesh.export_to_vtk("mesh.vtk")
+    print("\nYou can view the mesh for instance with")
+    print("mayavi2 -d mesh.vtk -f ExtractEdges -m Surface \n")
 
 #
 # Definition of finite elements methods and integration method
@@ -131,101 +137,107 @@ mfu = gf.MeshFem(mesh, 2)  # Finite element for the 
elastic displacement
 mfu.set_classical_fem(elements_degree)
 mft = gf.MeshFem(mesh, 1)  # Finite element for temperature and electrical 
field
 mft.set_classical_fem(elements_degree)
-mfvm = gf.MeshFem(mesh, 1) # Finite element for Von Mises stress interpolation
+mfvm = gf.MeshFem(mesh, 1)  # Finite element for Von Mises stress interpolation
 mfvm.set_classical_discontinuous_fem(elements_degree)
-mim = gf.MeshIm(mesh, pow(elements_degree,2))   # Integration method
+mim = gf.MeshIm(mesh, pow(elements_degree, 2))  # Integration method
 
 
 #
 # Model definition
 #
 
-md=gf.Model('real');
-md.add_fem_variable('u', mfu)       # Displacement of the structure
-md.add_fem_variable('theta', mft)   # Temperature
-md.add_fem_variable('V', mft)       # Electric potential
+md = gf.Model("real")
+md.add_fem_variable("u", mfu)  # Displacement of the structure
+md.add_fem_variable("theta", mft)  # Temperature
+md.add_fem_variable("V", mft)  # Electric potential
 
 # Membrane elastic deformation
-md.add_initialized_data('cmu', [cmu])
-md.add_initialized_data('clambdastar', [clambdastar])
-md.add_isotropic_linearized_elasticity_brick(mim, 'u', 'clambdastar', 'cmu')
+md.add_initialized_data("cmu", [cmu])
+md.add_initialized_data("clambdastar", [clambdastar])
+md.add_isotropic_linearized_elasticity_brick(mim, "u", "clambdastar", "cmu")
 
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', elements_degree-1, 
LEFT_BOUND)
-md.add_initialized_data('Fdata', [F*epsilon, 0])
-md.add_source_term_brick(mim, 'u', 'Fdata', RIGHT_BOUND)
+md.add_Dirichlet_condition_with_multipliers(mim, "u", elements_degree - 1, 
LEFT_BOUND)
+md.add_initialized_data("Fdata", [F * epsilon, 0])
+md.add_source_term_brick(mim, "u", "Fdata", RIGHT_BOUND)
 
 # Electrical field
-sigmaeps = '(eps/(rho_0*(1+alpha*(theta-T0))))'
-md.add_initialized_data('eps', [epsilon])
-md.add_initialized_data('rho_0', [rho_0])
-md.add_initialized_data('alpha', [alpha])
-md.add_initialized_data('T0', [T0])
-md.add_nonlinear_term(mim, sigmaeps+'*(Grad_V.Grad_Test_V)')
-md.add_Dirichlet_condition_with_multipliers(mim, 'V', elements_degree-1, 
RIGHT_BOUND)
-md.add_initialized_data('DdataV', [0.1])
-md.add_Dirichlet_condition_with_multipliers(mim, 'V', elements_degree-1, 
LEFT_BOUND, 'DdataV')
+sigmaeps = "(eps/(rho_0*(1+alpha*(theta-T0))))"
+md.add_initialized_data("eps", [epsilon])
+md.add_initialized_data("rho_0", [rho_0])
+md.add_initialized_data("alpha", [alpha])
+md.add_initialized_data("T0", [T0])
+md.add_nonlinear_term(mim, sigmaeps + "*(Grad_V.Grad_Test_V)")
+md.add_Dirichlet_condition_with_multipliers(mim, "V", elements_degree - 1, 
RIGHT_BOUND)
+md.add_initialized_data("DdataV", [0.1])
+md.add_Dirichlet_condition_with_multipliers(
+    mim, "V", elements_degree - 1, LEFT_BOUND, "DdataV"
+)
 
 # Thermal problem
-md.add_initialized_data('kaeps', [kappa*epsilon])
-md.add_generic_elliptic_brick(mim, 'theta', 'kaeps')
-md.add_initialized_data('D2', [D*2])
-md.add_initialized_data('D2airt', [air_temp*D*2])
-md.add_mass_brick(mim, 'theta', 'D2')
-md.add_source_term_brick(mim, 'theta', 'D2airt')
-md.add_initialized_data('Deps', [D/epsilon])
-md.add_initialized_data('Depsairt', [air_temp*D/epsilon])
-md.add_Fourier_Robin_brick(mim, 'theta', 'Deps', TOP_BOUND)
-md.add_source_term_brick(mim, 'theta', 'Depsairt', TOP_BOUND)
-md.add_Fourier_Robin_brick(mim, 'theta', 'Deps', BOTTOM_BOUND)
-md.add_source_term_brick(mim, 'theta', 'Depsairt', BOTTOM_BOUND)
+md.add_initialized_data("kaeps", [kappa * epsilon])
+md.add_generic_elliptic_brick(mim, "theta", "kaeps")
+md.add_initialized_data("D2", [D * 2])
+md.add_initialized_data("D2airt", [air_temp * D * 2])
+md.add_mass_brick(mim, "theta", "D2")
+md.add_source_term_brick(mim, "theta", "D2airt")
+md.add_initialized_data("Deps", [D / epsilon])
+md.add_initialized_data("Depsairt", [air_temp * D / epsilon])
+md.add_Fourier_Robin_brick(mim, "theta", "Deps", TOP_BOUND)
+md.add_source_term_brick(mim, "theta", "Depsairt", TOP_BOUND)
+md.add_Fourier_Robin_brick(mim, "theta", "Deps", BOTTOM_BOUND)
+md.add_source_term_brick(mim, "theta", "Depsairt", BOTTOM_BOUND)
 
 # Joule heating term
-md.add_nonlinear_term(mim, '-'+sigmaeps+'*Norm_sqr(Grad_V)*Test_theta')
+md.add_nonlinear_term(mim, "-" + sigmaeps + "*Norm_sqr(Grad_V)*Test_theta")
 
 # Thermal expansion term
-md.add_initialized_data('beta', [alpha_th*E/(1-2*nu)])
-md.add_linear_term(mim, 'beta*(T0-theta)*Trace(Grad_Test_u)')
+md.add_initialized_data("beta", [alpha_th * E / (1 - 2 * nu)])
+md.add_linear_term(mim, "beta*(T0-theta)*Trace(Grad_Test_u)")
 
 
 #
 # Model solve
 #
-if (solve_in_two_steps):
-  md.disable_variable('u')
-  print('First problem with', md.nbdof(), ' dofs')
-  md.solve('max_res', 1E-9, 'max_iter', 100, 'noisy')
-  md.enable_variable('u')
-  md.disable_variable('theta')
-  md.disable_variable('V')
-  print('Second problem with ', md.nbdof(), ' dofs')
-  md.solve('max_res', 1E-9, 'max_iter', 100, 'noisy')
+if solve_in_two_steps:
+    md.disable_variable("u")
+    print("First problem with", md.nbdof(), " dofs")
+    md.solve("max_res", 1e-9, "max_iter", 100, "noisy")
+    md.enable_variable("u")
+    md.disable_variable("theta")
+    md.disable_variable("V")
+    print("Second problem with ", md.nbdof(), " dofs")
+    md.solve("max_res", 1e-9, "max_iter", 100, "noisy")
 else:
-  print('Global problem with ', md.nbdof(), ' dofs')
-  md.solve('max_res', 1E-9, 'max_iter', 100, 'noisy')
+    print("Global problem with ", md.nbdof(), " dofs")
+    md.solve("max_res", 1e-9, "max_iter", 100, "noisy")
 
 
 #
 # Solution export
-#  
-U = md.variable('u')
-V = md.variable('V')
-THETA = md.variable('theta')
-VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u', 'clambdastar', 
'cmu', mfvm)
-CO = np.reshape(md.interpolation('-'+sigmaeps+'*Grad_V', mfvm), (2, 
mfvm.nbdof()), 'F')
-
-mfvm.export_to_vtk('displacement_with_von_mises.vtk', mfvm,  VM, 'Von Mises 
Stresses', mfu, U, 'Displacements')
-print('You can view solutions with for instance:\nmayavi2 -d 
displacement_with_von_mises.vtk -f WarpVector -m Surface')
-mft.export_to_vtk('temperature.vtk', mft, THETA, 'Temperature')
-print('mayavi2 -d temperature.vtk -f WarpScalar -m Surface')
-mft.export_to_vtk('electric_potential.vtk', mft, V, 'Electric potential')
-print('mayavi2 -d electric_potential.vtk -f WarpScalar -m Surface')
-
-
-
-
-
-
-
-
-
-
+#
+U = md.variable("u")
+V = md.variable("V")
+THETA = md.variable("theta")
+VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca(
+    "u", "clambdastar", "cmu", mfvm
+)
+CO = np.reshape(
+    md.interpolation("-" + sigmaeps + "*Grad_V", mfvm), (2, mfvm.nbdof()), "F"
+)
+
+mfvm.export_to_vtk(
+    "displacement_with_von_mises.vtk",
+    mfvm,
+    VM,
+    "Von Mises Stresses",
+    mfu,
+    U,
+    "Displacements",
+)
+print(
+    "You can view solutions with for instance:\nmayavi2 -d 
displacement_with_von_mises.vtk -f WarpVector -m Surface"
+)
+mft.export_to_vtk("temperature.vtk", mft, THETA, "Temperature")
+print("mayavi2 -d temperature.vtk -f WarpScalar -m Surface")
+mft.export_to_vtk("electric_potential.vtk", mft, V, "Electric potential")
+print("mayavi2 -d electric_potential.vtk -f WarpScalar -m Surface")
diff --git a/interface/tests/python/demo_tresca.py 
b/interface/tests/python/demo_tresca.py
index a9f8dfc..6f7bb71 100644
--- a/interface/tests/python/demo_tresca.py
+++ b/interface/tests/python/demo_tresca.py
@@ -31,30 +31,33 @@ import getfem as gf
 import numpy as np
 
 ## Parameters
-NX = 100                           # Mesh parameter.
-thr = 1                            # Tresca threshold
-gamma0 = 5                         # Nitsche's parameter
-theta = 1                          # Nitsche's version
+NX = 100  # Mesh parameter.
+thr = 1  # Tresca threshold
+gamma0 = 5  # Nitsche's parameter
+theta = 1  # Nitsche's version
 
 # Create a simple cartesian mesh
-m = gf.Mesh('regular_simplices', np.arange(0,2+1./NX,1./NX),
-            np.arange(0,1+1./NX,1./NX))
+m = gf.Mesh(
+    "regular_simplices",
+    np.arange(0, 2 + 1.0 / NX, 1.0 / NX),
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+)
 
 # Create a MeshFem for u and rhs fields of dimension 1 (i.e. a scalar field)
-mfu   = gf.MeshFem(m, 1)
+mfu = gf.MeshFem(m, 1)
 mfrhs = gf.MeshFem(m, 1)
 # assign the P2 fem to all convexes of the both MeshFem
-mfu.set_fem(gf.Fem('FEM_PK(2,2)'))
-mfrhs.set_fem(gf.Fem('FEM_PK(2,2)'))
+mfu.set_fem(gf.Fem("FEM_PK(2,2)"))
+mfrhs.set_fem(gf.Fem("FEM_PK(2,2)"))
 
 #  Integration method used
-mim = gf.MeshIm(m, gf.Integ('IM_TRIANGLE(4)'))
+mim = gf.MeshIm(m, gf.Integ("IM_TRIANGLE(4)"))
 
 # Boundary selection
-flst  = m.outer_faces()
-fnor  = m.normal_of_faces(flst)
-ftop  = np.compress(abs(fnor[1,:]-1) < 1e-14, flst, axis=1)
-fbottom  = np.compress(abs(fnor[1,:]+1) < 1e-14, flst, axis=1)
+flst = m.outer_faces()
+fnor = m.normal_of_faces(flst)
+ftop = np.compress(abs(fnor[1, :] - 1) < 1e-14, flst, axis=1)
+fbottom = np.compress(abs(fnor[1, :] + 1) < 1e-14, flst, axis=1)
 
 # Mark it as boundary
 DIRICHLET_BOUNDARY = 1
@@ -64,50 +67,48 @@ m.set_region(CONTACT_BOUNDARY, fbottom)
 
 
 # Interpolate the source term
-F = mfrhs.eval('x+3*y/2')
+F = mfrhs.eval("x+3*y/2")
 
 # Model
-md = gf.Model('real')
+md = gf.Model("real")
 md.add_initialized_data("theta", [theta])
 md.add_initialized_data("thr", [thr])
 md.add_initialized_data("gamma0", [gamma0])
-md.add_fem_variable('u', mfu)
-md.add_macro("gh", "gamma0/element_size");
-md.add_macro("dnu", "Grad_u.Normal");
-md.add_macro("dnv", "Grad_Test_u.Normal");
+md.add_fem_variable("u", mfu)
+md.add_macro("gh", "gamma0/element_size")
+md.add_macro("dnu", "Grad_u.Normal")
+md.add_macro("dnv", "Grad_Test_u.Normal")
 # md.add_macro("P(x,y)", "Ball_projection(x,y)"); # Do not work in old versions
-md.add_macro("P(x,y)", "max(min(x,y),-y)"); # Projection definition
+md.add_macro("P(x,y)", "max(min(x,y),-y)")
+# Projection definition
 
 # Laplacian term on u
-md.add_linear_term(mim, 'Grad_u.Grad_Test_u')
+md.add_linear_term(mim, "Grad_u.Grad_Test_u")
 
 # Nitsche terms for the Tresca condition
-md.add_nonlinear_term(mim, '-(theta/gh)*dnu*dnv',
-                      CONTACT_BOUNDARY)
-md.add_nonlinear_term(mim, '(1/gh)*P(dnu-gh*u,thr)*(theta*dnv-gh*Test_u)',
-                      CONTACT_BOUNDARY)
-
+md.add_nonlinear_term(mim, "-(theta/gh)*dnu*dnv", CONTACT_BOUNDARY)
+md.add_nonlinear_term(
+    mim, "(1/gh)*P(dnu-gh*u,thr)*(theta*dnv-gh*Test_u)", CONTACT_BOUNDARY
+)
 
 
 # Volumic source term
-md.add_initialized_fem_data('VolumicData', mfrhs, F)
-md.add_source_term_brick(mim, 'u', 'VolumicData')
+md.add_initialized_fem_data("VolumicData", mfrhs, F)
+md.add_source_term_brick(mim, "u", "VolumicData")
 
 # Dirichlet condition on the top.
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, DIRICHLET_BOUNDARY)
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, DIRICHLET_BOUNDARY)
 
 
 # Assembly of the linear system and solve.
-md.solve('max_res', 1e-8, 'max_iter', 100, 'noisy')
+md.solve("max_res", 1e-8, "max_iter", 100, "noisy")
 
 # Main unknown
-U = md.variable('u')
+U = md.variable("u")
 
 # Export data
-mfu.export_to_pos('tresca.pos', U,'Computed solution')
-mfu.export_to_vtk('tresca.vtk', U,'Computed solution')
-print('You can view the solution with (for example):')
-print('gmsh tresca.pos')
+mfu.export_to_pos("tresca.pos", U, "Computed solution")
+mfu.export_to_vtk("tresca.vtk", U, "Computed solution")
+print("You can view the solution with (for example):")
+print("gmsh tresca.pos")
 print("mayavi2 -d tresca.vtk -f WarpScalar -m Surface")
-
-
diff --git a/interface/tests/python/demo_tripod.py 
b/interface/tests/python/demo_tripod.py
index 4be1e72..dd6f910 100644
--- a/interface/tests/python/demo_tripod.py
+++ b/interface/tests/python/demo_tripod.py
@@ -31,109 +31,116 @@
 import getfem as gf
 import numpy as np
 
-with_graphics=True
+with_graphics = True
 try:
     import getfem_tvtk
 except:
     print("\n** Could NOT import getfem_tvtk -- graphical output disabled 
**\n")
     import time
+
     time.sleep(2)
-    with_graphics=False
+    with_graphics = False
 
 
-m=gf.Mesh('import','gid','../meshes/tripod.GiD.msh')
-print('done!')
-mfu=gf.MeshFem(m,3) # displacement
-mfp=gf.MeshFem(m,1) # pressure
-mfd=gf.MeshFem(m,1) # data
-mim=gf.MeshIm(m, gf.Integ('IM_TETRAHEDRON(5)'))
+m = gf.Mesh("import", "gid", "../meshes/tripod.GiD.msh")
+print("done!")
+mfu = gf.MeshFem(m, 3)  # displacement
+mfp = gf.MeshFem(m, 1)  # pressure
+mfd = gf.MeshFem(m, 1)  # data
+mim = gf.MeshIm(m, gf.Integ("IM_TETRAHEDRON(5)"))
 degree = 2
 linear = False
-incompressible = False # ensure that degree > 1 when incompressible is on..
-
-mfu.set_fem(gf.Fem('FEM_PK(3,%d)' % (degree,)))
-mfd.set_fem(gf.Fem('FEM_PK(3,0)'))
-mfp.set_fem(gf.Fem('FEM_PK_DISCONTINUOUS(3,0)'))
-
-print('nbcvs=%d, nbpts=%d, qdim=%d, fem = %s, nbdof=%d' % \
-      (m.nbcvs(), m.nbpts(), mfu.qdim(), mfu.fem()[0].char(), mfu.nbdof()))
-
-P=m.pts()
-print('test', P[1,:])
-ctop=(abs(P[1,:] - 13) < 1e-6)
-cbot=(abs(P[1,:] + 10) < 1e-6)
-pidtop=np.compress(ctop, list(range(0, m.nbpts())))
-pidbot=np.compress(cbot, list(range(0, m.nbpts())))
-
-ftop=m.faces_from_pid(pidtop)
-fbot=m.faces_from_pid(pidbot)
+incompressible = False  # ensure that degree > 1 when incompressible is on..
+
+mfu.set_fem(gf.Fem("FEM_PK(3,%d)" % (degree,)))
+mfd.set_fem(gf.Fem("FEM_PK(3,0)"))
+mfp.set_fem(gf.Fem("FEM_PK_DISCONTINUOUS(3,0)"))
+
+print(
+    "nbcvs=%d, nbpts=%d, qdim=%d, fem = %s, nbdof=%d"
+    % (m.nbcvs(), m.nbpts(), mfu.qdim(), mfu.fem()[0].char(), mfu.nbdof())
+)
+
+P = m.pts()
+print("test", P[1, :])
+ctop = abs(P[1, :] - 13) < 1e-6
+cbot = abs(P[1, :] + 10) < 1e-6
+pidtop = np.compress(ctop, list(range(0, m.nbpts())))
+pidbot = np.compress(cbot, list(range(0, m.nbpts())))
+
+ftop = m.faces_from_pid(pidtop)
+fbot = m.faces_from_pid(pidbot)
 NEUMANN_BOUNDARY = 1
 DIRICHLET_BOUNDARY = 2
 
-m.set_region(NEUMANN_BOUNDARY,ftop)
-m.set_region(DIRICHLET_BOUNDARY,fbot)
+m.set_region(NEUMANN_BOUNDARY, ftop)
+m.set_region(DIRICHLET_BOUNDARY, fbot)
 
-E=1e3
-Nu=0.3
-Lambda = E*Nu/((1+Nu)*(1-2*Nu))
-Mu =E/(2*(1+Nu))
+E = 1e3
+Nu = 0.3
+Lambda = E * Nu / ((1 + Nu) * (1 - 2 * Nu))
+Mu = E / (2 * (1 + Nu))
 
 
-md = gf.Model('real')
-md.add_fem_variable('u', mfu)
+md = gf.Model("real")
+md.add_fem_variable("u", mfu)
 if linear:
-    md.add_initialized_data('cmu', Mu)
-    md.add_initialized_data('clambda', Lambda)
-    md.add_isotropic_linearized_elasticity_brick(mim, 'u', 'clambda', 'cmu')
+    md.add_initialized_data("cmu", Mu)
+    md.add_initialized_data("clambda", Lambda)
+    md.add_isotropic_linearized_elasticity_brick(mim, "u", "clambda", "cmu")
     if incompressible:
-        md.add_fem_variable('p', mfp)
-        md.add_linear_incompressibility_brick(mim, 'u', 'p')
+        md.add_fem_variable("p", mfp)
+        md.add_linear_incompressibility_brick(mim, "u", "p")
 else:
-    md.add_initialized_data('params', [Lambda, Mu]);
+    md.add_initialized_data("params", [Lambda, Mu])
     if incompressible:
-        lawname = 'Incompressible Mooney Rivlin';
-        md.add_finite_strain_elasticity_brick(mim, lawname, 'u', 'params')
-        md.add_fem_variable('p', mfp);
-        md.add_finite_strain_incompressibility_brick(mim, 'u', 'p');
+        lawname = "Incompressible Mooney Rivlin"
+        md.add_finite_strain_elasticity_brick(mim, lawname, "u", "params")
+        md.add_fem_variable("p", mfp)
+        md.add_finite_strain_incompressibility_brick(mim, "u", "p")
     else:
-        lawname = 'SaintVenant Kirchhoff';
-        md.add_finite_strain_elasticity_brick(mim, lawname, 'u', 'params');
-  
+        lawname = "SaintVenant Kirchhoff"
+        md.add_finite_strain_elasticity_brick(mim, lawname, "u", "params")
+
 
-md.add_initialized_data('VolumicData', [0,-1,0]);
-md.add_source_term_brick(mim, 'u', 'VolumicData');
+md.add_initialized_data("VolumicData", [0, -1, 0])
+md.add_source_term_brick(mim, "u", "VolumicData")
 
 # Attach the tripod to the ground
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, 2);
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mfu, 2)
 
-print('running solve...')
-md.solve('noisy', 'max iter', 1);
-U = md.variable('u');
-print('solve done!')
+print("running solve...")
+md.solve("noisy", "max iter", 1)
+U = md.variable("u")
+print("solve done!")
 
 
-mfdu=gf.MeshFem(m,1)
-mfdu.set_fem(gf.Fem('FEM_PK_DISCONTINUOUS(3,1)'))
+mfdu = gf.MeshFem(m, 1)
+mfdu.set_fem(gf.Fem("FEM_PK_DISCONTINUOUS(3,1)"))
 if linear:
-  VM = 
md.compute_isotropic_linearized_Von_Mises_or_Tresca('u','clambda','cmu', mfdu);
+    VM = md.compute_isotropic_linearized_Von_Mises_or_Tresca(
+        "u", "clambda", "cmu", mfdu
+    )
 else:
-  VM = md.compute_finite_strain_elasticity_Von_Mises(lawname, 'u', 'params', 
mfdu);
+    VM = md.compute_finite_strain_elasticity_Von_Mises(lawname, "u", "params", 
mfdu)
 
 # post-processing
-sl=gf.Slice(('boundary',), mfu, degree)
+sl = gf.Slice(("boundary",), mfu, degree)
 
-print('Von Mises range: ', VM.min(), VM.max())
+print("Von Mises range: ", VM.min(), VM.max())
 
 # export results to VTK
-sl.export_to_vtk('tripod.vtk', 'ascii', mfdu,  VM, 'Von Mises Stress', mfu, U, 
'Displacement')
-sl.export_to_pos('tripod.pos', mfdu, VM, 'Von Mises Stress', mfu, U, 
'Displacement')
+sl.export_to_vtk(
+    "tripod.vtk", "ascii", mfdu, VM, "Von Mises Stress", mfu, U, "Displacement"
+)
+sl.export_to_pos("tripod.pos", mfdu, VM, "Von Mises Stress", mfu, U, 
"Displacement")
 
 gf.memstats()
 
-print('You can view the tripod with (for example) mayavi:')
-print('mayavi2 -d tripod.vtk -f WarpVector -m Surface')
-print('or')
-print('gmsh tripod.pos')
+print("You can view the tripod with (for example) mayavi:")
+print("mayavi2 -d tripod.vtk -f WarpVector -m Surface")
+print("or")
+print("gmsh tripod.pos")
 
 # mfu.save('tripod.mf', 'with_mesh')
 # U.tofile('tripod.U')
@@ -141,8 +148,8 @@ print('gmsh tripod.pos')
 # VM.tofile('tripod.VM')
 
 if with_graphics:
-  fig = getfem_tvtk.Figure()
-  fig.show(mfu, deformation=U, data=(mfdu,VM), deformation_scale='20%')
-  print("Press Q to continue..")
-  fig.set_colormap('tripod')
-  fig.loop()
+    fig = getfem_tvtk.Figure()
+    fig.show(mfu, deformation=U, data=(mfdu, VM), deformation_scale="20%")
+    print("Press Q to continue..")
+    fig.set_colormap("tripod")
+    fig.loop()
diff --git a/interface/tests/python/demo_tripod_alt.py 
b/interface/tests/python/demo_tripod_alt.py
index 8f39ec1..d2e6185 100644
--- a/interface/tests/python/demo_tripod_alt.py
+++ b/interface/tests/python/demo_tripod_alt.py
@@ -31,94 +31,107 @@
 from getfem import *
 from numpy import *
 
-print('importing the mesh..',)
-m=Mesh('import','gid','../meshes/tripod.GiD.msh')
-print('done!')
-mfu=MeshFem(m,3)
-mfd=MeshFem(m,1)
-mfe=MeshFem(m,1)
-mim=MeshIm(m, Integ('IM_TETRAHEDRON(5)'))
-degree = 1     
-mfu.set_fem(Fem('FEM_PK(3,%d)' % (degree,)));
-mfe.set_fem(Fem('FEM_PK_DISCONTINUOUS(3,%d,0.01)' % (degree,)))
-mfd.set_fem(Fem('FEM_PK(3,0)'))
-
-print('nbcvs=%d, nbpts=%d, qdim=%d, fem = %s, nbdof=%d' % \
-      (m.nbcvs(), m.nbpts(), mfu.qdim(), mfu.fem()[0].char(), mfu.nbdof()))
-
-P=m.pts()
-
-ctop=(abs(P[1,:] - 13) < 1e-6);
-cbot=(abs(P[1,:] + 10) < 1e-6);
-pidtop=compress(ctop, list(range(0, m.nbpts())))
-pidbot=compress(cbot, list(range(0, m.nbpts())))
-
-ftop=m.faces_from_pid(pidtop)
-fbot=m.faces_from_pid(pidbot)
+print("importing the mesh..")
+m = Mesh("import", "gid", "../meshes/tripod.GiD.msh")
+print("done!")
+mfu = MeshFem(m, 3)
+mfd = MeshFem(m, 1)
+mfe = MeshFem(m, 1)
+mim = MeshIm(m, Integ("IM_TETRAHEDRON(5)"))
+degree = 1
+mfu.set_fem(Fem("FEM_PK(3,%d)" % (degree,)))
+mfe.set_fem(Fem("FEM_PK_DISCONTINUOUS(3,%d,0.01)" % (degree,)))
+mfd.set_fem(Fem("FEM_PK(3,0)"))
+
+print(
+    "nbcvs=%d, nbpts=%d, qdim=%d, fem = %s, nbdof=%d"
+    % (m.nbcvs(), m.nbpts(), mfu.qdim(), mfu.fem()[0].char(), mfu.nbdof())
+)
+
+P = m.pts()
+
+ctop = abs(P[1, :] - 13) < 1e-6
+cbot = abs(P[1, :] + 10) < 1e-6
+pidtop = compress(ctop, list(range(0, m.nbpts())))
+pidbot = compress(cbot, list(range(0, m.nbpts())))
+
+ftop = m.faces_from_pid(pidtop)
+fbot = m.faces_from_pid(pidbot)
 NEUMANN_BOUNDARY = 1
 DIRICHLET_BOUNDARY = 2
 
-m.set_region(NEUMANN_BOUNDARY,ftop)
-m.set_region(DIRICHLET_BOUNDARY,fbot)
+m.set_region(NEUMANN_BOUNDARY, ftop)
+m.set_region(DIRICHLET_BOUNDARY, fbot)
 
-E=1e3
-Nu=0.3
-Lambda = E*Nu/((1+Nu)*(1-2*Nu))
-Mu =E/(2*(1+Nu))
+E = 1e3
+Nu = 0.3
+Lambda = E * Nu / ((1 + Nu) * (1 - 2 * Nu))
+Mu = E / (2 * (1 + Nu))
 
-F = asm_boundary_source(NEUMANN_BOUNDARY, mim, 
mfu,mfd,repeat([[0],[-100],[0]], mfd.nbdof(),1))
-K = asm_linear_elasticity(mim, mfu, mfd, repeat([Lambda], mfd.nbdof()),
-                          repeat([Mu], mfd.nbdof()));
+F = asm_boundary_source(
+    NEUMANN_BOUNDARY, mim, mfu, mfd, repeat([[0], [-100], [0]], mfd.nbdof(), 1)
+)
+K = asm_linear_elasticity(
+    mim, mfu, mfd, repeat([Lambda], mfd.nbdof()), repeat([Mu], mfd.nbdof())
+)
 
 # handle Dirichlet condition
-(H,R)=asm_dirichlet(DIRICHLET_BOUNDARY, mim, mfu, mfd,
-                    mfd.eval('identity(3)',globals(),locals()),
-                    mfd.eval('[0,0,0]'));
-(N,U0)=H.dirichlet_nullspace(R)
-Nt=Spmat('copy',N); Nt.transpose()
-KK=Nt*K*N
-FF=Nt*F
+(H, R) = asm_dirichlet(
+    DIRICHLET_BOUNDARY,
+    mim,
+    mfu,
+    mfd,
+    mfd.eval("identity(3)", globals(), locals()),
+    mfd.eval("[0,0,0]"),
+)
+(N, U0) = H.dirichlet_nullspace(R)
+Nt = Spmat("copy", N)
+Nt.transpose()
+KK = Nt * K * N
+FF = Nt * F
 
 # solve ...
 print("preconditioner..")
-P=Precond('ildlt',KK)
+P = Precond("ildlt", KK)
 print("solving..."),
-UU=linsolve_cg(KK,FF,P)
+UU = linsolve_cg(KK, FF, P)
 print("done!")
-U=N*UU+U0
+U = N * UU + U0
 
 # post-processing
-sl=Slice(('boundary',), mfu, degree)
+sl = Slice(("boundary",), mfu, degree)
 
 # compute the Von Mises Stress
-DU=compute_gradient(mfu,U,mfe)
-VM=zeros((DU.shape[2],),'d')
-Sigma=DU
+DU = compute_gradient(mfu, U, mfe)
+VM = zeros((DU.shape[2],), "d")
+Sigma = DU
 
 for i in range(0, DU.shape[2]):
-  d = array(DU[:,:,i]);
-  E = (d+transpose(d))*0.5
-  Sigma[:,:,i]=E
-  VM[i] = sum(E.ravel()**2) - (1./3.)*sum(diagonal(E))**2
+    d = array(DU[:, :, i])
+    E = (d + transpose(d)) * 0.5
+    Sigma[:, :, i] = E
+    VM[i] = sum(E.ravel() ** 2) - (1.0 / 3.0) * sum(diagonal(E)) ** 2
 
-print('Von Mises range: ', VM.min(), VM.max())
+print("Von Mises range: ", VM.min(), VM.max())
 
 # export results to VTK you can use
 # i.e. with  "mayavi2 -d tripod.vtk -f WarpScalar -m Surface"
-sl.export_to_vtk('tripod.vtk', 'ascii',mfe,  VM,'Von Mises Stress', mfu, U, 
'Displacement')
+sl.export_to_vtk(
+    "tripod.vtk", "ascii", mfe, VM, "Von Mises Stress", mfu, U, "Displacement"
+)
 
-sl.export_to_vtk('tripod_edges.vtk','edges')
+sl.export_to_vtk("tripod_edges.vtk", "edges")
 
 # export to OpenDX
-sl.export_to_dx('tripod.dx', 'ascii', mfe, VM, 'Von Mises Stress')
+sl.export_to_dx("tripod.dx", "ascii", mfe, VM, "Von Mises Stress")
 # export the displacement and the stress tensor field
 # can be viewed with mayavi -d ./tripod_ev.vtk -f WarpVector -m TensorGlyphs
-SigmaSL = compute_interpolate_on(mfe, Sigma, sl);
-sl.export_to_vtk('tripod_ev.vtk', mfu, U, 'Displacement', SigmaSL, 'stress')
+SigmaSL = compute_interpolate_on(mfe, Sigma, sl)
+sl.export_to_vtk("tripod_ev.vtk", mfu, U, "Displacement", SigmaSL, "stress")
 # export to Gmsh POS
-sl.export_to_pos('tripod.pos', mfe, VM, 'Von Mises Stress', mfu, U, 
'Displacement')
+sl.export_to_pos("tripod.pos", mfe, VM, "Von Mises Stress", mfu, U, 
"Displacement")
 
-print('You can view the tripod with (for example) mayavi:')
-print('mayavi2 -d tripod.vtk -f WarpScalar -m Surface')
-print('or')
-print('gmsh tripod.pos')
+print("You can view the tripod with (for example) mayavi:")
+print("mayavi2 -d tripod.vtk -f WarpScalar -m Surface")
+print("or")
+print("gmsh tripod.pos")
diff --git a/interface/tests/python/demo_unit_disk.py 
b/interface/tests/python/demo_unit_disk.py
index 26c8c2f..8e7737c 100644
--- a/interface/tests/python/demo_unit_disk.py
+++ b/interface/tests/python/demo_unit_disk.py
@@ -32,11 +32,11 @@ import getfem as gf
 import numpy as np
 
 ## Parameters
-h = 0.1 # approximate diameter of the elements.
+h = 0.1  # approximate diameter of the elements.
 
 # Create a unit disk mesh
-mo = gf.MesherObject('ball', [1.0, 1.0], 1.0)
-mesh = gf.Mesh('generate', mo, h, 2)
+mo = gf.MesherObject("ball", [1.0, 1.0], 1.0)
+mesh = gf.Mesh("generate", mo, h, 2)
 mesh.translate([-1.0, -1.0])
 
 # Create a MeshFem for u and rhs fields of dimension 1 (i.e. a scalar field)
@@ -48,7 +48,7 @@ mfu.set_classical_fem(elements_degree)
 mfrhs.set_classical_fem(elements_degree)
 
 #  Integration method used
-mim = gf.MeshIm(mesh, pow(elements_degree,2))
+mim = gf.MeshIm(mesh, pow(elements_degree, 2))
 
 # Boundary selection
 flst = mesh.outer_faces()
@@ -58,44 +58,45 @@ DIRICHLET_BOUNDARY = 1
 mesh.set_region(DIRICHLET_BOUNDARY, flst)
 
 # Interpolate the exact solution (Assuming mfu is a Lagrange fem)
-Ue = mfu.eval('(1-x*x-y*y)/4')
+Ue = mfu.eval("(1-x*x-y*y)/4")
 
 # Interpolate the source term
-F = mfrhs.eval('1')
+F = mfrhs.eval("1")
 
 # Model
-md = gf.Model('real')
+md = gf.Model("real")
 
 # Main unknown
-md.add_fem_variable('u', mfu)
+md.add_fem_variable("u", mfu)
 
 # Laplacian term on u
-md.add_Laplacian_brick(mim, 'u')
+md.add_Laplacian_brick(mim, "u")
 
 # Volumic source term
-md.add_initialized_fem_data('VolumicData', mfrhs, F)
-md.add_source_term_brick(mim, 'u', 'VolumicData')
+md.add_initialized_fem_data("VolumicData", mfrhs, F)
+md.add_source_term_brick(mim, "u", "VolumicData")
 
 # Dirichlet condition on the boundary.
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', elements_degree - 1, 
DIRICHLET_BOUNDARY)
+md.add_Dirichlet_condition_with_multipliers(
+    mim, "u", elements_degree - 1, DIRICHLET_BOUNDARY
+)
 
 # Assembly of the linear system and solve.
 md.solve()
 
 # Main unknown
-U = md.variable('u')
-L2error = gf.compute(mfu, U-Ue, 'L2 norm', mim)
-H1error = gf.compute(mfu, U-Ue, 'H1 norm', mim)
-print('Error in L2 norm : ', L2error)
-print('Error in H1 norm : ', H1error)
+U = md.variable("u")
+L2error = gf.compute(mfu, U - Ue, "L2 norm", mim)
+H1error = gf.compute(mfu, U - Ue, "H1 norm", mim)
+print("Error in L2 norm : ", L2error)
+print("Error in H1 norm : ", H1error)
 
 # Export data
-mfu.export_to_pos('unit_disk.pos', Ue,'Exact solution',
-                                    U,'Computed solution')
-print('You can view the solution with (for example):')
-print('gmsh unit_disk.pos')
+mfu.export_to_pos("unit_disk.pos", Ue, "Exact solution", U, "Computed 
solution")
+print("You can view the solution with (for example):")
+print("gmsh unit_disk.pos")
 
 
-if (H1error > 1e-3):
-    print('Error too large !')
+if H1error > 1e-3:
+    print("Error too large !")
     exit(1)
diff --git a/interface/tests/python/demo_wave.py 
b/interface/tests/python/demo_wave.py
index 46702cc..f58c20f 100644
--- a/interface/tests/python/demo_wave.py
+++ b/interface/tests/python/demo_wave.py
@@ -30,64 +30,66 @@ from numpy import *
 from getfem import *
 import os
 
-make_check=('srcdir' in os.environ);
+make_check = "srcdir" in os.environ
 
-filename='../meshes/holed_disc_with_quadratic_2D_triangles.msh';
-if (make_check):
-    filename=os.environ['srcdir']+'/'+filename
+filename = "../meshes/holed_disc_with_quadratic_2D_triangles.msh"
+if make_check:
+    filename = os.environ["srcdir"] + "/" + filename
 
 ## Parameters
-PK=3; k = 1.;
+PK = 3
+k = 1.0
 
 ## Mesh and MeshFems
-m=Mesh('import','gid',filename);
-mfu=MeshFem(m,1);
-mfu.set_fem(Fem('FEM_PK(2,%d)' % (PK,)));
-mfd=MeshFem(m,1);
-mfd.set_fem(Fem('FEM_PK(2,%d)' % (PK,)));
-mim=MeshIm(m, Integ('IM_TRIANGLE(13)'));
+m = Mesh("import", "gid", filename)
+mfu = MeshFem(m, 1)
+mfu.set_fem(Fem("FEM_PK(2,%d)" % (PK,)))
+mfd = MeshFem(m, 1)
+mfd.set_fem(Fem("FEM_PK(2,%d)" % (PK,)))
+mim = MeshIm(m, Integ("IM_TRIANGLE(13)"))
 
 ## Boundary selection
-P=m.pts(); # get list of mesh points coordinates
-Psqr=sum(P*P, 0);
-cobj=(Psqr < 1*1+1e-6);
-cout=(Psqr > 10*10-1e-2);
-pidobj=compress(cobj, list(range(0, m.nbpts())))
-pidout=compress(cout, list(range(0, m.nbpts())))
-fobj=m.faces_from_pid(pidobj)
-fout=m.faces_from_pid(pidout)
+P = m.pts()
+# get list of mesh points coordinates
+Psqr = sum(P * P, 0)
+cobj = Psqr < 1 * 1 + 1e-6
+cout = Psqr > 10 * 10 - 1e-2
+pidobj = compress(cobj, list(range(0, m.nbpts())))
+pidout = compress(cout, list(range(0, m.nbpts())))
+fobj = m.faces_from_pid(pidobj)
+fout = m.faces_from_pid(pidout)
 ROBIN_BOUNDARY = 1
 DIRICHLET_BOUNDARY = 2
-m.set_region(DIRICHLET_BOUNDARY,fobj)
-m.set_region(ROBIN_BOUNDARY,fout)
+m.set_region(DIRICHLET_BOUNDARY, fobj)
+m.set_region(ROBIN_BOUNDARY, fout)
 
 ## Interpolate the exact solution on mfd (assuming it is a Lagrange fem)
-wave_expr = ('cos(%f*y+.2)+complex(0.,1.)*sin(%f*y+.2)' % (k,k));
-Uinc=mfd.eval(wave_expr,globals(),locals());
+wave_expr = "cos(%f*y+.2)+complex(0.,1.)*sin(%f*y+.2)" % (k, k)
+Uinc = mfd.eval(wave_expr, globals(), locals())
 
 ## Model Bricks
-md = Model('complex')
-md.add_fem_variable('u', mfu)
-md.add_initialized_data('k', [k]);
-md.add_Helmholtz_brick(mim, 'u', 'k');
-md.add_initialized_data('Q', [complex(0.,1.)*k]);
-md.add_Fourier_Robin_brick(mim, 'u', 'Q', ROBIN_BOUNDARY);
-md.add_initialized_fem_data('DirichletData', mfd, Uinc);
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mfu, DIRICHLET_BOUNDARY,
-                                            'DirichletData');
-#md.add_Dirichlet_condition_with_penalization(mim, 'u', 1e12,
+md = Model("complex")
+md.add_fem_variable("u", mfu)
+md.add_initialized_data("k", [k])
+md.add_Helmholtz_brick(mim, "u", "k")
+md.add_initialized_data("Q", [complex(0.0, 1.0) * k])
+md.add_Fourier_Robin_brick(mim, "u", "Q", ROBIN_BOUNDARY)
+md.add_initialized_fem_data("DirichletData", mfd, Uinc)
+md.add_Dirichlet_condition_with_multipliers(
+    mim, "u", mfu, DIRICHLET_BOUNDARY, "DirichletData"
+)
+# md.add_Dirichlet_condition_with_penalization(mim, 'u', 1e12,
 #                                             DIRICHLET_BOUNDARY,
 #                                             'DirichletData');
 
 ## Solving the problem
-md.solve();
-U = md.variable('u');
+md.solve()
+U = md.variable("u")
 
-if (not(make_check)):
+if not (make_check):
 
-    sl=Slice(('none',), mfu, 8)
-    sl.export_to_vtk('wave.vtk', mfu, real(U), 'rWave',
-                     mfu, imag(U), 'iWave')
+    sl = Slice(("none",), mfu, 8)
+    sl.export_to_vtk("wave.vtk", mfu, real(U), "rWave", mfu, imag(U), "iWave")
 
-    print('You can view the solution with (for instance):')
-    print('mayavi2 -d wave.vtk -f WarpScalar -m Surface')
+    print("You can view the solution with (for instance):")
+    print("mayavi2 -d wave.vtk -f WarpScalar -m Surface")
diff --git a/interface/tests/python/demo_wave_equation.py 
b/interface/tests/python/demo_wave_equation.py
index ace88eb..41077d0 100644
--- a/interface/tests/python/demo_wave_equation.py
+++ b/interface/tests/python/demo_wave_equation.py
@@ -32,12 +32,15 @@ import getfem as gf
 import os
 
 NX = 20
-m = gf.Mesh('cartesian', np.arange(0., 1.+1./NX,1./NX),
-            np.arange(0., 1.+1./NX,1./NX));
+m = gf.Mesh(
+    "cartesian",
+    np.arange(0.0, 1.0 + 1.0 / NX, 1.0 / NX),
+    np.arange(0.0, 1.0 + 1.0 / NX, 1.0 / NX),
+)
 
 
 ## create a mesh_fem of for a field of dimension 1 (i.e. a scalar field)
-mf = gf.MeshFem(m,1)
+mf = gf.MeshFem(m, 1)
 mf.set_classical_fem(2)
 
 ## Integration which will be used
@@ -49,57 +52,59 @@ border = m.outer_faces()
 m.set_region(1, border)
 
 ## Interpolate the initial data
-U0 = mf.eval('y*(y-1.)*x*(x-1.)*x*x')
-V0 = 0.*U0
+U0 = mf.eval("y*(y-1.)*x*(x-1.)*x*x")
+V0 = 0.0 * U0
 
-md=gf.Model('real');
-md.add_fem_variable('u', mf);
-md.add_Laplacian_brick(mim, 'u');
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mf, 1);
+md = gf.Model("real")
+md.add_fem_variable("u", mf)
+md.add_Laplacian_brick(mim, "u")
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mf, 1)
 # md.add_Dirichlet_condition_with_penalization(mim, 'u', 1E9, 1);
 # md.add_Dirichlet_condition_with_simplification('u', 1);
 
 ## Transient part.
-T = 5.0;
-dt = 0.025;
-beta = 0.25;
-gamma = 0.5;
+T = 5.0
+dt = 0.025
+beta = 0.25
+gamma = 0.5
 
-md.add_Newmark_scheme('u', beta, gamma)
-md.add_mass_brick(mim, 'Dot2_u')
+md.add_Newmark_scheme("u", beta, gamma)
+md.add_mass_brick(mim, "Dot2_u")
 md.set_time_step(dt)
 
 ## Initial data.
-md.set_variable('Previous_u',  U0)
-md.set_variable('Previous_Dot_u',  V0)
+md.set_variable("Previous_u", U0)
+md.set_variable("Previous_Dot_u", V0)
 
 ## Initialisation of the acceleration 'Previous_Dot2_u'
-md.perform_init_time_derivative(dt/2.)
+md.perform_init_time_derivative(dt / 2.0)
 md.solve()
 
-A0 = md.variable('Previous_Dot2_u')
+A0 = md.variable("Previous_Dot2_u")
 
 
-os.system('mkdir results');
-mf.export_to_vtk('results/displacement_0.vtk', U0)
-mf.export_to_vtk('results/velocity_0.vtk', V0)
-mf.export_to_vtk('results/acceleration_0.vtk', A0)
+os.system("mkdir results")
+mf.export_to_vtk("results/displacement_0.vtk", U0)
+mf.export_to_vtk("results/velocity_0.vtk", V0)
+mf.export_to_vtk("results/acceleration_0.vtk", A0)
 
 ## Iterations
-n = 1;
-for t in np.arange(0.,T,dt):
-  print ('Time step %g' % t)
-  md.solve();
-  U = md.variable('u')
-  V = md.variable('Dot_u')
-  A = md.variable('Dot2_u')
-  
-  mf.export_to_vtk('results/displacement_%d.vtk' % n, U)
-  mf.export_to_vtk('results/velocity_%d.vtk' % n, V)
-  mf.export_to_vtk('results/acceleration_%d.vtk' % n, A)
-
-  n += 1
-  md.shift_variables_for_time_integration()
-  
-
-print ('You can view solutions with for instance:\nmayavi2 -d 
results/displacement_0.vtk -f WarpScalar -m Surface')
+n = 1
+for t in np.arange(0.0, T, dt):
+    print("Time step %g" % t)
+    md.solve()
+    U = md.variable("u")
+    V = md.variable("Dot_u")
+    A = md.variable("Dot2_u")
+
+    mf.export_to_vtk("results/displacement_%d.vtk" % n, U)
+    mf.export_to_vtk("results/velocity_%d.vtk" % n, V)
+    mf.export_to_vtk("results/acceleration_%d.vtk" % n, A)
+
+    n += 1
+    md.shift_variables_for_time_integration()
+
+
+print(
+    "You can view solutions with for instance:\nmayavi2 -d 
results/displacement_0.vtk -f WarpScalar -m Surface"
+)
diff --git a/interface/tests/python/demo_wheel_contact.py 
b/interface/tests/python/demo_wheel_contact.py
index 3dc5071..d5ded64 100644
--- a/interface/tests/python/demo_wheel_contact.py
+++ b/interface/tests/python/demo_wheel_contact.py
@@ -27,57 +27,75 @@
 
 import getfem as gf
 import numpy as np
-gf.util('trace level', 1)    # No trace for mesh generation nor for assembly
 
-export_mesh = True;
-Dirichlet_version = False; # Use a dirichlet condition instead of a global load
+gf.util("trace level", 1)  # No trace for mesh generation nor for assembly
+
+export_mesh = True
+Dirichlet_version = False
+# Use a dirichlet condition instead of a global load
 
 #
 # Physical parameters
 #
-E = 21E6                         # Young Modulus (N/cm^2)
-nu = 0.3                         # Poisson ratio
-clambda = E*nu/((1+nu)*(1-2*nu)) # First Lame coefficient (N/cm^2)
-cmu = E/(2*(1+nu))               # Second Lame coefficient (N/cm^2)
-clambdastar = 2*clambda*cmu/(clambda+2*cmu) # Lame coefficient for Plane stress
-applied_force = 1E7              # Force at the hole boundary (N)
+E = 21e6  # Young Modulus (N/cm^2)
+nu = 0.3  # Poisson ratio
+clambda = E * nu / ((1 + nu) * (1 - 2 * nu))  # First Lame coefficient (N/cm^2)
+cmu = E / (2 * (1 + nu))  # Second Lame coefficient (N/cm^2)
+clambdastar = (
+    2 * clambda * cmu / (clambda + 2 * cmu)
+)  # Lame coefficient for Plane stress
+applied_force = 1e7  # Force at the hole boundary (N)
 
 
 #
 # Numerical parameters
 #
-h = 1                    # Approximate mesh size
-elements_degree = 2      # Degree of the finite element methods
-gamma0 = 1./E;           # Augmentation parameter for the augmented Lagrangian 
+h = 1  # Approximate mesh size
+elements_degree = 2  # Degree of the finite element methods
+gamma0 = 1.0 / E
+# Augmentation parameter for the augmented Lagrangian
 
 #
 # Mesh generation. Meshes can also been imported from several formats.
 #
-mo1 = gf.MesherObject('ball', [0., 15.], 15.)
-mo2 = gf.MesherObject('ball', [0., 15.], 8.)
-mo3 = gf.MesherObject('set minus', mo1, mo2)
+mo1 = gf.MesherObject("ball", [0.0, 15.0], 15.0)
+mo2 = gf.MesherObject("ball", [0.0, 15.0], 8.0)
+mo3 = gf.MesherObject("set minus", mo1, mo2)
 
-print('Meshes generation')
-mesh1 = gf.Mesh('generate', mo3, h, 2)
-mesh2 = 
gf.Mesh('import','structured','GT="GT_PK(2,1)";SIZES=[30,10];NOISED=0;NSUBDIV=[%d,%d];'
 % (int(30/h)+1, int(10/h)+1));
-mesh2.translate([-15.,-10.])
+print("Meshes generation")
+mesh1 = gf.Mesh("generate", mo3, h, 2)
+mesh2 = gf.Mesh(
+    "import",
+    "structured",
+    'GT="GT_PK(2,1)";SIZES=[30,10];NOISED=0;NSUBDIV=[%d,%d];'
+    % (int(30 / h) + 1, int(10 / h) + 1),
+)
+mesh2.translate([-15.0, -10.0])
 
 
-if (export_mesh):
-  mesh1.export_to_vtk('mesh1.vtk')
-  mesh2.export_to_vtk('mesh2.vtk')
-  print('\nYou can view the meshes for instance with')
-  print('mayavi2  -d mesh1.vtk -f ExtractEdges -m Surface -d mesh2.vtk -f 
ExtractEdges -m Surface \n')
+if export_mesh:
+    mesh1.export_to_vtk("mesh1.vtk")
+    mesh2.export_to_vtk("mesh2.vtk")
+    print("\nYou can view the meshes for instance with")
+    print(
+        "mayavi2  -d mesh1.vtk -f ExtractEdges -m Surface -d mesh2.vtk -f 
ExtractEdges -m Surface \n"
+    )
 
 
 #
 # Boundary selection
 #
 fb1 = mesh1.outer_faces_in_box([-8.1, 6.9], [8.1, 23.1])  # Boundary of the 
hole
-fb2 = mesh1.outer_faces_with_direction([0., -1.], np.pi/4.5) # Contact 
boundary of the wheel
-fb3 = mesh2.outer_faces_with_direction([0., -1.], 0.01)   # Bottom boundary of 
the foundation
+fb2 = mesh1.outer_faces_with_direction(
+    [0.0, -1.0], np.pi / 4.5
+)  # Contact boundary of the wheel
+fb3 = mesh2.outer_faces_with_direction(
+    [0.0, -1.0], 0.01
+)  # Bottom boundary of the foundation
 
-HOLE_BOUND=1; CONTACT_BOUND=2; BOTTOM_BOUND=3;
+HOLE_BOUND = 1
+CONTACT_BOUND = 2
+BOTTOM_BOUND = 3
 
 mesh1.set_region(HOLE_BOUND, fb1)
 mesh1.set_region(CONTACT_BOUND, fb2)
@@ -92,9 +110,9 @@ mesh2.set_region(BOTTOM_BOUND, fb3)
 mfu1 = gf.MeshFem(mesh1, 2)
 mfu1.set_classical_fem(elements_degree)
 mflambda = gf.MeshFem(mesh1, 2)
-mflambda.set_classical_fem(elements_degree-1)
+mflambda.set_classical_fem(elements_degree - 1)
 mflambda_C = gf.MeshFem(mesh1, 1)
-mflambda_C.set_classical_fem(elements_degree-1)
+mflambda_C.set_classical_fem(elements_degree - 1)
 mfu2 = gf.MeshFem(mesh2, 2)
 mfu2.set_classical_fem(elements_degree)
 mfvm1 = gf.MeshFem(mesh1, 1)
@@ -102,7 +120,7 @@ mfvm1.set_classical_discontinuous_fem(elements_degree)
 mfvm2 = gf.MeshFem(mesh2, 1)
 mfvm2.set_classical_discontinuous_fem(elements_degree)
 mim1 = gf.MeshIm(mesh1, 4)
-mim1c = gf.MeshIm(mesh1, gf.Integ('IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(4),2)'))
+mim1c = gf.MeshIm(mesh1, gf.Integ("IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(4),2)"))
 mim2 = gf.MeshIm(mesh2, 4)
 
 
@@ -110,59 +128,96 @@ mim2 = gf.MeshIm(mesh2, 4)
 # Model definition
 #
 
-md=gf.Model('real');
-md.add_fem_variable('u1', mfu1)       # Displacement of the structure 1
-md.add_fem_variable('u2', mfu2)       # Displacement of the structure 2
-
-md.add_initialized_data('cmu', [cmu])
-md.add_initialized_data('clambdastar', [clambdastar])
-md.add_isotropic_linearized_elasticity_brick(mim1, 'u1', 'clambdastar', 'cmu')
-md.add_isotropic_linearized_elasticity_brick(mim2, 'u2', 'clambdastar', 'cmu')
-md.add_Dirichlet_condition_with_multipliers(mim2, 'u2', elements_degree-1, 
BOTTOM_BOUND)
+md = gf.Model("real")
+md.add_fem_variable("u1", mfu1)  # Displacement of the structure 1
+md.add_fem_variable("u2", mfu2)  # Displacement of the structure 2
 
+md.add_initialized_data("cmu", [cmu])
+md.add_initialized_data("clambdastar", [clambdastar])
+md.add_isotropic_linearized_elasticity_brick(mim1, "u1", "clambdastar", "cmu")
+md.add_isotropic_linearized_elasticity_brick(mim2, "u2", "clambdastar", "cmu")
+md.add_Dirichlet_condition_with_multipliers(
+    mim2, "u2", elements_degree - 1, BOTTOM_BOUND
+)
 
 
 # Contact condition (augmented Lagrangian)
-md.add_initialized_data('gamma0', [gamma0])
-md.add_interpolate_transformation_from_expression('Proj1', mesh1, mesh2, 
'[X(1);0]')
-md.add_filtered_fem_variable('lambda1', mflambda_C, CONTACT_BOUND)
-md.add_nonlinear_term(mim1c, 'lambda1*(Test_u1.[0;1])'
-                                        
'-lambda1*(Interpolate(Test_u2,Proj1).[0;1])', CONTACT_BOUND)
-md.add_nonlinear_term(mim1c, '-(gamma0*element_size)*(lambda1 + 
neg_part(lambda1+(1/(gamma0*element_size))*((u1-Interpolate(u2,Proj1)+X-Interpolate(X,Proj1)).[0;1])))*Test_lambda1',
 CONTACT_BOUND);
+md.add_initialized_data("gamma0", [gamma0])
+md.add_interpolate_transformation_from_expression("Proj1", mesh1, mesh2, 
"[X(1);0]")
+md.add_filtered_fem_variable("lambda1", mflambda_C, CONTACT_BOUND)
+md.add_nonlinear_term(
+    mim1c,
+    "lambda1*(Test_u1.[0;1])" "-lambda1*(Interpolate(Test_u2,Proj1).[0;1])",
+    CONTACT_BOUND,
+)
+md.add_nonlinear_term(
+    mim1c,
+    "-(gamma0*element_size)*(lambda1 + 
neg_part(lambda1+(1/(gamma0*element_size))*((u1-Interpolate(u2,Proj1)+X-Interpolate(X,Proj1)).[0;1])))*Test_lambda1",
+    CONTACT_BOUND,
+)
 
 # Prescribed force in the hole
-if (Dirichlet_version):
-  md.add_initialized_data('DData', [0., -1.0])
-  md.add_Dirichlet_condition_with_multipliers(mim1, 'u1', elements_degree-1, 
HOLE_BOUND, 'DData');
+if Dirichlet_version:
+    md.add_initialized_data("DData", [0.0, -1.0])
+    md.add_Dirichlet_condition_with_multipliers(
+        mim1, "u1", elements_degree - 1, HOLE_BOUND, "DData"
+    )
 else:
-  md.add_filtered_fem_variable('lambda_D', mflambda, HOLE_BOUND)
-  md.add_initialized_data('F', [applied_force/(8*2*np.pi)])
-  md.add_variable('alpha_D', 1)
-  md.add_linear_term(mim1, '-lambda_D.Test_u1 + (alpha_D*[0;1] - 
u1).Test_lambda_D + (lambda_D.[0;1] + F)*Test_alpha_D + 
1E-6*alpha_D*Test_alpha_D', HOLE_BOUND)
-  # The small penalization 1E-6*alpha_D*Test_alpha_D seems necessary to have
-  # a convergence in all cases. Why ?
+    md.add_filtered_fem_variable("lambda_D", mflambda, HOLE_BOUND)
+    md.add_initialized_data("F", [applied_force / (8 * 2 * np.pi)])
+    md.add_variable("alpha_D", 1)
+    md.add_linear_term(
+        mim1,
+        "-lambda_D.Test_u1 + (alpha_D*[0;1] - u1).Test_lambda_D + 
(lambda_D.[0;1] + F)*Test_alpha_D + 1E-6*alpha_D*Test_alpha_D",
+        HOLE_BOUND,
+    )
+    # The small penalization 1E-6*alpha_D*Test_alpha_D seems necessary to have
+    # a convergence in all cases. Why ?
 
 
 #
 # Model solve
 #
 
-print('Solve problem with ', md.nbdof(), ' dofs')
-md.solve('max_res', 1E-9, 'max_iter', 40, 'noisy') # , 'lsearch', 'simplest',  
'alpha min', 0.8)
-if not(Dirichlet_version):
-  print('alpha_D = ', md.variable('alpha_D')[0])
+print("Solve problem with ", md.nbdof(), " dofs")
+md.solve(
+    "max_res", 1e-9, "max_iter", 40, "noisy"
+)  # , 'lsearch', 'simplest',  'alpha min', 0.8)
+if not (Dirichlet_version):
+    print("alpha_D = ", md.variable("alpha_D")[0])
 # print('Contact multiplier ', md.variable('lambda1'))
 
 #
 # Solution export
-#  
-U1 = md.variable('u1')
-U2 = md.variable('u2')
-VM1 = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u1', 'clambdastar', 
'cmu', mfvm1)
-VM2 = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u2', 'clambdastar', 
'cmu', mfvm2)
-
-mfvm1.export_to_vtk('displacement_with_von_mises1.vtk', mfvm1,  VM1, 'Von 
Mises Stresses', mfu1, U1, 'Displacements')
-
-mfvm2.export_to_vtk('displacement_with_von_mises2.vtk', mfvm2,  VM2, 'Von 
Mises Stresses', mfu2, U2, 'Displacements')
-print('You can view solutions with for instance:\nmayavi2 -d 
displacement_with_von_mises1.vtk -f WarpVector -m Surface -d 
displacement_with_von_mises2.vtk -f WarpVector -m Surface')
-
+#
+U1 = md.variable("u1")
+U2 = md.variable("u2")
+VM1 = md.compute_isotropic_linearized_Von_Mises_or_Tresca(
+    "u1", "clambdastar", "cmu", mfvm1
+)
+VM2 = md.compute_isotropic_linearized_Von_Mises_or_Tresca(
+    "u2", "clambdastar", "cmu", mfvm2
+)
+
+mfvm1.export_to_vtk(
+    "displacement_with_von_mises1.vtk",
+    mfvm1,
+    VM1,
+    "Von Mises Stresses",
+    mfu1,
+    U1,
+    "Displacements",
+)
+
+mfvm2.export_to_vtk(
+    "displacement_with_von_mises2.vtk",
+    mfvm2,
+    VM2,
+    "Von Mises Stresses",
+    mfu2,
+    U2,
+    "Displacements",
+)
+print(
+    "You can view solutions with for instance:\nmayavi2 -d 
displacement_with_von_mises1.vtk -f WarpVector -m Surface -d 
displacement_with_von_mises2.vtk -f WarpVector -m Surface"
+)
diff --git a/interface/tests/python/getfem_tvtk.py 
b/interface/tests/python/getfem_tvtk.py
index 3c17071..295bd1b 100644
--- a/interface/tests/python/getfem_tvtk.py
+++ b/interface/tests/python/getfem_tvtk.py
@@ -42,69 +42,157 @@ import getfem
 import numpy
 import scipy
 
+
 def gf_colormap(name):
-    if name == 'tripod':
-        s=64; s1=20; s2=25; s3=48; s4=55;
+    if name == "tripod":
+        s = 64
+        s1 = 20
+        s2 = 25
+        s3 = 48
+        s4 = 55
         c = []
-        for i in range(1,s):
-            c1 = max(min((i-s1)/(s2-s1),1),0);
-            c2 = max(min((i-s3)/(s4-s3),1),0);
-            c += [(1-c2)*((1-c1)*0.7 + c1) + c2,
-                  (1-c2)*((1-c1)*0.7) + c2*.8,
-                  (1-c2)*((1-c1)*0.7) + c2*.2]
-    elif name == 'chouette':
-        c = [.8,  1, .8,
-             .7, .9, .4,
-             .3, .8, .2,
-             .1, .7, .4,
-             .2, 0.7, 1.0000,
-             .3, 0.3, 1.0000,
-             1.0, .8, .1,
-             1.0, .6, .1,
-             1.0, .45, .1,
-             1.0, 0.3, .1]
-    elif name == 'froid':
-        c = [.8, 1, .8,
-             .7, .9, .4,
-             .3, .8, .2,
-             .1, .7, .4,
-             .2, 0.7, 1.0000,
-             .3, 0.3, 1.0000]
-    elif name == 'tank':
-        c = [0, 0, 1,
-             0, .5, 1,
-             0, 1, .5,
-             0, 1, 0,
-             .5, 1, 0,
-             1, .5, 0,
-             1, .4, 0,
-             1, 0, 0,
-             1, .2, 0,
-             1, .4, 0,
-             1, .6, 0,
-             1, .8, 0];
-    elif name == 'earth':
-        c = [252, 233, 79, #   Butter 1
-             247, 222, 30,
-             237, 212,  0, #   Butter 2
-             216, 180,  0,
-             196, 160,  0, #   Butter 3
-             138, 226, 52, #   Chameleon 1
-             115, 210, 22, #   Chameleon 2
-             78, 154,   6]
-        c = numpy.array(c) / 255.0;
-    c = numpy.array(c);
-    c.shape = (-1,3)
+        for i in range(1, s):
+            c1 = max(min((i - s1) / (s2 - s1), 1), 0)
+            c2 = max(min((i - s3) / (s4 - s3), 1), 0)
+            c += [
+                (1 - c2) * ((1 - c1) * 0.7 + c1) + c2,
+                (1 - c2) * ((1 - c1) * 0.7) + c2 * 0.8,
+                (1 - c2) * ((1 - c1) * 0.7) + c2 * 0.2,
+            ]
+    elif name == "chouette":
+        c = [
+            0.8,
+            1,
+            0.8,
+            0.7,
+            0.9,
+            0.4,
+            0.3,
+            0.8,
+            0.2,
+            0.1,
+            0.7,
+            0.4,
+            0.2,
+            0.7,
+            1.0000,
+            0.3,
+            0.3,
+            1.0000,
+            1.0,
+            0.8,
+            0.1,
+            1.0,
+            0.6,
+            0.1,
+            1.0,
+            0.45,
+            0.1,
+            1.0,
+            0.3,
+            0.1,
+        ]
+    elif name == "froid":
+        c = [
+            0.8,
+            1,
+            0.8,
+            0.7,
+            0.9,
+            0.4,
+            0.3,
+            0.8,
+            0.2,
+            0.1,
+            0.7,
+            0.4,
+            0.2,
+            0.7,
+            1.0000,
+            0.3,
+            0.3,
+            1.0000,
+        ]
+    elif name == "tank":
+        c = [
+            0,
+            0,
+            1,
+            0,
+            0.5,
+            1,
+            0,
+            1,
+            0.5,
+            0,
+            1,
+            0,
+            0.5,
+            1,
+            0,
+            1,
+            0.5,
+            0,
+            1,
+            0.4,
+            0,
+            1,
+            0,
+            0,
+            1,
+            0.2,
+            0,
+            1,
+            0.4,
+            0,
+            1,
+            0.6,
+            0,
+            1,
+            0.8,
+            0,
+        ]
+    elif name == "earth":
+        c = [
+            252,
+            233,
+            79,  #   Butter 1
+            247,
+            222,
+            30,
+            237,
+            212,
+            0,  #   Butter 2
+            216,
+            180,
+            0,
+            196,
+            160,
+            0,  #   Butter 3
+            138,
+            226,
+            52,  #   Chameleon 1
+            115,
+            210,
+            22,  #   Chameleon 2
+            78,
+            154,
+            6,
+        ]
+        c = numpy.array(c) / 255.0
+    c = numpy.array(c)
+    c.shape = (-1, 3)
     return c
 
+
 def _getfem_to_tvtk_points(points):
-    (N,nbpt) = points.shape
-    if N<3:
-        points=numpy.concatenate((points,
-                                  numpy.zeros([3-N, nbpt])), axis=0)
-    points=numpy.array(points.transpose(), 'd')
+    (N, nbpt) = points.shape
+    if N < 3:
+        points = numpy.concatenate((points, numpy.zeros([3 - N, nbpt])), 
axis=0)
+    points = numpy.array(points.transpose(), "d")
     return points
 
+
 class FigureItem:
     def __init__(self, fig):
         self.fig = fig
@@ -118,7 +206,7 @@ class FigureItem:
         self.lookup_table = None
         self.scalar_data = None
         self.scalar_data_name = None
-        self.scalar_data_range = (0,1)
+        self.scalar_data_range = (0, 1)
         self.scalar_bar = None
         self.vector_data = None
         self.edges_color = None
@@ -127,121 +215,126 @@ class FigureItem:
         self.glyph_nb_pts = 1000
         self.glyph_scale_factor = 1
         self.tube_color = None
-        self.set_colormap('tripod')
+        self.set_colormap("tripod")
+
     def set_nrefine(self, nr):
         self.nrefine = nr
-    def set_scalar_bar(self,v):
+
+    def set_scalar_bar(self, v):
         self.use_scalar_bar = v
+
     def scalar_range(self, *args):
-        if (len(args)==0):
+        if len(args) == 0:
             return self.scalar_data_range
-        if (len(args)==1):
+        if len(args) == 1:
             self.scalar_data_range = (args[0][0], args[0][1])
         else:
             self.scalar_data_range = (args[0], args[1])
         if self.mapper is not None:
-            self.mapper.scalar_range = self.scalar_data_range;
-
-    def build_from_mesh(self,m, **args):
-        dim = m.dim();
-        if (dim == 2):
-            self.sl=getfem.Slice(('none',),m,self.nrefine)
-        elif (dim == 3):
-            self.sl=getfem.Slice(('boundary',),m,self.nrefine);
+            self.mapper.scalar_range = self.scalar_data_range
+
+    def build_from_mesh(self, m, **args):
+        dim = m.dim()
+        if dim == 2:
+            self.sl = getfem.Slice(("none",), m, self.nrefine)
+        elif dim == 3:
+            self.sl = getfem.Slice(("boundary",), m, self.nrefine)
         else:
-            raise Exception('%d-D Meshes are not supported'%(dim,))
+            raise Exception("%d-D Meshes are not supported" % (dim,))
         self.build_from_slice(self.sl, **args)
 
     def build_from_slice(self, sl, **args):
         self.sl = sl
-        self.show_faces = args.get('faces', True)
-        self.show_edges = args.get('edges', True)
-        self.edges_color = args.get('edges_color', (0.1, 0.1, 0.1))
-        self.edges_width = args.get('edges_width', 0.7)
-        self.glyph_name = args.get('glyph', None)
-        self.glyph_scale_factor = args.get('glyph_scale', 1.0)
-        self.glyph_nb_pts = args.get('glyph_nb_pts', 1000)
-        self.tube_color = args.get('tube_color',(1,1,1))
+        self.show_faces = args.get("faces", True)
+        self.show_edges = args.get("edges", True)
+        self.edges_color = args.get("edges_color", (0.1, 0.1, 0.1))
+        self.edges_width = args.get("edges_width", 0.7)
+        self.glyph_name = args.get("glyph", None)
+        self.glyph_scale_factor = args.get("glyph_scale", 1.0)
+        self.glyph_nb_pts = args.get("glyph_nb_pts", 1000)
+        self.tube_color = args.get("tube_color", (1, 1, 1))
         self.actor = None
 
     def dfield_on_slice(self, data):
         mf = None
-        if (isinstance(data, tuple)):
-            if (len(data) == 2):
+        if isinstance(data, tuple):
+            if len(data) == 2:
                 mf = data[0]
                 U = data[1]
-            elif (len(data) == 1):
+            elif len(data) == 1:
                 U = data[0]
             else:
                 raise Exception("wrong data tuple..")
         else:
             U = data
         if mf is not None:
-            return getfem.compute(mf, U, 'interpolate on', self.sl);
+            return getfem.compute(mf, U, "interpolate on", self.sl)
         else:
             return U
 
-    def set_scalar_data(self, data, name='scalars'):
+    def set_scalar_data(self, data, name="scalars"):
         self.scalar_data = self.dfield_on_slice(data)
 
         self.scalar_data_name = name
-        #self.scalar_data_range = (min(self.scalar_data),
+        # self.scalar_data_range = (min(self.scalar_data),
         #                          max(self.scalar_data))
         m = self.scalar_data.mean()
         s = self.scalar_data.std()
-        self.scalar_data_range = (max(m - s, self.scalar_data.min()),
-                                  min(m + s, self.scalar_data.max()))
+        self.scalar_data_range = (
+            max(m - s, self.scalar_data.min()),
+            min(m + s, self.scalar_data.max()),
+        )
 
-    def set_vector_data(self, vdata, name='vectors'):
+    def set_vector_data(self, vdata, name="vectors"):
         d = self.dfield_on_slice(vdata)
         n = self.sl.nbpts()
         if d.size % n != 0:
             raise Exception("non consistent dimension for data")
         if d.size > n:
             d = d.transpose()
-            d.shape = (n,-1)
+            d.shape = (n, -1)
         self.vector_data = d
         if self.glyph_name is None:
-            self.glyph_name = 'default'
+            self.glyph_name = "default"
 
     def deformation_from_mf(self, mf, U, scale):
-        P=self.sl.pts()
-        deform = getfem.compute(mf, U, 'interpolate on', self.sl)
+        P = self.sl.pts()
+        deform = getfem.compute(mf, U, "interpolate on", self.sl)
         try:
-            scale=float(scale)
+            scale = float(scale)
         except ValueError:
-            if scale.endswith('%'):
-                a = max(abs(P.max()),abs(P.min()),1e-10);
-                b = max(abs(deform.max()),abs(deform.min()));
-                scale = float(scale[:-1]) * 0.01 * a/b;
-        P=P + scale * deform
+            if scale.endswith("%"):
+                a = max(abs(P.max()), abs(P.min()), 1e-10)
+                b = max(abs(deform.max()), abs(deform.min()))
+                scale = float(scale[:-1]) * 0.01 * a / b
+        P = P + scale * deform
         self.sl.set_pts(P)
-        #print("deformation!", repr(mf), U.size(), repr(self.sl), 
"\nDEFORM=",self.deform,"\n")
+        # print("deformation!", repr(mf), U.size(), repr(self.sl), 
"\nDEFORM=",self.deform,"\n")
         sys.stdout.flush()
 
-
     def set_colormap(self, c):
-        if isinstance(c,str):
+        if isinstance(c, str):
             lut = tvtk.LookupTable()
-            c=gf_colormap(c)
-            lut.number_of_table_values=c.shape[0]
+            c = gf_colormap(c)
+            lut.number_of_table_values = c.shape[0]
             for i in range(c.shape[0]):
-                lut.set_table_value(i,c[i,0],c[i,1],c[i,2],1)
+                lut.set_table_value(i, c[i, 0], c[i, 1], c[i, 2], 1)
         elif isinstance(c, tvtk.LookupTable):
             lut = c
         else:
             raise Exception("expected a string or a tvtk.LookupTable")
         self.lookup_table = lut
-        if (self.mapper is not None):
+        if self.mapper is not None:
             self.mapper.lookup_table = self.lookup_table
-        if (self.scalar_bar is not None):
+        if self.scalar_bar is not None:
             self.scalar_bar.lookup_table = self.lookup_table
+
     def vtk_actors(self):
-        if (self.actors is None):
+        if self.actors is None:
             self.actors = []
-            points=_getfem_to_tvtk_points(self.sl.pts())
-            (triangles,cv2tr)=self.sl.splxs(2);
-            triangles=numpy.array(triangles.transpose(), 'I');
+            points = _getfem_to_tvtk_points(self.sl.pts())
+            (triangles, cv2tr) = self.sl.splxs(2)
+            triangles = numpy.array(triangles.transpose(), "I")
             data = tvtk.PolyData(points=points, polys=triangles)
             if self.scalar_data is not None:
                 data.point_data.scalars = numpy.array(self.scalar_data)
@@ -253,115 +346,119 @@ class FigureItem:
                 mask.random_mode = True
                 mask.input = data
 
-                if self.glyph_name == 'default':
+                if self.glyph_name == "default":
                     if self.vector_data is not None:
-                        self.glyph_name = 'arrow'
+                        self.glyph_name = "arrow"
                     else:
-                        self.glyph_name = 'ball'
+                        self.glyph_name = "ball"
 
                 glyph = tvtk.Glyph3D()
-                glyph.scale_mode = 'scale_by_vector'
-                glyph.color_mode = 'color_by_scalar'
-                #glyph.scale_mode = 'data_scaling_off'
-                glyph.vector_mode = 'use_vector' # or 'use_normal'
+                glyph.scale_mode = "scale_by_vector"
+                glyph.color_mode = "color_by_scalar"
+                # glyph.scale_mode = 'data_scaling_off'
+                glyph.vector_mode = "use_vector"  # or 'use_normal'
                 glyph.input = mask.output
-                if self.glyph_name == 'arrow':
+                if self.glyph_name == "arrow":
                     glyph.source = tvtk.ArrowSource().output
-                elif self.glyph_name == 'ball':
+                elif self.glyph_name == "ball":
                     glyph.source = tvtk.SphereSource().output
-                elif self.glyph_name == 'cone':
+                elif self.glyph_name == "cone":
                     glyph.source = tvtk.ConeSource().output
-                elif self.glyph_name == 'cylinder':
+                elif self.glyph_name == "cylinder":
                     glyph.source = tvtk.CylinderSource().output
-                elif self.glyph_name == 'cube':
+                elif self.glyph_name == "cube":
                     glyph.source = tvtk.CubeSource().output
                 else:
                     raise Exception("Unknown glyph name..")
-                #glyph.scaling = 1
-                #glyph.scale_factor = self.glyph_scale_factor
+                # glyph.scaling = 1
+                # glyph.scale_factor = self.glyph_scale_factor
                 data = glyph.output
 
             if self.show_faces:
-##                if self.deform is not None:
-##                    data.point_data.vectors = 
array(numarray.transpose(self.deform))
-##                    warper = tvtk.WarpVector(input=data)
-##                    data = warper.output
-##                lut = tvtk.LookupTable()
-##                lut.hue_range = 0.667,0
-##                c=gf_colormap('tripod')
-##                lut.number_of_table_values=c.shape[0]
-##                for i in range(0,c.shape[0]):
-##                    lut.set_table_value(i,c[i,0],c[i,1],c[i,2],1)
-
-
-
-                self.mapper = tvtk.PolyDataMapper(input=data);
-                self.mapper.scalar_range = self.scalar_data_range;
+                ##                if self.deform is not None:
+                ##                    data.point_data.vectors = 
array(numarray.transpose(self.deform))
+                ##                    warper = tvtk.WarpVector(input=data)
+                ##                    data = warper.output
+                ##                lut = tvtk.LookupTable()
+                ##                lut.hue_range = 0.667,0
+                ##                c=gf_colormap('tripod')
+                ##                lut.number_of_table_values=c.shape[0]
+                ##                for i in range(0,c.shape[0]):
+                ##                    
lut.set_table_value(i,c[i,0],c[i,1],c[i,2],1)
+
+                self.mapper = tvtk.PolyDataMapper(input=data)
+                self.mapper.scalar_range = self.scalar_data_range
                 self.mapper.scalar_visibility = True
                 # Create mesh actor for display
                 self.actors += [tvtk.Actor(mapper=self.mapper)]
             if self.show_edges:
-                (Pe, E1, E2)=self.sl.edges();
+                (Pe, E1, E2) = self.sl.edges()
                 if Pe.size:
-                    E = numpy.array(numpy.concatenate((E1.transpose(),
-                                                       E2.transpose()),
-                                                      axis=0), 'I')
-                    edges=tvtk.PolyData(points=_getfem_to_tvtk_points(Pe),
-                                        polys=E)
-                    mapper_edges = tvtk.PolyDataMapper(input=edges);
+                    E = numpy.array(
+                        numpy.concatenate((E1.transpose(), E2.transpose()), 
axis=0), "I"
+                    )
+                    edges = tvtk.PolyData(points=_getfem_to_tvtk_points(Pe), 
polys=E)
+                    mapper_edges = tvtk.PolyDataMapper(input=edges)
                     actor_edges = tvtk.Actor(mapper=mapper_edges)
-                    actor_edges.property.representation = 'wireframe'
-                    #actor_edges.property.configure_traits()
+                    actor_edges.property.representation = "wireframe"
+                    # actor_edges.property.configure_traits()
                     actor_edges.property.color = self.edges_color
                     actor_edges.property.line_width = self.edges_width
                     actor_edges.property.ambient = 0.5
-                    self.actors += [actor_edges];
+                    self.actors += [actor_edges]
             if self.sl.nbsplxs(1):
                 # plot tubes
-                (seg,cv2seg)=self.sl.splxs(1)
-                seg=numpy.array(seg.transpose(),'I')
-                data=tvtk.Axes(origin=(0,0,0), scale_factor=0.5, symmetric=1)
-                data=tvtk.PolyData(points=points, lines=seg)
-                tube = tvtk.TubeFilter(radius=0.4, number_of_sides=10,
-                                       vary_radius='vary_radius_off',
-                                       input=data)
+                (seg, cv2seg) = self.sl.splxs(1)
+                seg = numpy.array(seg.transpose(), "I")
+                data = tvtk.Axes(origin=(0, 0, 0), scale_factor=0.5, 
symmetric=1)
+                data = tvtk.PolyData(points=points, lines=seg)
+                tube = tvtk.TubeFilter(
+                    radius=0.4,
+                    number_of_sides=10,
+                    vary_radius="vary_radius_off",
+                    input=data,
+                )
                 mapper = tvtk.PolyDataMapper(input=tube.output)
                 actor_tubes = tvtk.Actor(mapper=mapper)
-                #actor_tubes.property.representation = 'wireframe'
+                # actor_tubes.property.representation = 'wireframe'
                 actor_tubes.property.color = self.tube_color
-                #actor_tubes.property.line_width = 8
-                #actor_tubes.property.ambient = 0.5
+                # actor_tubes.property.line_width = 8
+                # actor_tubes.property.ambient = 0.5
 
                 self.actors += [actor_tubes]
 
             if self.use_scalar_bar:
-                self.scalar_bar = 
tvtk.ScalarBarActor(title=self.scalar_data_name,
-                                                 orientation='horizontal',
-                                                 width=0.8, height=0.07)
-                self.scalar_bar.position_coordinate.coordinate_system = 
'normalized_viewport'
+                self.scalar_bar = tvtk.ScalarBarActor(
+                    title=self.scalar_data_name,
+                    orientation="horizontal",
+                    width=0.8,
+                    height=0.07,
+                )
+                self.scalar_bar.position_coordinate.coordinate_system = (
+                    "normalized_viewport"
+                )
                 self.scalar_bar.position_coordinate.value = 0.1, 0.01, 0.0
                 self.actors += [self.scalar_bar]
 
-            if (self.lookup_table is not None):
+            if self.lookup_table is not None:
                 self.set_colormap(self.lookup_table)
 
         return self.actors
 
 
-
-
 class Figure:
-    def __init__(self, gui='tvtk'):
+    def __init__(self, gui="tvtk"):
         self.actors = []
         self.gui = None
         self.renderer = None
         self.items = []
-        if gui == 'tvtk':
+        if gui == "tvtk":
             self._create_tvtk_window()
         else:
             self._create_ivtk_window()
-        self.renderer.background = (1,1,1)
-    def _create_tvtk_window(self, size=(500,500)):
+        self.renderer.background = (1, 1, 1)
+
+    def _create_tvtk_window(self, size=(500, 500)):
         # create a renderer
         self.renderer = tvtk.Renderer()
         # create a render window and hand it the renderer
@@ -372,7 +469,7 @@ class Figure:
         self.interactor = 
tvtk.RenderWindowInteractor(render_window=self.render_window)
         self.gui = None
 
-    def _create_ivtk_window(self, size=(800,800)):
+    def _create_ivtk_window(self, size=(800, 800)):
         from enthought.tvtk.tools import ivtk
         from enthought.pyface.api import GUI
 
@@ -384,7 +481,6 @@ class Figure:
         self.renderer = window.scene
         self.render_window = window
 
-
     def show_mesh(self, m, **args):
         it = FigureItem(self)
         it.build_from_mesh(m, **args)
@@ -394,44 +490,44 @@ class Figure:
     def show_mesh_fem(self, mf, **args):
         it = FigureItem(self)
         it.build_from_mesh(mf.linked_mesh(), **args)
-        if 'deformation' in args:
-            it.deformation_from_mf(args.get('deformation_mf',mf),
-                                   args['deformation'],
-                                   args.get('deformation_scale','10%'));
-        if 'data' in args:
-            it.set_scalar_data(args.get('data'),
-                               args.get('scalar_label', 'data'));
-        it.set_scalar_bar(args.get('scalar_bar', False))
-
-        if 'vdata' in args:
-            it.set_vector_data(args.get('vdata'))
+        if "deformation" in args:
+            it.deformation_from_mf(
+                args.get("deformation_mf", mf),
+                args["deformation"],
+                args.get("deformation_scale", "10%"),
+            )
+        if "data" in args:
+            it.set_scalar_data(args.get("data"), args.get("scalar_label", 
"data"))
+        it.set_scalar_bar(args.get("scalar_bar", False))
+
+        if "vdata" in args:
+            it.set_vector_data(args.get("vdata"))
 
         self.actors += it.vtk_actors()
         self.items.append(it)
 
-        it.set_colormap(args.get('colormap','earth'));
+        it.set_colormap(args.get("colormap", "earth"))
 
     def show_slice(self, sl, **args):
         it = FigureItem(self)
         it.build_from_slice(sl, **args)
 
-        if 'data' in args:
-            it.set_scalar_data(args.get('data'),
-                               args.get('scalar_label', 'data'));
+        if "data" in args:
+            it.set_scalar_data(args.get("data"), args.get("scalar_label", 
"data"))
 
-        it.set_scalar_bar(args.get('scalar_bar', False))
+        it.set_scalar_bar(args.get("scalar_bar", False))
 
-        if 'vdata' in args:
-            it.set_vector_data(args.get('vdata'))
+        if "vdata" in args:
+            it.set_vector_data(args.get("vdata"))
 
         self.actors += it.vtk_actors()
         self.items.append(it)
 
-        it.set_colormap(args.get('colormap','chouette'));
+        it.set_colormap(args.get("colormap", "chouette"))
 
     def scalar_range(self, *args):
         if len(self.items):
-            if len(args)==0:
+            if len(args) == 0:
                 return self.items[-1].scalar_range()
             else:
                 for i in self.items:
@@ -439,13 +535,14 @@ class Figure:
         else:
             raise Exception("plot something before changing its scalar range!")
 
-##    def scalar_bar(self):
-##        if len(self.items):
-##            self.items[-1].set_scalar_bar(True)
+    ##    def scalar_bar(self):
+    ##        if len(self.items):
+    ##            self.items[-1].set_scalar_bar(True)
 
     def set_colormap(self, c):
-        if (len(self.items)):
+        if len(self.items):
             self.items[-1].set_colormap(c)
+
     def show(self, mf, **args):
         if isinstance(mf, getfem.MeshFem):
             self.show_mesh_fem(mf, **args)
@@ -455,6 +552,7 @@ class Figure:
             self.show_slice(mf, **args)
         else:
             raise TypeError("argument must be a drawable getfem object")
+
     def loop(self):
         for a in self.actors:
             self.renderer.add_actor(a)
diff --git a/interface/tests/python/tutorial1.py 
b/interface/tests/python/tutorial1.py
index a8b1da5..2cf1c63 100644
--- a/interface/tests/python/tutorial1.py
+++ b/interface/tests/python/tutorial1.py
@@ -24,28 +24,32 @@ import getfem as gf
 import numpy as np
 
 NX = 10
-m = gf.Mesh('cartesian', np.arange(0,1+1./NX,1./NX), 
np.arange(0,1+1./NX,1./NX))
-mf = gf.MeshFem(m,1) # create a meshfem of for a field of dimension 1
-mf.set('fem',gf.Fem('FEM_QK(2,2)'))
+m = gf.Mesh(
+    "cartesian",
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+    np.arange(0, 1 + 1.0 / NX, 1.0 / NX),
+)
+mf = gf.MeshFem(m, 1)  # create a meshfem of for a field of dimension 1
+mf.set("fem", gf.Fem("FEM_QK(2,2)"))
 
-print (gf.Fem('FEM_QK(2,2)').poly_str())
+print(gf.Fem("FEM_QK(2,2)").poly_str())
 
 # mim=gf.MeshIm(m, gf.Integ('IM_EXACT_PARALLELEPIPED(2)')); // not allowed
-mim=gf.MeshIm(m, gf.Integ('IM_GAUSS_PARALLELEPIPED(2, 4)'));
+mim = gf.MeshIm(m, gf.Integ("IM_GAUSS_PARALLELEPIPED(2, 4)"))
 
 
 border = m.outer_faces()
 m.set_region(42, border)  # create the region B42 (:-
 
 
-md=gf.Model('real')
-md.add_fem_variable('u', mf)
-md.add_Laplacian_brick(mim, 'u')
-R = mf.eval('(x-.5)*(x-.5) + (y-.5)*(y-.5) + x/5 - y/3')
-md.add_initialized_fem_data('DirichletData', mf, R)
-md.add_Dirichlet_condition_with_multipliers(mim, 'u', mf, 42, 'DirichletData')
+md = gf.Model("real")
+md.add_fem_variable("u", mf)
+md.add_Laplacian_brick(mim, "u")
+R = mf.eval("(x-.5)*(x-.5) + (y-.5)*(y-.5) + x/5 - y/3")
+md.add_initialized_fem_data("DirichletData", mf, R)
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mf, 42, "DirichletData")
 
 md.variable_list()
 
 md.solve()
-U = md.variable('u')
+U = md.variable("u")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]