Good Morning,

I'm trying to verify that the CAD -> PETSc/DMPlex methods I've developed
can be used for FEM analyses using PETSc. Attached is my current attempt
where I import a CAD STEP file to create a volumetric tetrahedral
discretization (DMPlex),  designate boundary condition points using
DMLabels, and solve the Laplace problem (heat) with Dirichlet conditions on
each end. At command line I indicate the STEP file with the -filename
option and the dual space degree with -petscspace_degree 2. The run ends
with either a SEGV Fault or a General MPI Communication Error.

Could you please look over the attached file to tell me if what I'm doing
to set up the FEM problem is wrong?

Thank you in advance for your time and help.
-Brandon

TYPICAL ERROR MESSAGE
[0]PETSC ERROR: --------------------- Error Message
--------------------------------------------------------------
[0]PETSC ERROR: General MPI error
[0]PETSC ERROR: MPI error 605109765 Invalid communicator, error stack:
                PMPI_Comm_get_attr(344): MPI_Comm_get_attr(comm=0x0,
comm_keyval=-1539309568, attribute_val=0x7ffe75a58848, flag=0x7ffe75a58844)
failed
                MPII_Comm_get_attr(257): MPIR_Comm_get_attr(comm=0x0,
comm_keyval=-1539309568, attribute_val=0x7ffe75a58848, flag=0x7ffe75a58844)
failed
                MPII_Comm_get_attr(53).: Invalid communicator
[0]PETSC ERROR: WARNING! There are option(s) set that were not used! Could
be the program crashed before they were used or a spelling mistake, etc!
[0]PETSC ERROR:   Option left: name:-dm_plex_refine_without_snap_to_geom
value: 0 source: command line
[0]PETSC ERROR:   Option left: name:-dm_refine value: 1 source: command line
[0]PETSC ERROR:   Option left: name:-snes_monitor (no value) source:
command line
[0]PETSC ERROR: See https://petsc.org/release/faq/ for trouble shooting.
[0]PETSC ERROR: Petsc Development GIT revision: v3.18.5-1817-gd2497b8de4c
GIT Date: 2023-05-22 18:44:03 +0000
[0]PETSC ERROR: ./thermal on a  named XPS. by bdenton Wed Jun  7 11:03:43
2023
[0]PETSC ERROR: Configure options --with-make-np=16
--prefix=/mnt/c/Users/Brandon/software/libs/petsc/3.19.1-gitlab/gcc/11.2.0/mpich/3.4.2/openblas/0.3.17/opt
--with-debugging=false --COPTFLAGS="-O3 -mavx" --CXXOPTFLAGS="-O3 -mavx"
--FOPTFLAGS=-O3 --with-shared-libraries=1
--with-mpi-dir=/mnt/c/Users/Brandon/software/libs/mpich/3.4.2/gcc/11.2.0
--with-mumps=true --download-mumps=1 --with-metis=true --download-metis=1
--with-parmetis=true --download-parmetis=1 --with-superlu=true
--download-superlu=1 --with-superludir=true --download-superlu_dist=1
--with-blacs=true --download-blacs=1 --with-scalapack=true
--download-scalapack=1 --with-hypre=true --download-hypre=1
--with-hdf5-dir=/mnt/c/Users/Brandon/software/libs/hdf5/1.12.1/gcc/11.2.0
--with-valgrind-dir=/mnt/c/Users/Brandon/software/apps/valgrind/3.14.0
--with-blas-lib="[/mnt/c/Users/Brandon/software/libs/openblas/0.3.17/gcc/11.2.0/lib/libopenblas.so]"
--with-lapack-lib="[/mnt/c/Users/Brandon/software/libs/openblas/0.3.17/gcc/11.2.0/lib/libopenblas.so]"
--LDFLAGS= --with-tetgen=true --download-tetgen=1 --download-ctetgen=1
--download-opencascade=1 --download-egads
[0]PETSC ERROR: #1 PetscObjectName() at
/mnt/c/Users/Brandon/software/builddir/petsc-3.19.1-gitlab/src/sys/objects/pname.c:119
[0]PETSC ERROR: #2 PetscObjectGetName() at
/mnt/c/Users/Brandon/software/builddir/petsc-3.19.1-gitlab/src/sys/objects/pgname.c:27
[0]PETSC ERROR: #3 PetscDSAddBoundary() at
/mnt/c/Users/Brandon/software/builddir/petsc-3.19.1-gitlab/src/dm/dt/interface/dtds.c:3404
[0]PETSC ERROR: #4 DMAddBoundary() at
/mnt/c/Users/Brandon/software/builddir/petsc-3.19.1-gitlab/src/dm/interface/dm.c:7828
[0]PETSC ERROR: #5 main() at
/mnt/c/Users/Brandon/Documents/School/Dissertation/Software/EGADS-dev/thermal_v319/thermal_nozzle.c:173
[0]PETSC ERROR: PETSc Option Table entries:
[0]PETSC ERROR: -dm_plex_geom_print_model 1 (source: command line)
[0]PETSC ERROR: -dm_plex_geom_shape_opt 0 (source: command line)
[0]PETSC ERROR: -dm_plex_refine_without_snap_to_geom 0 (source: command
line)
[0]PETSC ERROR: -dm_refine 1 (source: command line)
[0]PETSC ERROR: -filename ./examples/Nozzle_example.stp (source: command
line)
[0]PETSC ERROR: -petscspace_degree 2 (source: command line)
[0]PETSC ERROR: -snes_monitor (source: command line)
[0]PETSC ERROR: ----------------End of Error Message -------send entire
error message to petsc-ma...@mcs.anl.gov----------
application called MPI_Abort(MPI_COMM_SELF, 98) - process 0
[unset]: write_line error; fd=-1 buf=:cmd=abort exitcode=98
:
system msg for write_line failure : Bad file descriptor
static const char help[] = "Test of FEA DMPlex w/CAD functionality";

