Constraining primitive DoFs in an hp::FECollection with non-primitive elements

21 views
Skip to first unread message

Devansh Sonigra

unread,
Jul 10, 2026, 11:50:42 AM (5 days ago) Jul 10
to dea...@googlegroups.com
Hello everyone,
I am working on a multi-physics problem (fluid and solid domains) using an hp::FECollection similar to the layout in step-46. My collection is defined as:

fluid_fe(FE_Q<dim>(degree), FE_RaviartThomasNodal<dim>(degree), FE_DGQ<dim>(degree)),
wall_fe(FE_Nothing<dim>(),  FE_RaviartThomasNodal<dim>(degree), FE_DGQ<dim>(degree)),

I want to constrain the first finite element (FE_Q, component 0) to zero along the fluid-solid interface. Because my system contains a non-primitive vector element (FE_RaviartThomasNodal), standard primitive functions like face_system_to_component_index cause assertion crashes if called directly on all face DoFs.I have thought of two potential strategies to isolate and constrain only the primitive FE_Q dofs on the interface face.

First approach is to use is_primitive to safely filter out the non-primitive Raviart-Thomas face shape functions before querying the components:

// ... [Interface detection loops from step-46] ... if(face_is_on_solid_boundary)
{
   // v = 0 on boundary condition
   cell->face(face_no)->get_dof_indices(local_face_dof_indices,0);
   for(unsigned int i = 0; i < local_face_dof_indices.size();++i)
   {
      if(fluid_fe.is_primitive(fluid_fe.face_to_cell_index(i, face_no)))
      {
         if(fluid_fe.face_system_to_component_index(i).first == 0)
            constraints.constrain_dof_to_zero(local_face_dof_indices[i]);
      }
   }
}

Second approach is to utilize system_to_block_index() to target the first block directly, which circumvents checking component indices:

// ... [Interface detection loops from step-46] ...if(face_is_on_solid_boundary)
{
   // v = 0 on boundary condition
   cell->face(face_no)->get_dof_indices(local_face_dof_indices,0);
   for(unsigned int i = 0; i < local_face_dof_indices.size();++i)
   {
         if(fluid_fe.system_to_block_index(fluid_fe.face_to_cell_index(i, face_no) ).first == 0)
            constraints.constrain_dof_to_zero(local_face_dof_indices[i]);
   }
}

My questions are
1. Which of these two approaches is considered the correct or safest way in deal.II when handling a mix of primitive and non-primitive elements in an hp context?
2. I am also aware of face_system_to_base_index(i). How does this function differ from the 2 functions used above in this context and would it be a better alternative?

Any advice or feedback would be greatly appreciated!

Regards,
Devansh Sonigra.

Wolfgang Bangerth

unread,
Jul 11, 2026, 10:10:32 PM (4 days ago) Jul 11
to dea...@googlegroups.com

Devansh:

> My questions are
> 1. Which of these two approaches is considered the correct or safest way in
> deal.II when handling a mix of primitive and non-primitive elements in an
> hp context?

You can go either way, and at least for the element you have, it shouldn't
make a difference. (I assume you already tried that out.) I don't think this
is a performance critical operation, so that's not a consideration either. My
personal choice would be the second one where the if-condition picks out a
specific element by index, rather than ask about certain properties of the
element. That's because if you extend the element by additional base elements,
the if-condition in your first approach may or may not trigger for the
additional element; the second approach seems safer in this regard.


> 2. I am also aware of face_system_to_base_index(i). How does this function
> differ from the 2 functions used above in this context and would it be a
> better alternative?

face_system_to_base_index() basically combines the actions of
face_to_cell_index() and system_to_base_index(). From system_to_base_index(),
you can then determine system_to_component_index() or system_to_block_index().
So there is no conceptual difference.

Best
W.
Reply all
Reply to author
Forward
0 new messages