For instance running the following with the latest dolfinx/dolfinx container returns:
import time
import dolfinx.mesh
import dolfinx.fem
from mpi4py import MPI
import ufl
N = 15
mesh = dolfinx.mesh.create_unit_cube(MPI.COMM_WORLD, N, N, N)
element = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
V = dolfinx.fem.FunctionSpace(mesh, element)
v = dolfinx.fem.Function(V)
v.x.array[:] = 1
element_2 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 2)
Q = dolfinx.fem.FunctionSpace(mesh, element_2)
def project(function: dolfinx.fem.Function, space: dolfinx.fem.FunctionSpace, jit_parameters: dict = {},
petsc_options: dict = {}):
p = ufl.TrialFunction(space)
q = ufl.TestFunction(space)
a = ufl.inner(p, q) * ufl.dx
L = ufl.inner(function, q) * ufl.dx
problem = dolfinx.fem.LinearProblem(
a, L, jit_parameters=jit_parameters, petsc_options=petsc_options)
return problem.solve()
# --- No JIT options-----
project(v, Q) # Run to JIT compile before timing
start = time.perf_counter()
q = project(v, Q)
end = time.perf_counter()
print(f"No compile options: {end-start}")
# ---- Optimized jit options -----
jit_parameters = {"cffi_extra_compile_args": [
"-O2", "-march=native"], "cffi_libraries": ["m"]}
# Run to JIT compile before timing
q = project(v, Q, jit_parameters=jit_parameters)
start = time.perf_counter()
q = project(v, Q, jit_parameters=jit_parameters)
end = time.perf_counter()
print(f"JIT options: {end-start}")
# Use linear solver (lu/mumps)
petsc_options = {"ksp_type": "preonly",
"pc_type": "lu", "pc_factor_mat_solver_type": "mumps"}
start = time.perf_counter()
q = project(v, Q, jit_parameters=jit_parameters, petsc_options=petsc_options)
end = time.perf_counter()
print(f"Linear solver (mumps): {end-start}")
# -----Interpolation------
q = dolfinx.fem.Function(Q)
start = time.perf_counter()
q.interpolate(v)
end = time.perf_counter()
print(f"Interpolate: {end-start}")
returns
No compile options: 0.17611332399997082
JIT options: 0.17151404399999137
Linear solver (mumps): 1.1754638479999358
Interpolate: 0.002084933999981331
while running the equivalent in the quay.io/fenicsproject/dev:latest dolfin container
from dolfin import *
import time
N = 15
mesh = UnitCubeMesh(N, N, N)
element = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
V = FunctionSpace(mesh, element)
v = Function(V)
element_2 = FiniteElement("Lagrange", mesh.ufl_cell(), 2)
Q = FunctionSpace(mesh, element_2)
q = project(v, Q) # Run to JIT compile before timing
start = time.perf_counter()
q = project(v, Q, solver_type="mumps")
end = time.perf_counter()
print(f"Dolfin (mumps): {end-start}")
start = time.perf_counter()
q = project(v, Q, solver_type="cg")
end = time.perf_counter()
print(f"Dolfin (cg): {end-start}")
you get:
Dolfin (mumps): 1.9629643200000828
Dolfin (cg): 0.16217956299999514