#include <petsc.h>

/* User-defined Work Context  */
typedef struct {
    PetscInt  dummy;
    char filename[PETSC_MAX_PATH_LEN];    // context containing CAD filename 
from command line
} AppCtx;


void f0_function(PetscInt dim, PetscInt Nf, PetscInt NfAux,
          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar 
u[], const PetscScalar u_t[], const PetscScalar u_x[],
          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar 
a[], const PetscScalar a_t[], const PetscScalar a_x[],
          PetscReal t, const PetscReal x[], PetscScalar f0[])
{
  f0[0] = 0.0;
}

void f1_function(PetscInt dim, PetscInt Nf, PetscInt NfAux,
          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar 
u[], const PetscScalar u_t[], const PetscScalar u_x[],
          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar 
a[], const PetscScalar a_t[], const PetscScalar a_x[],
          PetscReal t, const PetscReal x[], PetscScalar f1[])
{
  for(PetscInt d = 0; d < dim; ++d) f1[d] = u_x[d];
}

void g3_uu_function(PetscInt dim, PetscInt Nf, PetscInt NfAux,
          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar 
u[], const PetscScalar u_t[], const PetscScalar u_x[],
          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar 
a[], const PetscScalar a_t[], const PetscScalar a_x[],
          PetscReal t, const PetscReal x[], PetscScalar g3[])
{
  for (PetscInt d=0; d < dim; ++d) g3[d*dim + d] = 1.0;
}

//void bc_inlet(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, 
PetscScalar bcval[])
static PetscErrorCode bc_inlet(PetscInt dim, PetscReal time, const PetscReal 
x[], PetscInt Nc, PetscScalar *u, void *ctx)
{
  u[0] = 1400.0;
  return PETSC_SUCCESS;
  //bcval[0] = 1400.0;
}

//void bc_outlet(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt 
Nc, PetscScalar bcval[])
static PetscErrorCode bc_outlet(PetscInt dim, PetscReal time, const PetscReal 
x[], PetscInt Nc, PetscScalar *u, void *ctx)
{
  u[0] = 100.0;
  return PETSC_SUCCESS;
  //bcval[0] = 100.0;
}

