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