Hello,I am a student currently doing a summer project so am fairly new to
Petsc. I am trying to alter vertex coordinates of an unstructured mesh to look
at mesh movement in DMPlex
after they have been created by DMPlexCreateBoxMesh. I have been altering the
first example on the
DMPlex documentation here:
https://www.mcs.anl.gov/petsc/petsc-current/src/dm/impls/plex/examples/tutorials/ex1.c.html
I have written something that vaguely does what I want in parallel, but it has
a problem as the output from DMPlexGetPointLocal
seems to be very inconsistent. Below is my code, I was wondering if anyone had
a better way of doing this? I believeI have a bug but I am not sure where to
start. Any help and advice/comments very welcome.
Thanks,
Daniel
#include <petscdmplex.h>
#include <Eigen/Core>
#include <iostream>
using namespace Eigen;
int move_vertex(DM dm, int global_index)
{
PetscInt n, extract, st, end, dim = 2;
IS global_num;
Vec u;
const PetscInt *nindices;
PetscScalar u_array;
DMGetCoordinatesLocal(dm, &u);
DMPlexGetVertexNumbering(dm, &global_num);
bool local_point = false;
ISGetLocalSize(global_num,&n);
ISGetIndices(global_num,&nindices);
for (int j=0; j<n; j++){
if (nindices[j]==global_index){
local_point = true;
extract = j;
break;
} // Finds the processor that the vertex is assigned to and gets the local index of this vertex
}
if (local_point){
DMPlexGetPointLocal(dm, extract, &st, &end);
PetscInt ix[2] = {st,st+1};
VecGetValues(u,dim,ix,&u_array);
Map<VectorXd> test(&u_array,2);
test(0)+=-0.2; // Subtract 0.2 from x coord as a sample test
VecSetValues(u,dim,ix,&u_array,INSERT_VALUES);
} // Extracts the coordinates of the vertex, alters it and then writes it back to the Vec
DMSetCoordinatesLocal(dm, u);
return(0);
}
int main(int argc, char **argv)
{
DM dm, dmDist = NULL;
Vec c, x;
PetscSection section, sect1;
PetscInt dim = 2, numFields, numBC, i, ls;
PetscInt numComp[3];
PetscInt numDof[12];
PetscInt bcField[1];
IS bcPointIS[1];
PetscBool interpolate = PETSC_TRUE, flag0, flag1, flag2;
PetscScalar *c_array, v;
PetscScalar check1[18] = {-0.2,0.0, 0.5,0.0, 1.0,0.0, 0.0,0.5, 0.5,0.5, 1.0,0.5, 0.0,1.0, 0.5,1.0, 1.0,1.0};
try {
PetscInitialize(&argc, &argv, NULL, NULL);
}
catch (const std::exception& e) {return(0);};
PetscOptionsGetInt(NULL,NULL, "-dim", &dim, NULL);
DMPlexCreateBoxMesh(PETSC_COMM_WORLD, dim, PETSC_FALSE, NULL, NULL, NULL, NULL, interpolate, &dm);
DMPlexDistribute(dm, 0, NULL, &dmDist);
if (dmDist) {DMDestroy(&dm); dm = dmDist;}
numFields = 3;
numComp[0] = 1;
numComp[1] = dim;
numComp[2] = dim-1;
for (i = 0; i < numFields*(dim+1); ++i) numDof[i] = 0;
/* Let u be defined on vertices */
numDof[0*(dim+1)+0] = 1;
/* Let v be defined on cells */
numDof[1*(dim+1)+dim] = dim;
/* Let v be defined on faces */
numDof[2*(dim+1)+dim-1] = dim-1;
/* Setup boundary conditions */
numBC = 1;
/* Prescribe a Dirichlet condition on u on the boundary
Label "marker" is made by the mesh creation routine */
bcField[0] = 0;
DMGetStratumIS(dm, "marker", 1, &bcPointIS[0]);
/* Create a PetscSection with this data layout */
DMSetNumFields(dm, numFields);
DMPlexCreateSection(dm, NULL, numComp, numDof, numBC, bcField, NULL, bcPointIS, NULL, §ion);
ISDestroy(&bcPointIS[0]);
DMSetSection(dm, section);
move_vertex(dm, 0);
DMGetCoordinates(dm, &c);
VecCreate(PETSC_COMM_WORLD,&x);
VecGetLocalSize(c, &ls);
VecSetSizes(x,ls,PETSC_DECIDE);
VecSetFromOptions(x);
VecSet(x,v);
PetscInt j=0;
for (j=0; j<18; j++) {
v = check1[j];
VecSetValues(x,1,&j,&v,INSERT_VALUES);
}
// Tests I would like it to pass
VecAssemblyBegin(x);
VecAssemblyEnd(x);
VecEqual(x,c, &flag0); // Moving a vertex on the mesh boundary
assert(flag0 == PETSC_TRUE);
DMSetCoordinates(dm, c);
move_vertex(dm, 4);
DMGetCoordinates(dm, &c);
j=8;
v=check1[j]-0.2;
VecSetValues(x,1,&j,&v,INSERT_VALUES);
VecAssemblyBegin(x);
VecAssemblyEnd(x);
VecEqual(x,c, &flag1); // Moving a vertex on the processor boundary
assert(flag1 == PETSC_TRUE);
DMSetCoordinates(dm, c);
move_vertex(dm, 5);
DMGetCoordinates(dm, &c);
j=10;
v=check1[j]-0.2;
VecSetValues(x,1,&j,&v,INSERT_VALUES);
VecAssemblyBegin(x);
VecAssemblyEnd(x);
VecEqual(x,c, &flag2); //Moving a vertex on both the processor boundary and the mesh boundary
assert(flag2 == PETSC_TRUE);
DMSetCoordinates(dm, c);
DMDestroy(&dm);
PetscFinalize();
return(0);
}