1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 3 PetscErrorCode DMPlexInvertCell_Internal(PetscInt dim, PetscInt numCorners, PetscInt cone[]) 4 { 5 int tmpc; 6 7 PetscFunctionBegin; 8 if (dim != 3) PetscFunctionReturn(0); 9 switch (numCorners) { 10 case 4: 11 tmpc = cone[0]; 12 cone[0] = cone[1]; 13 cone[1] = tmpc; 14 break; 15 case 8: 16 tmpc = cone[1]; 17 cone[1] = cone[3]; 18 cone[3] = tmpc; 19 break; 20 default: break; 21 } 22 PetscFunctionReturn(0); 23 } 24 25 /*@C 26 DMPlexInvertCell - This flips tetrahedron and hexahedron orientation since Plex stores them internally with outward normals. Other cells are left untouched. 27 28 Input Parameters: 29 + numCorners - The number of vertices in a cell 30 - cone - The incoming cone 31 32 Output Parameter: 33 . cone - The inverted cone (in-place) 34 35 Level: developer 36 37 .seealso: DMPlexGenerate() 38 @*/ 39 PetscErrorCode DMPlexInvertCell(PetscInt dim, PetscInt numCorners, int cone[]) 40 { 41 int tmpc; 42 43 PetscFunctionBegin; 44 if (dim != 3) PetscFunctionReturn(0); 45 switch (numCorners) { 46 case 4: 47 tmpc = cone[0]; 48 cone[0] = cone[1]; 49 cone[1] = tmpc; 50 break; 51 case 8: 52 tmpc = cone[1]; 53 cone[1] = cone[3]; 54 cone[3] = tmpc; 55 break; 56 default: break; 57 } 58 PetscFunctionReturn(0); 59 } 60 61 62 /*@C 63 DMPlexTriangleSetOptions - Set the options used for the Triangle mesh generator 64 65 Not Collective 66 67 Inputs Parameters: 68 + dm - The DMPlex object 69 - opts - The command line options 70 71 Level: developer 72 73 .seealso: DMPlexTetgenSetOptions(), DMPlexGenerate() 74 @*/ 75 PetscErrorCode DMPlexTriangleSetOptions(DM dm, const char *opts) 76 { 77 DM_Plex *mesh = (DM_Plex*) dm->data; 78 PetscErrorCode ierr; 79 80 PetscFunctionBegin; 81 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 82 PetscValidPointer(opts, 2); 83 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 84 ierr = PetscStrallocpy(opts, &mesh->triangleOpts);CHKERRQ(ierr); 85 PetscFunctionReturn(0); 86 } 87 88 /*@C 89 DMPlexTetgenSetOptions - Set the options used for the Tetgen mesh generator 90 91 Not Collective 92 93 Inputs Parameters: 94 + dm - The DMPlex object 95 - opts - The command line options 96 97 Level: developer 98 99 .seealso: DMPlexTriangleSetOptions(), DMPlexGenerate() 100 @*/ 101 PetscErrorCode DMPlexTetgenSetOptions(DM dm, const char *opts) 102 { 103 DM_Plex *mesh = (DM_Plex*) dm->data; 104 PetscErrorCode ierr; 105 106 PetscFunctionBegin; 107 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 108 PetscValidPointer(opts, 2); 109 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 110 ierr = PetscStrallocpy(opts, &mesh->tetgenOpts);CHKERRQ(ierr); 111 PetscFunctionReturn(0); 112 } 113 114 /* 115 Contains the list of registered DMPlexGenerators routines 116 */ 117 PetscFunctionList DMPlexGenerateList = NULL; 118 119 struct _n_PetscFunctionList { 120 PetscErrorCode (*generate)(DM, PetscBool, DM*); 121 PetscErrorCode (*refine)(DM,double*, DM*); 122 char *name; /* string to identify routine */ 123 PetscInt dim; 124 PetscFunctionList next; /* next pointer */ 125 }; 126 127 /*@C 128 DMPlexGenerate - Generates a mesh. 129 130 Not Collective 131 132 Input Parameters: 133 + boundary - The DMPlex boundary object 134 . name - The mesh generation package name 135 - interpolate - Flag to create intermediate mesh elements 136 137 Output Parameter: 138 . mesh - The DMPlex object 139 140 Options Database: 141 + -dm_plex_generate <name> - package to generate mesh, for example, triangle, ctetgen or tetgen 142 - -dm_plex_generator <name> - package to generate mesh, for example, triangle, ctetgen or tetgen (deprecated) 143 144 Level: intermediate 145 146 .seealso: DMPlexCreate(), DMRefine() 147 @*/ 148 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 149 { 150 PetscInt dim; 151 char genname[1024]; 152 PetscBool flg; 153 PetscErrorCode ierr; 154 PetscFunctionList fl; 155 const char* suggestions; 156 157 PetscFunctionBegin; 158 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 159 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 160 ierr = DMGetDimension(boundary, &dim);CHKERRQ(ierr); 161 ierr = PetscOptionsGetString(((PetscObject) boundary)->options,((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 162 if (flg) name = genname; 163 else { 164 ierr = PetscOptionsGetString(((PetscObject) boundary)->options,((PetscObject) boundary)->prefix, "-dm_plex_generate", genname, 1024, &flg);CHKERRQ(ierr); 165 if (flg) name = genname; 166 } 167 168 fl = DMPlexGenerateList; 169 if (name) { 170 while (fl) { 171 ierr = PetscStrcmp(fl->name,name,&flg);CHKERRQ(ierr); 172 if (flg) { 173 ierr = (*fl->generate)(boundary,interpolate,mesh);CHKERRQ(ierr); 174 PetscFunctionReturn(0); 175 } 176 fl = fl->next; 177 } 178 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Grid generator %s not registered; you may need to add --download-%s to your ./configure options",name,name); 179 } else { 180 while (fl) { 181 if (boundary->dim == fl->dim) { 182 ierr = (*fl->generate)(boundary,interpolate,mesh);CHKERRQ(ierr); 183 PetscFunctionReturn(0); 184 } 185 fl = fl->next; 186 } 187 suggestions = ""; 188 if (boundary->dim+1 == 2) suggestions = " You may need to add --download-triangle to your ./configure options"; 189 else if (boundary->dim+1 == 3) suggestions = " You may need to add --download-ctetgen or --download-tetgen in your ./configure options"; 190 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"No grid generator of dimension %D registered%s",boundary->dim+1,suggestions); 191 } 192 PetscFunctionReturn(0); 193 } 194 195 /*@C 196 DMPlexGenerateRegister - Adds a grid generator to DMPlex 197 198 Not Collective 199 200 Input Parameters: 201 + name_solver - name of a new user-defined grid generator 202 . fnc - generator function 203 . rfnc - refinement function 204 - dim - dimension of boundary of domain 205 206 Notes: 207 DMPlexGenerateRegister() may be called multiple times to add several user-defined solvers. 208 209 Sample usage: 210 .vb 211 DMPlexGenerateRegister("my_generator",MyGeneratorCreate,MyGeneratorRefiner,dim); 212 .ve 213 214 Then, your generator can be chosen with the procedural interface via 215 $ DMPlexGenerate(dm,"my_generator",...) 216 or at runtime via the option 217 $ -dm_plex_generator my_generator 218 219 Level: advanced 220 221 .seealso: DMPlexGenerateRegisterAll(), DMPlexGenerate(), DMPlexGenerateRegisterDestroy() 222 223 @*/ 224 PetscErrorCode DMPlexGenerateRegister(const char sname[],PetscErrorCode (*fnc)(DM, PetscBool,DM*), PetscErrorCode (*rfnc)(DM, double*,DM*),PetscInt dim) 225 { 226 PetscErrorCode ierr; 227 PetscFunctionList entry; 228 229 PetscFunctionBegin; 230 ierr = PetscNew(&entry);CHKERRQ(ierr); 231 ierr = PetscStrallocpy(sname,&entry->name);CHKERRQ(ierr); 232 entry->generate = fnc; 233 entry->refine = rfnc; 234 entry->dim = dim; 235 entry->next = NULL; 236 if (!DMPlexGenerateList) DMPlexGenerateList = entry; 237 else { 238 PetscFunctionList fl = DMPlexGenerateList; 239 while (fl->next) fl = fl->next; 240 fl->next = entry; 241 } 242 PetscFunctionReturn(0); 243 } 244 245 extern PetscBool DMPlexGenerateRegisterAllCalled; 246 247 PetscErrorCode DMPlexGenerateRegisterDestroy(void) 248 { 249 PetscFunctionList next,fl; 250 PetscErrorCode ierr; 251 252 PetscFunctionBegin; 253 next = fl = DMPlexGenerateList; 254 while (next) { 255 next = fl ? fl->next : NULL; 256 if (fl) {ierr = PetscFree(fl->name);CHKERRQ(ierr);} 257 ierr = PetscFree(fl);CHKERRQ(ierr); 258 fl = next; 259 } 260 DMPlexGenerateList = NULL; 261 DMPlexGenerateRegisterAllCalled = PETSC_FALSE; 262 PetscFunctionReturn(0); 263 } 264