/* Procees Options - This should be removed once creation bug is fixed by Prof. 
Knepley */
static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
{
  PetscFunctionBeginUser;
  options->filename[0] = '\0';

  PetscOptionsBegin(comm, "", "FEA DMPlex w/CAD Options", "DMPlex w/CAD");
  PetscOptionsString("-filename", "The CAD/Geometry file", "ex18.c", 
options->filename, options->filename, PETSC_MAX_PATH_LEN, NULL);
  PetscOptionsEnd();
  PetscFunctionReturn(0);
}

/* Main Function */
int main(int argc, char **argv)
{
  // Define PETSc Variables
  DM            dm, dmSurface;    // Unstructured Grid
  SNES          snes;             // Nonlinear Solver
  Vec           temp;             // Solutions
  AppCtx        ctx;      // User-defined Work Context
  PetscInt      dim;      // DM Geometric Dimension
  PetscBool     simplex;  // Is DMPlex Simplex type?
  PetscFE       fe;       // PETSc Finite Element Object
  PetscDS       ds;       // PETSc Discretization System Object
  PetscMPIInt   rank;     // PETSc MPI Processor ID
  
  PetscFunctionBeginUser;
  PetscCall(PetscInitialize(&argc, &argv, NULL, help));   // Initialize PETSc
  PetscCall(ProcessOptions(PETSC_COMM_WORLD, &ctx));      // Process Options :: 
Here we get the filename from the command line options

  PetscCall(DMCreate(PETSC_COMM_WORLD, &dmSurface));
  PetscCall(DMCreate(PETSC_COMM_WORLD, &dm));
  PetscCall(DMSetType(dmSurface, DMPLEX));
  PetscCall(DMSetType(dm, DMPLEX));
  
  // Create DMPlex from CAD file
  PetscCall(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));      // Get Rank of 
Current Processor
  if (!rank) {
    PetscCall(DMPlexCreateFromFile(PETSC_COMM_WORLD, ctx.filename, "EGADS", 
PETSC_TRUE, &dmSurface)); // Return dm created from CAD file
  }
  
  // Setup DMLabels for Boundary Conditions on DMPlex Vertices
  PetscInt    nStart, nEnd, eStart, eEnd, faceID;
  DMLabel     inletLabel, outletLabel;
  const PetscInt  idA = 1, idB = 2;
  
  PetscCall(DMCreateLabel(dmSurface, "inlet"));
  PetscCall(DMCreateLabel(dmSurface, "outlet"));
  PetscCall(DMGetLabel(dmSurface, "inlet", &inletLabel));
  PetscCall(DMGetLabel(dmSurface, "outlet", &outletLabel));
  PetscCall(DMPlexGetDepthStratum(dmSurface, 0, &nStart, &nEnd));
  PetscCall(DMPlexGetDepthStratum(dmSurface, 1, &eStart, &eEnd));
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [nStart = %d  ||  nEnd = %d] \n", 
nStart, nEnd));
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [eStart = %d  ||  eEnd = %d] \n", 
eStart, eEnd));
  for (PetscInt ii = nStart; ii < nEnd; ++ii) {
    PetscCall(DMGetLabelValue(dmSurface, "EGADS Face ID", ii, &faceID));
    
    if (faceID == 14) {PetscCall(DMSetLabelValue(dmSurface, "inlet", ii, 
faceID));}
    if (faceID == 7)  {PetscCall(DMSetLabelValue(dmSurface, "outlet", ii, 
faceID));}
  }
  
  for (PetscInt ii = eStart; ii < eEnd; ++ii) {
    PetscCall(DMGetLabelValue(dmSurface, "EGADS Face ID", ii, &faceID));
    
    if (faceID == 14) {PetscCall(DMSetLabelValue(dmSurface, "inlet", ii, 
faceID));}
    if (faceID == 7)  {PetscCall(DMSetLabelValue(dmSurface, "outlet", ii, 
faceID));}
  }
  
  // Generate Volumetric Mesh
  PetscCall(DMPlexGenerate(dmSurface, "tetgen", PETSC_TRUE, &dm));   // 
Generate Volumetric Mesh
  PetscCall(DMDestroy(&dmSurface));      // Destroy DM dmSurface no longer 
