Quick question: number of vertices in gmsh model vs. degrees of freedom in functionspace

Hi!

I have a 2D gmsh mesh with elements of order 1. On the other hand, I am using a function space with linear Lagrange elements.

Why in general the number of vertices in my gmsh mesh model is not equivalent to the number of degrees of freedom of the function space?

Regards,
Jorge

Can you provide a MWE?

Hi @nate,

I am using dolfinx 0.7.2

Here is a MWE.


"""
============================================================================================================
NAME:
    generate_hollow_disc

PURPOSE: As the name suggests, this function generate the model of a hollow disc mesh using gmsh software.

INPUT:
    max_mesh_size := maximum mesh element size
    element_order := order of the curves you want to use to connect the vertices of an elements
    algo_2D := identifier of the type of 2D mesh generator algorithm
    r_bottom := radial location of the hollow disc bottom
    r_top := radial location of the hollow disc top
    inner_marker := will mark the inner hollow disc
    bottom_boundary_marker := will mark the bottom boundary
    top_boundary_marker := will mark the real top boundary
    ========================================================================================================
"""    
def generate_hollow_disc(max_mesh_size,r_bottom,r_top,inner_marker,bottom_boundary_marker,
                         top_boundary_marker,element_order=1,algo_2D=1):

    circle1 = gmsh.model.occ.addCircle(0,0,0,r_bottom,tag=1)
    circle2 = gmsh.model.occ.addCircle(0,0,0,r_top,tag=2)
    curveLoop1 = gmsh.model.occ.addCurveLoop([circle1])
    curveLoop2 = gmsh.model.occ.addCurveLoop([circle2])

    hollow_disc = gmsh.model.occ.addPlaneSurface([curveLoop1,curveLoop2],tag=3) 

    gdim = 2
    gmsh.model.occ.synchronize()

    gmsh.model.addPhysicalGroup(gdim,[hollow_disc],inner_marker)
    gmsh.model.addPhysicalGroup(gdim-1,[circle1],bottom_boundary_marker)
    gmsh.model.addPhysicalGroup(gdim-1,[circle2],top_boundary_marker)

    gmsh.option.setNumber("Mesh.CharacteristicLengthMin",0)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMax",max_mesh_size)
    gmsh.option.setNumber("Mesh.ElementOrder",element_order)
    gmsh.option.setNumber("Mesh.Algorithm",algo_2D)

    gmsh.model.occ.synchronize()
    gmsh.model.mesh.generate(gdim)

    return gmsh.model

if __name__=='__main__':

    # vars
    max_mesh_size = 1e-2
    r_bottom, r_top = 0.9, 1.0
    inner_marker, bottom_boundary_marker, top_boundary_marker = 33, 44, 55
    element_order = 1
    algo_2D = 1

    # mpi 
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    size = comm.Get_size()

    # gmsh
    gmsh.initialize()
    gmsh_model = generate_hollow_disc(max_mesh_size,r_bottom,r_top,inner_marker,bottom_boundary_marker,
                                      top_boundary_marker,element_order,algo_2D)
    gmsh_model_rank = 0
    domain, cell_markers, facet_markers = dolfinx.io.gmshio.model_to_mesh(gmsh_model,comm,gmsh_model_rank,gdim=2)
    gmsh.finalize()
    
    # shape of domain geometry array is (number_of_nodes,dof_per_node)
    print()
    print('shape of mesh geometry ndarray is: ' ,domain.geometry.x.shape)
    print()

    # create function space
    Q = dolfinx.fem.FunctionSpace(domain,("Lagrange",1))
   
    # shape of degrees of freedom array is (number_of_nodes,dof_per_node)
    print()
    print('shape of function space dofmap ndarray is: ', Q.dofmap.list.shape)
    print()

The function you’re calling I doubt is what you’re expecting:

If you instead report the number of local DoFs you’ll see what you expect, e.g:

    print(Q.dofmap.index_map.size_local)
1 Like

Hi @nate,

Thanks for your response.

May you explain what the property “list” does?

Regards,
Jorge

Give you an adjacency list with the DoFs associated with each cell. So for P1 Lagrange on a mesh of triangles you’d have 3 DoFs per cell. That list tells you which belong to each cell.

1 Like