1 #define PETSCDM_DLL 2 #include <petsc/private/dmswarmimpl.h> /*I "petscdmswarm.h" I*/ 3 #include <petscsf.h> 4 #include <petscdmda.h> 5 #include <petscdmplex.h> 6 #include "data_bucket.h" 7 8 /* 9 Error chceking macto to ensure the swarm type is correct and that a cell DM has been set 10 */ 11 #define DMSWARMPICVALID(dm) \ 12 { \ 13 DM_Swarm *_swarm = (DM_Swarm*)(dm)->data; \ 14 if (_swarm->swarm_type != DMSWARM_PIC) SETERRQ(PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Only valid for DMSwarm-PIC. You must call DMSwarmSetType(dm,DMSWARM_PIC)"); \ 15 else \ 16 if (!_swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Only valid for DMSwarmPIC if the cell DM is set. You must call DMSwarmSetCellDM(dm,celldm)"); \ 17 } 18 19 /* Coordinate insertition/addition API */ 20 /*@C 21 DMSwarmSetPointsUniformCoordinates - Set point coordinates in a DMSwarm on a regular (ijk) grid 22 23 Collective on DM 24 25 Input parameters: 26 + dm - the DMSwarm 27 . min - minimum coordinate values in the x, y, z directions (array of length dim) 28 . max - maximum coordinate values in the x, y, z directions (array of length dim) 29 . npoints - number of points in each spatial direction (array of length dim) 30 - mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES) 31 32 Level: beginner 33 34 Notes: 35 When using mode = INSERT_VALUES, this method will reset the number of particles in the DMSwarm 36 to be npoints[0]*npoints[1] (2D) or npoints[0]*npoints[1]*npoints[2] (3D). When using mode = ADD_VALUES, 37 new points will be appended to any already existing in the DMSwarm 38 39 .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 40 @*/ 41 PETSC_EXTERN PetscErrorCode DMSwarmSetPointsUniformCoordinates(DM dm,PetscReal min[],PetscReal max[],PetscInt npoints[],InsertMode mode) 42 { 43 PetscErrorCode ierr; 44 PetscReal gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL}; 45 PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 46 PetscInt i,j,k,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found; 47 Vec coorlocal; 48 const PetscScalar *_coor; 49 DM celldm; 50 PetscReal dx[3]; 51 PetscInt _npoints[] = { 0, 0, 1 }; 52 Vec pos; 53 PetscScalar *_pos; 54 PetscReal *swarm_coor; 55 PetscInt *swarm_cellid; 56 PetscSF sfcell = NULL; 57 const PetscSFNode *LA_sfcell; 58 59 PetscFunctionBegin; 60 DMSWARMPICVALID(dm); 61 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 62 ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr); 63 ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr); 64 ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr); 65 N = N / bs; 66 ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 67 for (i=0; i<N; i++) { 68 for (b=0; b<bs; b++) { 69 gmin[b] = PetscMin(gmin[b],PetscRealPart(_coor[bs*i+b])); 70 gmax[b] = PetscMax(gmax[b],PetscRealPart(_coor[bs*i+b])); 71 } 72 } 73 ierr = VecRestoreArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 74 75 for (b=0; b<bs; b++) { 76 if (npoints[b] > 1) { 77 dx[b] = (max[b] - min[b])/((PetscReal)(npoints[b]-1)); 78 } else { 79 dx[b] = 0.0; 80 } 81 82 _npoints[b] = npoints[b]; 83 } 84 85 /* determine number of points living in the bounding box */ 86 n_estimate = 0; 87 for (k=0; k<_npoints[2]; k++) { 88 for (j=0; j<_npoints[1]; j++) { 89 for (i=0; i<_npoints[0]; i++) { 90 PetscReal xp[] = {0.0,0.0,0.0}; 91 PetscInt ijk[3]; 92 PetscBool point_inside = PETSC_TRUE; 93 94 ijk[0] = i; 95 ijk[1] = j; 96 ijk[2] = k; 97 for (b=0; b<bs; b++) { 98 xp[b] = min[b] + ijk[b] * dx[b]; 99 } 100 for (b=0; b<bs; b++) { 101 if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; } 102 if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; } 103 } 104 if (point_inside) { n_estimate++; } 105 } 106 } 107 } 108 109 /* create candidate list */ 110 ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr); 111 ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr); 112 ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr); 113 ierr = VecSetFromOptions(pos);CHKERRQ(ierr); 114 ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr); 115 116 n_estimate = 0; 117 for (k=0; k<_npoints[2]; k++) { 118 for (j=0; j<_npoints[1]; j++) { 119 for (i=0; i<_npoints[0]; i++) { 120 PetscReal xp[] = {0.0,0.0,0.0}; 121 PetscInt ijk[3]; 122 PetscBool point_inside = PETSC_TRUE; 123 124 ijk[0] = i; 125 ijk[1] = j; 126 ijk[2] = k; 127 for (b=0; b<bs; b++) { 128 xp[b] = min[b] + ijk[b] * dx[b]; 129 } 130 for (b=0; b<bs; b++) { 131 if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; } 132 if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; } 133 } 134 if (point_inside) { 135 for (b=0; b<bs; b++) { 136 _pos[bs*n_estimate+b] = xp[b]; 137 } 138 n_estimate++; 139 } 140 } 141 } 142 } 143 ierr = VecRestoreArray(pos,&_pos);CHKERRQ(ierr); 144 145 /* locate points */ 146 ierr = DMLocatePoints(celldm,pos,DM_POINTLOCATION_NONE,&sfcell);CHKERRQ(ierr); 147 148 ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr); 149 n_found = 0; 150 for (p=0; p<n_estimate; p++) { 151 if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 152 n_found++; 153 } 154 } 155 156 /* adjust size */ 157 if (mode == ADD_VALUES) { 158 ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr); 159 n_new_est = n_curr + n_found; 160 ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 161 } 162 if (mode == INSERT_VALUES) { 163 n_curr = 0; 164 n_new_est = n_found; 165 ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 166 } 167 168 /* initialize new coords, cell owners, pid */ 169 ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr); 170 ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 171 ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 172 n_found = 0; 173 for (p=0; p<n_estimate; p++) { 174 if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 175 for (b=0; b<bs; b++) { 176 swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]); 177 } 178 swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 179 n_found++; 180 } 181 } 182 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 183 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 184 ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr); 185 186 ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr); 187 ierr = VecDestroy(&pos);CHKERRQ(ierr); 188 189 PetscFunctionReturn(0); 190 } 191 192 /*@C 193 DMSwarmSetPointCoordinates - Set point coordinates in a DMSwarm from a user defined list 194 195 Collective on DM 196 197 Input parameters: 198 + dm - the DMSwarm 199 . npoints - the number of points to insert 200 . coor - the coordinate values 201 . redundant - if set to PETSC_TRUE, it is assumed that npoints and coor[] are only valid on rank 0 and should be broadcast to other ranks 202 - mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES) 203 204 Level: beginner 205 206 Notes: 207 If the user has specified redundant = PETSC_FALSE, the cell DM will attempt to locate the coordinates provided by coor[] within 208 its sub-domain. If they any values within coor[] are not located in the sub-domain, they will be ignored and will not get 209 added to the DMSwarm. 210 211 .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType, DMSwarmSetPointsUniformCoordinates() 212 @*/ 213 PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinates(DM dm,PetscInt npoints,PetscReal coor[],PetscBool redundant,InsertMode mode) 214 { 215 PetscErrorCode ierr; 216 PetscReal gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL}; 217 PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 218 PetscInt i,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found; 219 Vec coorlocal; 220 const PetscScalar *_coor; 221 DM celldm; 222 Vec pos; 223 PetscScalar *_pos; 224 PetscReal *swarm_coor; 225 PetscInt *swarm_cellid; 226 PetscSF sfcell = NULL; 227 const PetscSFNode *LA_sfcell; 228 PetscReal *my_coor; 229 PetscInt my_npoints; 230 PetscMPIInt rank; 231 MPI_Comm comm; 232 233 PetscFunctionBegin; 234 DMSWARMPICVALID(dm); 235 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 236 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 237 238 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 239 ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr); 240 ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr); 241 ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr); 242 N = N / bs; 243 ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 244 for (i=0; i<N; i++) { 245 for (b=0; b<bs; b++) { 246 gmin[b] = PetscMin(gmin[b],PetscRealPart(_coor[bs*i+b])); 247 gmax[b] = PetscMax(gmax[b],PetscRealPart(_coor[bs*i+b])); 248 } 249 } 250 ierr = VecRestoreArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 251 252 /* broadcast points from rank 0 if requested */ 253 if (redundant) { 254 my_npoints = npoints; 255 ierr = MPI_Bcast(&my_npoints,1,MPIU_INT,0,comm);CHKERRQ(ierr); 256 257 if (rank > 0) { /* allocate space */ 258 ierr = PetscMalloc1(bs*my_npoints,&my_coor);CHKERRQ(ierr); 259 } else { 260 my_coor = coor; 261 } 262 ierr = MPI_Bcast(my_coor,bs*my_npoints,MPIU_REAL,0,comm);CHKERRQ(ierr); 263 } else { 264 my_npoints = npoints; 265 my_coor = coor; 266 } 267 268 /* determine the number of points living in the bounding box */ 269 n_estimate = 0; 270 for (i=0; i<my_npoints; i++) { 271 PetscBool point_inside = PETSC_TRUE; 272 273 for (b=0; b<bs; b++) { 274 if (my_coor[bs*i+b] < gmin[b]) { point_inside = PETSC_FALSE; } 275 if (my_coor[bs*i+b] > gmax[b]) { point_inside = PETSC_FALSE; } 276 } 277 if (point_inside) { n_estimate++; } 278 } 279 280 /* create candidate list */ 281 ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr); 282 ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr); 283 ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr); 284 ierr = VecSetFromOptions(pos);CHKERRQ(ierr); 285 ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr); 286 287 n_estimate = 0; 288 for (i=0; i<my_npoints; i++) { 289 PetscBool point_inside = PETSC_TRUE; 290 291 for (b=0; b<bs; b++) { 292 if (my_coor[bs*i+b] < gmin[b]) { point_inside = PETSC_FALSE; } 293 if (my_coor[bs*i+b] > gmax[b]) { point_inside = PETSC_FALSE; } 294 } 295 if (point_inside) { 296 for (b=0; b<bs; b++) { 297 _pos[bs*n_estimate+b] = my_coor[bs*i+b]; 298 } 299 n_estimate++; 300 } 301 } 302 ierr = VecRestoreArray(pos,&_pos);CHKERRQ(ierr); 303 304 /* locate points */ 305 ierr = DMLocatePoints(celldm,pos,DM_POINTLOCATION_NONE,&sfcell);CHKERRQ(ierr); 306 307 ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr); 308 n_found = 0; 309 for (p=0; p<n_estimate; p++) { 310 if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 311 n_found++; 312 } 313 } 314 315 /* adjust size */ 316 if (mode == ADD_VALUES) { 317 ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr); 318 n_new_est = n_curr + n_found; 319 ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 320 } 321 if (mode == INSERT_VALUES) { 322 n_curr = 0; 323 n_new_est = n_found; 324 ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 325 } 326 327 /* initialize new coords, cell owners, pid */ 328 ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr); 329 ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 330 ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 331 n_found = 0; 332 for (p=0; p<n_estimate; p++) { 333 if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 334 for (b=0; b<bs; b++) { 335 swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]); 336 } 337 swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 338 n_found++; 339 } 340 } 341 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 342 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 343 ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr); 344 345 if (redundant) { 346 if (rank > 0) { 347 ierr = PetscFree(my_coor);CHKERRQ(ierr); 348 } 349 } 350 ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr); 351 ierr = VecDestroy(&pos);CHKERRQ(ierr); 352 353 PetscFunctionReturn(0); 354 } 355 356 extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM,DM,DMSwarmPICLayoutType,PetscInt); 357 extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM,DM,DMSwarmPICLayoutType,PetscInt); 358 359 /*@C 360 DMSwarmInsertPointsUsingCellDM - Insert point coordinates within each cell 361 362 Not collective 363 364 Input parameters: 365 + dm - the DMSwarm 366 . layout_type - method used to fill each cell with the cell DM 367 - fill_param - parameter controlling how many points per cell are added (the meaning of this parameter is dependent on the layout type) 368 369 Level: beginner 370 371 Notes: 372 * The insert method will reset any previous defined points within the DMSwarm. 373 * When using a DMDA both 2D and 3D are supported for all layout types provided you are using DMDA_ELEMENT_Q1. 374 * When using a DMPLEX the following case are supported 375 (i) DMSWARMPIC_LAYOUT_REGULAR: 2D (triangle), 376 (ii) DMSWARMPIC_LAYOUT_GAUSS: 2D and 3D provided the cell is a tri/tet or a quad/hex, 377 (iii) DMSWARMPIC_LAYOUT_SUBDIVISION: 2D and 3D for quad/hex and 2D tri. 378 379 .seealso: DMSwarmPICLayoutType, DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 380 @*/ 381 PETSC_EXTERN PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm,DMSwarmPICLayoutType layout_type,PetscInt fill_param) 382 { 383 PetscErrorCode ierr; 384 DM celldm; 385 PetscBool isDA,isPLEX; 386 387 PetscFunctionBegin; 388 DMSWARMPICVALID(dm); 389 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 390 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 391 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 392 if (isDA) { 393 ierr = private_DMSwarmInsertPointsUsingCellDM_DA(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 394 } else if (isPLEX) { 395 ierr = private_DMSwarmInsertPointsUsingCellDM_PLEX(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 396 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 397 398 PetscFunctionReturn(0); 399 } 400 401 402 extern PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM,DM,PetscInt,PetscReal*); 403 404 /*@C 405 DMSwarmSetPointCoordinatesCellwise - Insert point coordinates (defined over the reference cell) within each cell 406 407 Not collective 408 409 Input parameters: 410 + dm - the DMSwarm 411 . celldm - the cell DM 412 . npoints - the number of points to insert in each cell 413 - xi - the coordinates (defined in the local coordinate system for each cell) to insert 414 415 Level: beginner 416 417 Notes: 418 The method will reset any previous defined points within the DMSwarm. 419 Only supported for DMPLEX. If you are using a DMDA it is recommended to either use 420 DMSwarmInsertPointsUsingCellDM(), or extract and set the coordinates yourself using 421 PetscReal *coor; 422 DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 423 // user code to define the coordinates here 424 DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 425 426 .seealso: DMSwarmSetCellDM(), DMSwarmInsertPointsUsingCellDM() 427 @*/ 428 PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinatesCellwise(DM dm,PetscInt npoints,PetscReal xi[]) 429 { 430 PetscErrorCode ierr; 431 DM celldm; 432 PetscBool isDA,isPLEX; 433 434 PetscFunctionBegin; 435 DMSWARMPICVALID(dm); 436 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 437 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 438 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 439 if (isDA) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMPLEX. Recommended you use DMSwarmInsertPointsUsingCellDM()"); 440 else if (isPLEX) { 441 ierr = private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm,celldm,npoints,xi);CHKERRQ(ierr); 442 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 443 444 PetscFunctionReturn(0); 445 } 446 447 448 /* Field projection API */ 449 extern PetscErrorCode private_DMSwarmProjectFields_DA(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]); 450 extern PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]); 451 452 /*@C 453 DMSwarmProjectFields - Project a set of swarm fields onto the cell DM 454 455 Collective on Vec 456 457 Input parameters: 458 + dm - the DMSwarm 459 . nfields - the number of swarm fields to project 460 . fieldnames - the textual names of the swarm fields to project 461 . fields - an array of Vec's of length nfields 462 - reuse - flag indicating whether the array and contents of fields should be re-used or internally allocated 463 464 Currently, the only available projection method consists of 465 phi_i = \sum_{p=0}^{np} N_i(x_p) phi_p dJ / \sum_{p=0}^{np} N_i(x_p) dJ 466 where phi_p is the swarm field at point p, 467 N_i() is the cell DM basis function at vertex i, 468 dJ is the determinant of the cell Jacobian and 469 phi_i is the projected vertex value of the field phi. 470 471 Level: beginner 472 473 Notes: 474 - If reuse = PETSC_FALSE, this function will allocate the array of Vec's, and each individual Vec. 475 The user is responsible for destroying both the array and the individual Vec objects. 476 - Only swarm fields registered with data type = PETSC_REAL can be projected onto the cell DM. 477 - Only swarm fields of block size = 1 can currently be projected. 478 - The only projection methods currently only support the DA (2D) and PLEX (triangles 2D). 479 480 .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 481 @*/ 482 PETSC_EXTERN PetscErrorCode DMSwarmProjectFields(DM dm,PetscInt nfields,const char *fieldnames[],Vec **fields,PetscBool reuse) 483 { 484 DM_Swarm *swarm = (DM_Swarm*)dm->data; 485 DataField *gfield; 486 DM celldm; 487 PetscBool isDA,isPLEX; 488 Vec *vecs; 489 PetscInt f,nvecs; 490 PetscInt project_type = 0; 491 PetscErrorCode ierr; 492 493 PetscFunctionBegin; 494 DMSWARMPICVALID(dm); 495 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 496 ierr = PetscMalloc1(nfields,&gfield);CHKERRQ(ierr); 497 nvecs = 0; 498 for (f=0; f<nfields; f++) { 499 ierr = DataBucketGetDataFieldByName(swarm->db,fieldnames[f],&gfield[f]);CHKERRQ(ierr); 500 if (gfield[f]->petsc_type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields using a data type = PETSC_REAL"); 501 if (gfield[f]->bs != 1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields with block size = 1"); 502 nvecs += gfield[f]->bs; 503 } 504 if (!reuse) { 505 ierr = PetscMalloc1(nvecs,&vecs);CHKERRQ(ierr); 506 for (f=0; f<nvecs; f++) { 507 ierr = DMCreateGlobalVector(celldm,&vecs[f]);CHKERRQ(ierr); 508 ierr = PetscObjectSetName((PetscObject)vecs[f],gfield[f]->name);CHKERRQ(ierr); 509 } 510 } else { 511 vecs = *fields; 512 } 513 514 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 515 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 516 if (isDA) { 517 ierr = private_DMSwarmProjectFields_DA(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); 518 } else if (isPLEX) { 519 ierr = private_DMSwarmProjectFields_PLEX(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); 520 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 521 522 ierr = PetscFree(gfield);CHKERRQ(ierr); 523 if (!reuse) { 524 *fields = vecs; 525 } 526 527 PetscFunctionReturn(0); 528 } 529 530 /*@C 531 DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM 532 533 Not collective 534 535 Input parameter: 536 . dm - the DMSwarm 537 538 Output parameters: 539 + ncells - the number of cells in the cell DM (optional argument, pass NULL to ignore) 540 - count - array of length ncells containing the number of points per cell 541 542 Level: beginner 543 544 Notes: 545 The array count is allocated internally and must be free'd by the user. 546 547 .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 548 @*/ 549 PETSC_EXTERN PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm,PetscInt *ncells,PetscInt **count) 550 { 551 PetscErrorCode ierr; 552 PetscBool isvalid; 553 PetscInt nel; 554 PetscInt *sum; 555 556 PetscFunctionBegin; 557 ierr = DMSwarmSortGetIsValid(dm,&isvalid);CHKERRQ(ierr); 558 nel = 0; 559 if (isvalid) { 560 PetscInt e; 561 562 ierr = DMSwarmSortGetSizes(dm,&nel,NULL);CHKERRQ(ierr); 563 564 ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 565 for (e=0; e<nel; e++) { 566 ierr = DMSwarmSortGetNumberOfPointsPerCell(dm,e,&sum[e]);CHKERRQ(ierr); 567 } 568 } else { 569 DM celldm; 570 PetscBool isda,isplex,isshell; 571 PetscInt p,npoints; 572 PetscInt *swarm_cellid; 573 574 /* get the number of cells */ 575 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 576 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isda);CHKERRQ(ierr); 577 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isplex);CHKERRQ(ierr); 578 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMSHELL,&isshell);CHKERRQ(ierr); 579 if (isda) { 580 PetscInt _nel,_npe; 581 const PetscInt *_element; 582 583 ierr = DMDAGetElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 584 nel = _nel; 585 ierr = DMDARestoreElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 586 } else if (isplex) { 587 PetscInt ps,pe; 588 589 ierr = DMPlexGetHeightStratum(celldm,0,&ps,&pe);CHKERRQ(ierr); 590 nel = pe - ps; 591 } else if (isshell) { 592 PetscErrorCode (*method_DMShellGetNumberOfCells)(DM,PetscInt*); 593 594 ierr = PetscObjectQueryFunction((PetscObject)celldm,"DMGetNumberOfCells_C",&method_DMShellGetNumberOfCells);CHKERRQ(ierr); 595 if (method_DMShellGetNumberOfCells) { 596 ierr = method_DMShellGetNumberOfCells(celldm,&nel);CHKERRQ(ierr); 597 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot determine the number of cells for the DMSHELL object. User must provide a method via PetscObjectComposeFunction( (PetscObject)shelldm, \"DMGetNumberOfCells_C\", your_function_to_compute_number_of_cells );"); 598 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot determine the number of cells for a DM not of type DA, PLEX or SHELL"); 599 600 ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 601 ierr = PetscMemzero(sum,sizeof(PetscInt)*nel);CHKERRQ(ierr); 602 ierr = DMSwarmGetLocalSize(dm,&npoints);CHKERRQ(ierr); 603 ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 604 for (p=0; p<npoints; p++) { 605 if (swarm_cellid[p] != DMLOCATEPOINT_POINT_NOT_FOUND) { 606 sum[ swarm_cellid[p] ]++; 607 } 608 } 609 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 610 } 611 if (ncells) { *ncells = nel; } 612 *count = sum; 613 PetscFunctionReturn(0); 614 } 615