Ffddm problem by using RT0 element

Dear all,

I am using ffddm to a mixed finite element problem with finite spaces [RT0,P0].
When I used ffddmbuildDfespace to build the local space, it showed an error:

Probleme partition de l’unite : uu.linfty = 1.

I realized that I should use ffddmbuildDfespaceEdge instead of ffddmbuildDfespace, for non Lagrange finite element:
https://doc.freefem.org/documentation/ffddm/documentation.html#ffddmdocumentationlocalfiniteelementspaces

But I have no idea how to choose a Pkpart space for [RT0,P0].

The following is my example:

include “ffddm.idp”
load “Element_Mixte”

macro dimension 2// EOM
int[int] ll=[1,2,3,4]; //boundary labels : 1 for bottom 2 for right 3 for upper 4 for left
mesh Th = square(20, 20, [x, y],label=ll);
ffddmbuildDmesh(M,Th,mpiCommWorld)

macro def(i) [i,i#B,i#C]// EOM // temperature field definition
macro init(i) [i,i,i]// EOM // temperature field initialization
func Pk = [RT0,P0];
func PkPart = [P1,P1,P0];
ffddmbuildDfespaceEdge(MFE , M , real , def , init , Pk, def, init,PkPart)
ffddmsetupinit(M,MFE)

Thanks!
Y.H.

ffddm does not handle RT finite elements as of today. PETSc does, cf. FreeFem-sources/laplace-RT-2d-PETSc.edp at develop · FreeFem/FreeFem-sources · GitHub or FreeFem-sources/laplace-RT-3d-PETSc.edp at develop · FreeFem/FreeFem-sources · GitHub.

Thank you very much for your response, I will try to write by PETSc…

Here it is with macro_ddm.idp.

load "PETSc"
include "macro_ddm.idp"
load "Element_Mixte"

int[int] ll=[1,2,3,4]; //boundary labels : 1 for bottom 2 for right 3 for upper 4 for left
mesh Th = square(20, 20, [x, y],label=ll);

macro def(i) [i,i#B,i#C]// EOM // temperature field definition
macro init(i) [i,i,i]// EOM // temperature field initialization
func Pk = [RT0,P0];
Mat A;
buildDmesh(Th);
fespace Wh(Th, Pk);
{
macro ThPostProcessD(D) {
    Wh def(u), def(v);
    varf onG(def(u), def(v)) = on(-111111, u = 10 + x + y, uB = 100 + y - x);
    v[] = D;
    u[] = onG(0, Wh);
    for [j, dj : u[]] dj = abs(dj) > 1e-2 ? 0.0 : 1.0;
    def(u) = [u, uB, vC];
    D = u[];
}// EOM
createMat(Th, A, Pk);
}

You do not have to worry about the ThPostProcessD macro, it’s just to make sure that your matrix is properly spread among processes. Then, you can write standard FreeFEM and assemble your varf in A.

FYI you can use the P0edge finite element (scalar constant-per-edge element) to build a partition of unity for RT0 :

include "ffddm.idp"
load "Element_Mixte"

macro dimension 2// EOM
int[int] ll=[1,2,3,4]; //boundary labels : 1 for bottom 2 for right 3 for upper 4 for left
mesh Th = square(20, 20, [x, y],label=ll);
ffddmbuildDmesh(M,Th,mpiCommWorld)

macro def(i) [i,i#B,i#C]// EOM // temperature field definition
macro init(i) [i,i,i]// EOM // temperature field initialization
macro defpart(i) [i, i#B] //
macro initpart(i) [i,i] //
func Pk = [RT0,P0];
func PkPart = [P0edge,P0];
ffddmbuildDfespaceEdge(MFE , M , real , def , init , Pk, defpart, initpart, PkPart)
ffddmsetupinit(M,MFE)

Oops, my bad, I will edit my answer to mention only higher orders (which are not handled if I’m not mistaken — again).

Thank you very much, your answer solve my problem.
Bonne journée.

I tried Pk= [RT1, P0] with PkPart = [P1Edge,P0], not worked;
but somehow Pk = [BDM1,P0] with PkPart = [P1nc,P1nc, P0] can work well, where BDM1 is a higher order option for me…
Thank you again!