KMV element uesd in FEnicsX

Hi, everyone,

I want to use the “KMV( Kong–Mulder–Veldhuizen)” element in fenicsx. However, it seems not to work. I wonder if the FenicsX could support this element.

Thx

import ufl
import numpy

from mpi4py import MPI
from petsc4py import PETSc

from dolfinx import mesh, fem, io, nls, log

def q(u):
    return 1 + u**2

domain = mesh.create_unit_square(MPI.COMM_WORLD, 10, 10)
x = ufl.SpatialCoordinate(domain)
u_ufl = 1 + x[0] + 2*x[1]
f = - ufl.div(q(u_ufl)*ufl.grad(u_ufl))

element = ufl.FiniteElement("KMV", domain.ufl_cell(), 2)

V = fem.FunctionSpace(domain, element)

ValueError: Unknown element family: Kong-Mulder-Veldhuizen with cell type triangle

You could implement them using the definitions at: DefElement: Kong–Mulder–Veldhuizen
as a custom element, as explained in:
Creating a custom element — Basix 0.4.3.0 documentation
and
Defining conforming Crouzeix–Raviart elements — Basix 0.4.3.0 documentation

Thank you very much, dokken.
I have already tested the Variants of Lagrange elements, as the Variants of Lagrange elements. but there is some issue with it.

import basix
import numpy as np
from basix import ElementFamily, CellType, LagrangeVariant, LatticeType

lagrange = basix.create_element(
    ElementFamily.P, CellType.triangle, 15, LagrangeVariant.equispaced)
points = basix.create_lattice(
    CellType.triangle, 50, LatticeType.equispaced, True)
tab = lagrange.tabulate(0, points)[0]
print(max(np.sum(np.abs(tab), axis=0)))

gll2 = basix.create_element(
    ElementFamily.P, CellType.triangle, 15, LagrangeVariant.gll_isaac)
print(max(np.sum(np.abs(gll2.tabulate(0, points)[0]), axis=0)))

from mpi4py import MPI
from dolfinx import mesh
domain = mesh.create_unit_square(MPI.COMM_WORLD, 15, 15)

from dolfinx.fem import FunctionSpace
V = FunctionSpace(domain, gll2)

TypeError                                 Traceback (most recent call last)
Input In [12], in <cell line: 2>()
      1 from dolfinx.fem import FunctionSpace
----> 2 V = FunctionSpace(domain, gll2)

File /usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/fem/function.py:440, in FunctionSpace.__init__(self, mesh, element, cppV, form_compiler_params, jit_params)
    438     super().__init__(mesh.ufl_domain(), element)
    439 else:
--> 440     e = ElementMetaData(*element)
    441     ufl_element = ufl.FiniteElement(e.family, mesh.ufl_cell(), e.degree)
    442     super().__init__(mesh.ufl_domain(), ufl_element)

TypeError: dolfinx.fem.function.ElementMetaData() argument after * must be an iterable, not basix._basixcpp.FiniteElement

could you please help me to check it? Thx

Hi, dokken,

I added one code e = basix.ufl_wrapper.BasixElement(gll2). It works. Thx

1 Like

Is it possible for FEniCSx to support (natively, not via custom implementation) the KMV finite element, like Firedrake does?

You can use the new SymFem converter by @mscroggs:

from mpi4py import MPI
import ufl
import symfem
import numpy as np

import symfem.basix_interface


import dolfinx

element = symfem.create_element("triangle", "KMV", 2)
basix_ufl_element = symfem.basix_interface.create_basix_element(element, ufl=True)


def f(x):
    return (1 - x[0] - x[1]) * x[0] * x[1] + x[0] ** 2 - 2 * x[1] ** 2


for n in [4, 8, 16, 32, 64]:
    mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, n, n)

    V = dolfinx.fem.functionspace(mesh, basix_ufl_element)

    u = dolfinx.fem.Function(V)

    u.interpolate(f)

    x = ufl.SpatialCoordinate(mesh)
    error_L2 = mesh.comm.allreduce(
        dolfinx.fem.assemble_scalar(dolfinx.fem.form((u - f(x)) ** 2 * ufl.dx)),
        op=MPI.SUM,
    )

    print(f"{n=} L2 error: {np.sqrt(error_L2)}")

ref: Creating a Basix custom element using Symfem — Symfem 2025.11.1 documentation

Although there appears to be a bug in the second order KMV space. I think first order works fine for now though.

1 Like

A note on

There is no bug. It was me testing with the wrong kind of mesh.

1 Like

Got it. I will work on this in a while and provide feedback here. Thank you for your reply.

Dear dokken,

Following up on our previous discussion, I have the following questions:

1. I would like to compare the results between FEniCSx and Firedrake.

The system environment is WSL2 Ubuntu, and I have created two separate virtual environments using micromamba. The FEniCSx version is 0.9.0, while Firedrake was installed according to the instructions in the Firedrake 2025.10.3.dev0 documentation. Installing Firedrake — Firedrake 2025.10.3.dev0 documentation.

I executed your code using the command mpirun -n 1 python3 KMV_test.py in the FEniCSx 0.9.0 environment (installed via conda-forge) on WSL2 Ubuntu. The execution command and corresponding results are as follows:

from mpi4py import MPI
import ufl
import symfem
import numpy as np
import symfem.basix_interface
import dolfinx
element = symfem.create_element("triangle", "KMV", 2)
basix_ufl_element = symfem.basix_interface.create_basix_element(element, ufl=True)
def f(x):
    return (1 - x[0] - x[1]) * x[0] * x[1] + x[0] ** 2 - 2 * x[1] ** 2
for n in [4, 8, 16, 32, 64]:
    mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, n, n)
    V = dolfinx.fem.functionspace(mesh, basix_ufl_element)
    u = dolfinx.fem.Function(V)
    u.interpolate(f)
    x = ufl.SpatialCoordinate(mesh)
    error_L2 = mesh.comm.allreduce(
        dolfinx.fem.assemble_scalar(dolfinx.fem.form((u - f(x)) ** 2 * ufl.dx)),
        op=MPI.SUM,
    )
    print(f"{n=} L2 error: {np.sqrt(error_L2)}")
n=4 L2 error: 0.0005391137182342338
n=8 L2 error: 6.738921477825666e-05
n=16 L2 error: 8.423651846508915e-06
n=32 L2 error: 1.0529564801666114e-06
n=64 L2 error: 1.3161955942545088e-07

I have executed my Firedrake code as follows:

import numpy as np
from firedrake import (
    Function, FunctionSpace,
    errornorm, UnitSquareMesh, SpatialCoordinate
)
def f(mesh):
    x = SpatialCoordinate(mesh)
    return (1 - x[0] - x[1]) * x[0] * x[1] + x[0] ** 2 - 2 * x[1] ** 2
for n in [4, 8, 16, 32, 64]:

    mesh = UnitSquareMesh(n, n)
    V = FunctionSpace(mesh, "KMV", 2)
    VE = FunctionSpace(mesh, "CG", 3)

    u = Function(V); u.interpolate(f(mesh))
    u_ = Function(VE); u_.interpolate(f(mesh))

    x = SpatialCoordinate(mesh)
    error_m = errornorm(u, u_, norm_type='L2')

    print(f"{n=} L2 error: {error_m}")

The result is

/.local/lib/python3.10/site-packages/numpy/_core/getlimits.py:551: UserWarning: Signature b'\x00\xd0\xcc\xcc\xcc\xcc\xcc\xcc\xfb\xbf\x00\x00\x00\x00\x00\x00' for <class 'numpy.longdouble'> does not match any known type: falling back to type probe function.
This warnings indicates broken support for the dtype!
  machar = _get_machar(dtype)
firedrake:WARNING OMP_NUM_THREADS is not set or is set to a value greater than 1, we suggest setting OMP_NUM_THREADS=1 to improve performance
firedrake:WARNING Degree of exact solution less than approximation degree
n=4 L2 error: 2.388585201114899e-16
firedrake:WARNING Degree of exact solution less than approximation degree
n=8 L2 error: 2.1926452124941248e-16
firedrake:WARNING Degree of exact solution less than approximation degree
n=16 L2 error: 2.269577765062539e-16
firedrake:WARNING Degree of exact solution less than approximation degree
n=32 L2 error: 2.0988940267773374e-16
firedrake:WARNING Degree of exact solution less than approximation degree
n=64 L2 error: 2.156275105378545e-16

The results clearly do not match.

2. The support degree order for KMV element

3. Are there any specialized quadrature rules for the KMV element in FEniCSx?
The adoption of the KMV element is driven by its application as a mass-lumped triangular element. Crucially, obtaining a lumped mass matrix requires both this special element and appropriate quadrature rules. This is implemented within Firedrake through the FInAT library, see Scalar wave equation with higher-order mass lumping — Firedrake 2025.10.3.dev0 documentation

import finat
quad_rule = finat.quadrature.make_quadrature(V.finat_element.cell, V.ufl_element().degree(), "KMV")
dxlump=dx(scheme=quad_rule)

However, when I tried to install the FInAT or FIAT package in my FEniCSx virtual environment, I encountered an error.

