Matt, Matt, Matt,
Sanjay, (1) is the only sane option. Here is an example taken from a
code that I work with.
This simply has 3 fields with 12 ("stride", not a great name, should
be "bs") dofs on each vertex in each field (2D Bell + 1D cubic Hermite).
This uses ISCreateBlock, which you might want to use for dof (1,2) in
your case. It lets, with stride = 2, input IS = [1,3] create an IS
with [2,3,6,7] semantically.
Thanks,
Mark
int matrix_solve:: setFieldSplitType()
{
// the global parameters
PetscInt ierr, dofPerEnt,stride,k;
int startDof, endDofPlusOne;
int num_own_ent=m3dc1_mesh::instance()->num_own_ent[0], num_own_dof;
m3dc1_field_getnumowndof(&fieldOrdering, &num_own_dof);
if (num_own_ent) dofPerEnt = num_own_dof/num_own_ent;
stride=dofPerEnt/3; //U 0->11, Omega 12->23, Chi 24->35
m3dc1_field_getowndofid (&fieldOrdering, &startDof, &endDofPlusOne);
startDof=startDof/stride;
// the 3 fields for PCFIELDSPLIT
IS field0, field1, field2;
PetscInt *idx0, *idx1, *idx2;
ierr=PetscMalloc1(num_own_ent, &idx0);
ierr=PetscMalloc1(num_own_ent, &idx1);
ierr=PetscMalloc1(num_own_ent, &idx2);
for (k=0; k<num_own_ent; k++) idx0[k]=k*dofPerEnt/stride + startDof;
ierr=ISCreateBlock(PETSC_COMM_WORLD, stride, num_own_ent, idx0,
PETSC_COPY_VALUES, &field0);
for (k=0; k<num_own_ent; k++) idx1[k]=1+k*dofPerEnt/stride + startDof;
ierr=ISCreateBlock(PETSC_COMM_WORLD, stride, num_own_ent, idx1,
PETSC_COPY_VALUES, &field1);
for (k=0; k<num_own_ent; k++) idx2[k]=2+k*dofPerEnt/stride + startDof;
ierr=ISCreateBlock(PETSC_COMM_WORLD, stride, num_own_ent, idx2,
PETSC_COPY_VALUES, &field2);
PC pc;
ierr= KSPAppendOptionsPrefix(*ksp,"fs_"); // ksp is a global here
ierr=KSPGetPC(*ksp, &pc);
ierr=PCSetType(pc, PCFIELDSPLIT);
ierr=PCFieldSplitSetIS(pc, NULL, field0);
ierr=PCFieldSplitSetIS(pc, NULL, field1);
ierr=PCFieldSplitSetIS(pc, NULL, field2);
ierr=PetscFree(idx0);PetscCall
<https://urldefense.us/v3/__https://petsc.org/main/manualpages/Sys/PetscCall/__;!!G_uCfscf7eWS!YYxJCjLuXQe2lb7pLGBk_jFm3tcpXjp7fMV9Z2SjL4wXwdnCNa3qKfT2WvEkGU5XtL60cuWHGdn1_3Btpjtuwg$ >(ISDestroy
<https://urldefense.us/v3/__https://petsc.org/main/manualpages/IS/ISDestroy/__;!!G_uCfscf7eWS!YYxJCjLuXQe2lb7pLGBk_jFm3tcpXjp7fMV9Z2SjL4wXwdnCNa3qKfT2WvEkGU5XtL60cuWHGdn1_3AhggVmlQ$ >(&field0));PetscCall
<https://urldefense.us/v3/__https://petsc.org/main/manualpages/Sys/PetscCall/__;!!G_uCfscf7eWS!YYxJCjLuXQe2lb7pLGBk_jFm3tcpXjp7fMV9Z2SjL4wXwdnCNa3qKfT2WvEkGU5XtL60cuWHGdn1_3Btpjtuwg$ >(ISDestroy
<https://urldefense.us/v3/__https://petsc.org/main/manualpages/IS/ISDestroy/__;!!G_uCfscf7eWS!YYxJCjLuXQe2lb7pLGBk_jFm3tcpXjp7fMV9Z2SjL4wXwdnCNa3qKfT2WvEkGU5XtL60cuWHGdn1_3AhggVmlQ$ >(&field1));PetscCall
<https://urldefense.us/v3/__https://petsc.org/main/manualpages/Sys/PetscCall/__;!!G_uCfscf7eWS!YYxJCjLuXQe2lb7pLGBk_jFm3tcpXjp7fMV9Z2SjL4wXwdnCNa3qKfT2WvEkGU5XtL60cuWHGdn1_3Btpjtuwg$ >(ISDestroy
<https://urldefense.us/v3/__https://petsc.org/main/manualpages/IS/ISDestroy/__;!!G_uCfscf7eWS!YYxJCjLuXQe2lb7pLGBk_jFm3tcpXjp7fMV9Z2SjL4wXwdnCNa3qKfT2WvEkGU5XtL60cuWHGdn1_3AhggVmlQ$ >(&field2));
ierr=PetscFree(idx1);
ierr=PetscFree(idx2);
fsSet=1;
return0;
}
On Thu, Apr 3, 2025 at 8:57 AM Matthew Knepley <knep...@gmail.com> wrote:
On Thu, Apr 3, 2025 at 12:11 AM Sanjay Govindjee via petsc-users
<petsc-users@mcs.anl.gov> wrote:
We would like to solve an FEA problem (unstructured grid)
where the nodes on the elements have different dofs. For
example the corner nodes have only dof 0 and then mid-side
nodes have dofs 0,1,2 (think 8 node serendipity element).
This is a multi-physics problem so we are looking to use the
fieldsplit features to pre-condition and solve. Is there a
simple example of this type of usage in the src that we can
try to mimic?
I presume this will take programming as opposed to just
setting command line options.
It will take a little programming, but not much. Here is the idea.
FieldSplit needs to know what dofs belong to what field. There are
a couple of ways to do this, at different levels of abstraction.
1. Low level
You can explicitly makes lists of the dofs in each field, as an
IS, and call
https://urldefense.us/v3/__https://petsc.org/main/manualpages/PC/PCFieldSplitSetIS/__;!!G_uCfscf7eWS!YYxJCjLuXQe2lb7pLGBk_jFm3tcpXjp7fMV9Z2SjL4wXwdnCNa3qKfT2WvEkGU5XtL60cuWHGdn1_3C_POMvmw$
<https://urldefense.us/v3/__https://petsc.org/main/manualpages/PC/PCFieldSplitSetIS/__;!!G_uCfscf7eWS!aMROjbrPD3RYXMpO8mIii7q8eXZX1uN-6F6-g_jcNLLXGCgYPt2JEDkIIQCHs_vNBhhxsiwQJaz57ydxKyWe$>
for each field. This is not very flexible, but the easiest to
understand.
2. Intermediate level
You can make a DMShell, and then make a PetscSection, that gives
the number of dofs on each vertex and edge. Then call KSPSetDM()
or SNESSetDM(), and you can do nested fieldsplits from the command
line. This also retains a connection between the topology and the
data layout, but you have to deal with that pesky DM object.
3. High level
You can use a DMPlex to represent your grid and a PetscFE to
represent the discretization, and then layout is done
automatically, and nested fieldsplits can be done from the command
line. I am not 100% sure PetscFE can represent what you want, but
you can always call DMPlexCreateSection() by hand to make the
PetscSection.
Thanks,
Matt
-sanjay
--
What most experimenters take for granted before they begin their
experiments is infinitely more interesting than any results to
which their experiments lead.
-- Norbert Wiener
https://urldefense.us/v3/__https://www.cse.buffalo.edu/*knepley/__;fg!!G_uCfscf7eWS!YYxJCjLuXQe2lb7pLGBk_jFm3tcpXjp7fMV9Z2SjL4wXwdnCNa3qKfT2WvEkGU5XtL60cuWHGdn1_3ALPfLgEw$
<https://urldefense.us/v3/__http://www.cse.buffalo.edu/*knepley/__;fg!!G_uCfscf7eWS!aMROjbrPD3RYXMpO8mIii7q8eXZX1uN-6F6-g_jcNLLXGCgYPt2JEDkIIQCHs_vNBhhxsiwQJaz57-FUThx2$>