1e83e87a5Sjeremylt #include "../include/petscutils.h" 2e83e87a5Sjeremylt 3e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 4e83e87a5Sjeremylt // Convert PETSc MemType to libCEED MemType 5e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 69b072555Sjeremylt CeedMemType MemTypeP2C(PetscMemType mem_type) { 79b072555Sjeremylt return PetscMemTypeDevice(mem_type) ? CEED_MEM_DEVICE : CEED_MEM_HOST; 8e83e87a5Sjeremylt } 9e83e87a5Sjeremylt 10e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 11e83e87a5Sjeremylt // Utility function taken from petsc/src/dm/impls/plex/examples/tutorials/ex7.c 12e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 13e83e87a5Sjeremylt PetscErrorCode ProjectToUnitSphere(DM dm) { 14e83e87a5Sjeremylt Vec coordinates; 15e83e87a5Sjeremylt PetscScalar *coords; 16e83e87a5Sjeremylt PetscInt Nv, v, dim, d; 17e83e87a5Sjeremylt PetscErrorCode ierr; 18e83e87a5Sjeremylt 19e83e87a5Sjeremylt PetscFunctionBeginUser; 20e83e87a5Sjeremylt ierr = DMGetCoordinatesLocal(dm, &coordinates); CHKERRQ(ierr); 21e83e87a5Sjeremylt ierr = VecGetLocalSize(coordinates, &Nv); CHKERRQ(ierr); 22e83e87a5Sjeremylt ierr = VecGetBlockSize(coordinates, &dim); CHKERRQ(ierr); 23e83e87a5Sjeremylt Nv /= dim; 24e83e87a5Sjeremylt ierr = VecGetArray(coordinates, &coords); CHKERRQ(ierr); 25e83e87a5Sjeremylt for (v = 0; v < Nv; ++v) { 26e83e87a5Sjeremylt PetscReal r = 0.0; 27e83e87a5Sjeremylt 28e83e87a5Sjeremylt for (d = 0; d < dim; ++d) r += PetscSqr(PetscRealPart(coords[v*dim+d])); 29e83e87a5Sjeremylt r = PetscSqrtReal(r); 30e83e87a5Sjeremylt for (d = 0; d < dim; ++d) coords[v*dim+d] /= r; 31e83e87a5Sjeremylt } 32e83e87a5Sjeremylt ierr = VecRestoreArray(coordinates, &coords); CHKERRQ(ierr); 33e83e87a5Sjeremylt PetscFunctionReturn(0); 34e83e87a5Sjeremylt }; 35e83e87a5Sjeremylt 36e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 372c58efb6Sjeremylt // Apply 3D Kershaw mesh transformation 382c58efb6Sjeremylt // ----------------------------------------------------------------------------- 392c58efb6Sjeremylt // Transition from a value of "a" for x=0, to a value of "b" for x=1. Optionally 402c58efb6Sjeremylt // smooth -- see the commented versions at the end. 412c58efb6Sjeremylt static double step(const double a, const double b, double x) { 422c58efb6Sjeremylt if (x <= 0) return a; 432c58efb6Sjeremylt if (x >= 1) return b; 442c58efb6Sjeremylt return a + (b-a) * (x); 452c58efb6Sjeremylt } 462c58efb6Sjeremylt 472c58efb6Sjeremylt // 1D transformation at the right boundary 482c58efb6Sjeremylt static double right(const double eps, const double x) { 492c58efb6Sjeremylt return (x <= 0.5) ? (2-eps) * x : 1 + eps*(x-1); 502c58efb6Sjeremylt } 512c58efb6Sjeremylt 522c58efb6Sjeremylt // 1D transformation at the left boundary 532c58efb6Sjeremylt static double left(const double eps, const double x) { 542c58efb6Sjeremylt return 1-right(eps,1-x); 552c58efb6Sjeremylt } 562c58efb6Sjeremylt 572c58efb6Sjeremylt // Apply 3D Kershaw mesh transformation 582c58efb6Sjeremylt // The eps parameters are in (0, 1] 592c58efb6Sjeremylt // Uniform mesh is recovered for eps=1 609b072555Sjeremylt PetscErrorCode Kershaw(DM dm_orig, PetscScalar eps) { 612c58efb6Sjeremylt PetscErrorCode ierr; 622c58efb6Sjeremylt Vec coord; 632c58efb6Sjeremylt PetscInt ncoord; 642c58efb6Sjeremylt PetscScalar *c; 652c58efb6Sjeremylt 662c58efb6Sjeremylt PetscFunctionBeginUser; 679b072555Sjeremylt ierr = DMGetCoordinatesLocal(dm_orig, &coord); CHKERRQ(ierr); 682c58efb6Sjeremylt ierr = VecGetLocalSize(coord, &ncoord); CHKERRQ(ierr); 692c58efb6Sjeremylt ierr = VecGetArray(coord, &c); CHKERRQ(ierr); 702c58efb6Sjeremylt 712c58efb6Sjeremylt for (PetscInt i = 0; i < ncoord; i += 3) { 722c58efb6Sjeremylt PetscScalar x = c[i], y = c[i+1], z = c[i+2]; 732c58efb6Sjeremylt PetscInt layer = x*6; 742c58efb6Sjeremylt PetscScalar lambda = (x-layer/6.0)*6; 752c58efb6Sjeremylt c[i] = x; 762c58efb6Sjeremylt 772c58efb6Sjeremylt switch (layer) { 782c58efb6Sjeremylt case 0: 792c58efb6Sjeremylt c[i+1] = left(eps, y); 802c58efb6Sjeremylt c[i+2] = left(eps, z); 812c58efb6Sjeremylt break; 822c58efb6Sjeremylt case 1: 832c58efb6Sjeremylt case 4: 842c58efb6Sjeremylt c[i+1] = step(left(eps, y), right(eps, y), lambda); 852c58efb6Sjeremylt c[i+2] = step(left(eps, z), right(eps, z), lambda); 862c58efb6Sjeremylt break; 872c58efb6Sjeremylt case 2: 882c58efb6Sjeremylt c[i+1] = step(right(eps, y), left(eps, y), lambda/2); 892c58efb6Sjeremylt c[i+2] = step(right(eps, z), left(eps, z), lambda/2); 902c58efb6Sjeremylt break; 912c58efb6Sjeremylt case 3: 922c58efb6Sjeremylt c[i+1] = step(right(eps, y), left(eps, y), (1+lambda)/2); 932c58efb6Sjeremylt c[i+2] = step(right(eps, z), left(eps, z), (1+lambda)/2); 942c58efb6Sjeremylt break; 952c58efb6Sjeremylt default: 962c58efb6Sjeremylt c[i+1] = right(eps, y); 972c58efb6Sjeremylt c[i+2] = right(eps, z); 982c58efb6Sjeremylt } 992c58efb6Sjeremylt } 1002c58efb6Sjeremylt ierr = VecRestoreArray(coord, &c); CHKERRQ(ierr); 1012c58efb6Sjeremylt PetscFunctionReturn(0); 1022c58efb6Sjeremylt } 1032c58efb6Sjeremylt 1042c58efb6Sjeremylt // ----------------------------------------------------------------------------- 105e83e87a5Sjeremylt // Create BC label 106e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 107e83e87a5Sjeremylt static PetscErrorCode CreateBCLabel(DM dm, const char name[]) { 108e83e87a5Sjeremylt int ierr; 109e83e87a5Sjeremylt DMLabel label; 110e83e87a5Sjeremylt 111e83e87a5Sjeremylt PetscFunctionBeginUser; 112e83e87a5Sjeremylt 113e83e87a5Sjeremylt ierr = DMCreateLabel(dm, name); CHKERRQ(ierr); 114e83e87a5Sjeremylt ierr = DMGetLabel(dm, name, &label); CHKERRQ(ierr); 115e83e87a5Sjeremylt ierr = DMPlexMarkBoundaryFaces(dm, 1, label); CHKERRQ(ierr); 116e83e87a5Sjeremylt ierr = DMPlexLabelComplete(dm, label); CHKERRQ(ierr); 117e83e87a5Sjeremylt 118e83e87a5Sjeremylt PetscFunctionReturn(0); 119e83e87a5Sjeremylt }; 120e83e87a5Sjeremylt 121e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 122e83e87a5Sjeremylt // This function sets up a DM for a given degree 123e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 1249b072555Sjeremylt PetscErrorCode SetupDMByDegree(DM dm, PetscInt degree, PetscInt num_comp_u, 1259b072555Sjeremylt PetscInt dim, bool enforce_bc, BCFunction bc_func) { 126e83e87a5Sjeremylt PetscInt ierr, marker_ids[1] = {1}; 127e83e87a5Sjeremylt PetscFE fe; 12865233696SJeremy L Thompson MPI_Comm comm; 129e83e87a5Sjeremylt 130e83e87a5Sjeremylt PetscFunctionBeginUser; 131e83e87a5Sjeremylt 132e83e87a5Sjeremylt // Setup FE 13365233696SJeremy L Thompson ierr = PetscObjectGetComm((PetscObject)dm, &comm); CHKERRQ(ierr); 13465233696SJeremy L Thompson ierr = PetscFECreateLagrange(comm, dim, num_comp_u, PETSC_FALSE, degree, degree, 13565233696SJeremy L Thompson &fe); CHKERRQ(ierr); 136e83e87a5Sjeremylt ierr = DMSetFromOptions(dm); CHKERRQ(ierr); 137e83e87a5Sjeremylt ierr = DMAddField(dm, NULL, (PetscObject)fe); CHKERRQ(ierr); 1387ed3e4cdSJeremy L Thompson { 1397ed3e4cdSJeremy L Thompson /* create FE field for coordinates */ 1407ed3e4cdSJeremy L Thompson PetscFE fe_coords; 1417ed3e4cdSJeremy L Thompson PetscInt num_comp_coord; 1427ed3e4cdSJeremy L Thompson ierr = DMGetCoordinateDim(dm, &num_comp_coord); CHKERRQ(ierr); 1437ed3e4cdSJeremy L Thompson ierr = PetscFECreateLagrange(comm, dim, num_comp_coord, PETSC_FALSE, 1, 1, 1447ed3e4cdSJeremy L Thompson &fe_coords); CHKERRQ(ierr); 1457ed3e4cdSJeremy L Thompson ierr = DMProjectCoordinates(dm, fe_coords); CHKERRQ(ierr); 1467ed3e4cdSJeremy L Thompson ierr = PetscFEDestroy(&fe_coords); CHKERRQ(ierr); 1477ed3e4cdSJeremy L Thompson } 148e83e87a5Sjeremylt 149e83e87a5Sjeremylt // Setup DM 150e83e87a5Sjeremylt ierr = DMCreateDS(dm); CHKERRQ(ierr); 1519b072555Sjeremylt if (enforce_bc) { 1529b072555Sjeremylt PetscBool has_label; 1539b072555Sjeremylt DMHasLabel(dm, "marker", &has_label); 1549b072555Sjeremylt if (!has_label) {CreateBCLabel(dm, "marker");} 15569f5adf1Sjeremylt DMLabel label; 15669f5adf1Sjeremylt ierr = DMGetLabel(dm, "marker", &label); CHKERRQ(ierr); 157*b8962995SJeremy L Thompson ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", label, 1, 158*b8962995SJeremy L Thompson marker_ids, 0, 0, NULL, (void(*)(void))bc_func, 159*b8962995SJeremy L Thompson NULL, NULL, NULL); CHKERRQ(ierr); 160e83e87a5Sjeremylt } 161e83e87a5Sjeremylt ierr = DMPlexSetClosurePermutationTensor(dm, PETSC_DETERMINE, NULL); 162e83e87a5Sjeremylt CHKERRQ(ierr); 163e83e87a5Sjeremylt ierr = PetscFEDestroy(&fe); CHKERRQ(ierr); 164e83e87a5Sjeremylt 165e83e87a5Sjeremylt PetscFunctionReturn(0); 166e83e87a5Sjeremylt }; 167e83e87a5Sjeremylt 168e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 169e83e87a5Sjeremylt // Utility function - essential BC dofs are encoded in closure indices as -(i+1) 170e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 171e83e87a5Sjeremylt PetscInt Involute(PetscInt i) { 172e83e87a5Sjeremylt return i >= 0 ? i : -(i + 1); 173e83e87a5Sjeremylt }; 174e83e87a5Sjeremylt 175e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 176e83e87a5Sjeremylt // Get CEED restriction data from DMPlex 177e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 1787ed3e4cdSJeremy L Thompson PetscErrorCode CreateRestrictionFromPlex(Ceed ceed, DM dm, CeedInt height, 1797ed3e4cdSJeremy L Thompson DMLabel domain_label, CeedInt value, CeedElemRestriction *elem_restr) { 1807ed3e4cdSJeremy L Thompson PetscInt num_elem, elem_size, num_dof, num_comp, *elem_restr_offsets; 181e83e87a5Sjeremylt PetscErrorCode ierr; 182e83e87a5Sjeremylt 183e83e87a5Sjeremylt PetscFunctionBeginUser; 184e83e87a5Sjeremylt 1857ed3e4cdSJeremy L Thompson ierr = DMPlexGetLocalOffsets(dm, domain_label, value, height, 0, &num_elem, 1867ed3e4cdSJeremy L Thompson &elem_size, &num_comp, &num_dof, &elem_restr_offsets); 1877ed3e4cdSJeremy L Thompson CHKERRQ(ierr); 188e83e87a5Sjeremylt 1897ed3e4cdSJeremy L Thompson CeedElemRestrictionCreate(ceed, num_elem, elem_size, num_comp, 1907ed3e4cdSJeremy L Thompson 1, num_dof, CEED_MEM_HOST, CEED_COPY_VALUES, 1919b072555Sjeremylt elem_restr_offsets, elem_restr); 1929b072555Sjeremylt ierr = PetscFree(elem_restr_offsets); CHKERRQ(ierr); 1937ed3e4cdSJeremy L Thompson 194e83e87a5Sjeremylt PetscFunctionReturn(0); 195e83e87a5Sjeremylt }; 196e83e87a5Sjeremylt 197e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 198