micromamba install finat -c conda-forge
nodefaults/linux-64                                 ??.?MB @  ??.?MB/s  0.6s
nodefaults/noarch                                   ??.?MB @  ??.?MB/s  0.6s
conda-forge/noarch                                  23.4MB @   3.4MB/s  6.8s
conda-forge/linux-64                                48.9MB @   6.6MB/s  7.3s

Pinned packages:

  - python=3.13

error    libmamba Could not solve for environment specs
    The following package could not be installed
    └─ finat =* * does not exist (perhaps a typo or a missing channel).
critical libmamba Could not solve for environment specs

I have also attempted to install it via pip , but without success. What is the recommended approach to implement the specific quadrature rules for mass lumping with the KMV element in FEniCSx?
4. Another question
Also, where can I see the basis functions of predefined elements in FEniCSx? Given that the KMV element is new, I’m skeptical if the basis functions in symfem and Firedrake are the same.

I’m new to this, so please forgive any naive questions. Thanks again to you and the FEniCSx team for your amazing work.

The important thing to note here is that the meshes are different, which is what made me think there were a bug in the symfem implementation, ref:

You need to use the same diagonal-type in both implementations, as the use different ones (i.e. / and ).

FIAT was part of the FEniCS project. However, as it is a Python-library, it wasn’t suited for efficient runtime tabulation for DOLFINx, especially as DOLFINx has both a C++ and Python interface.

You are also right that the symfem implementation is «limited» to 3rd and 2nd order in 2D and 3D. However, as you can see from the code, it should be quite straightforward to extend it to higher degrees.

It is a lot easier to extend symfem than basix, so if you require higher order you could give that a go.

In DOLFINx you can specify your own custom quadrature. Thus you should be able to take the one from final and use it in the respective ufl measure.

As FINAT is not maintained by FEniCS, I would be surprised to see it on conda (as far as I am aware firedrake is not on conda).

What error message did you get when installing through pip? As far as I am aware fiat and finat is now one repository (see comment for archiving at : GitHub - FInAT/FInAT: (ARCHIVED) A smarter library of finite elements), I would probably try: python3 -m pip install git+https://github.com/firedrakeproject/fiat.git

We have a separate paper on verifying finite element implementations; [2506.20188] DefElement: an encyclopedia of finite element definitions
which is used in defelement:
DefElement/defelement/implementations at a619ed9f76d5c314c4916b7a89ce140a958c77ad · DefElement/DefElement · GitHub

to verify various implementations, including fiat (firedrake), symfem and basix.

Yes, after flipping the mesh generated by FEniCSx, I achieved machine precision, although the error is not identical to the one from Firedrake.

Thank you for the guidance. I will attempt a custom implementation, although it will require more effort on my part.

I initially ran pip install finat (or fiat ), which was apparently incorrect.

(fenicsx-env) :~$ pip install finat
ERROR: Could not find a version that satisfies the requirement finat (from versions: none)
ERROR: No matching distribution found for finat
(fenicsx-env):~$ pip install FInAT
ERROR: Could not find a version that satisfies the requirement FInAT (from versions: none)
ERROR: No matching distribution found for FInAT
(fenicsx-env):~$ pip install FIAT
ERROR: Could not find a version that satisfies the requirement FIAT (from versions: none)
ERROR: No matching distribution found for FIAT
(fenicsx-env):~$ pip install fiat
ERROR: Could not find a version that satisfies the requirement fiat (from versions: none)
ERROR: No matching distribution found for fiat

When I ran python3 -m pip install git+https://github.com/firedrakeproject/fiat.git, I encountered a serious error:

Successfully built firedrake-fiat fenics-ufl
Installing collected packages: symengine, recursivenodes, fenics-ufl, firedrake-fiat
  Attempting uninstall: fenics-ufl
    Found existing installation: fenics-ufl 2024.2.0
    Uninstalling fenics-ufl-2024.2.0:
      Successfully uninstalled fenics-ufl-2024.2.0
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
fenics-dolfinx 0.9.0 requires fenics-ufl<2024.3.0,>=2024.2.0, but you have fenics-ufl 2025.3.0.dev0 which is incompatible.
fenics-ffcx 0.9.0 requires fenics-ufl<2024.3.0,>=2024.2.0, but you have fenics-ufl 2025.3.0.dev0 which is incompatible.
Successfully installed fenics-ufl-2025.3.0.dev0 firedrake-fiat-2025.11.0.dev0 recursivenodes-0.2.0 symengine-0.14.1

This severe dependency conflict forced me to remove my FEniCSx environment and reinstall FEniCSx 0.10 (upgrading from 0.9.0) :joy:. These significant conflicts highlight the necessity of defining custom quadrature rules, as you mentioned.

I have downloaded this paper and will read it carefully. Thank you again for your reply.

1 Like