needed
  PetscCall(DMSetApplicationContext(dm, &ctx));            // Link context to dm
  PetscCall(DMViewFromOptions(dm, NULL, "-dm_view"));     // Write DM to file 
(hdf5)
  PetscCall(DMView(dm, PETSC_VIEWER_STDOUT_SELF));
  
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [CREATED MESH] \n"));
  
  // Setup SNES and link to DM
  PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));         // Create SNES object
  PetscCall(SNESSetDM(snes, dm));                         // Link SNES object 
to DM
  
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [SETUP SNES] \n"));
  
  // Setup Discretization
  PetscCall(DMGetDimension(dm, &dim));        // Get Geometric Dimension of the 
DM (2D or 3D)
  PetscCall(DMPlexIsSimplex(dm, &simplex));   // Check if DMPlex is Simplex Type
  PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, 1, 
simplex, NULL, -1, &fe));    // Define and Create PetscFE Object
  PetscCall(DMAddField(dm, NULL, (PetscObject)fe));        // Add Field to 
Discretization object. In this case, the temperature field.
  PetscCall(DMCreateDS(dm));                  // Create The Discretization 
System (DS) based on the field(s) added to the DM
  
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [SETUP DISCRETIZATION] \n"));
  
  // Setup Residuals & (Optional) Jacobian
  PetscInt    testFieldID = 0;                // This is an assumption. How do 
we find out which field ID goes with each added field?
  PetscCall(DMGetDS(dm, &ds));                // Get DS associated with DM
  PetscCall(PetscDSSetResidual(ds, testFieldID, (void (*))f0_function, (void 
(*))f1_function));            // Set Residual Function
  PetscCall(PetscDSSetJacobian(ds, testFieldID, testFieldID, NULL, NULL, NULL, 
(void (*))g3_uu_function));    // Set Jacobian Function
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [SETUP RESIDUAL & JACOBIAN] \n"));
  
  // Apply inlet face conditions - Dirichlet    
  PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "inTemp", inletLabel, 1, &idA, 
0, 0, NULL, (void (*)(void))bc_inlet, NULL, &ctx, NULL));
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [SETUP BOUNDARY CONDITION inTemp] 
\n"));
  PetscCall(DMAddBoundary(dm, DM_BC_ESSENTIAL, "outTemp", outletLabel, 1, &idB, 
0, 0, NULL, (void (*)(void))bc_outlet, NULL, &ctx, NULL));

  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [SETUP BOUNDARY CONDITIONS] \n"));

  // Create Global Vector, Initialize Values & Name
  PetscCall(DMCreateGlobalVector(dm, &temp));
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [AFTER GLOBAL VECTOR] \n"));
  PetscCall(VecSet(temp, 100.0));
  PetscCall(VecView(temp, PETSC_VIEWER_STDOUT_SELF));
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [AFTER temp set to 100] \n"));
  PetscCall(PetscObjectSetName((PetscObject)temp, "temperature"));
  
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [AFTER SET OBJECT NAME] \n"));
  
  PetscCall(DMPlexSetSNESLocalFEM(dm, &ctx, &ctx, &ctx));
  
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [AFTER SNESLocalFEM] \n"));
  
  //Set SNES from Options
  PetscCall(SNESSetFromOptions(snes));
  PetscCall(SNESView(snes, PETSC_VIEWER_STDOUT_SELF));
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [AFTER SNESSetFromOptions] \n"));
  
  // Solve System of Equations
  PetscCall(SNESSolve(snes, NULL, temp));
  
  PetscCall(PetscPrintf(PETSC_COMM_SELF, "   [SOLVED PROBLEM] \n"));
  
  //Get Solution and View
  PetscCall(SNESGetSolution(snes, &temp));
  PetscCall(VecViewFromOptions(temp, NULL, "-sol_view"));
  
  // Cleanup
  PetscCall(VecDestroy(&temp));
  PetscCall(SNESDestroy(&snes));
  PetscCall(DMDestroy(&dm));

  PetscCall(PetscFinalize());  
  return 0;
}

Reply via email to