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 "../src/dm/impls/swarm/data_bucket.h" 7 8 /* 9 Error checking 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 PetscCheckFalse(_swarm->swarm_type != DMSWARM_PIC,PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Valid only for DMSwarm-PIC. You must call DMSwarmSetType(dm,DMSWARM_PIC)"); \ 15 else \ 16 PetscCheckFalse(!_swarm->dmcell,PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Valid only 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 _npoints[b] = npoints[b]; 82 } 83 84 /* determine number of points living in the bounding box */ 85 n_estimate = 0; 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(PETSC_COMM_SELF,&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 ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr); 147 n_found = 0; 148 for (p=0; p<n_estimate; p++) { 149 if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 150 n_found++; 151 } 152 } 153 154 /* adjust size */ 155 if (mode == ADD_VALUES) { 156 ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr); 157 n_new_est = n_curr + n_found; 158 ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 159 } 160 if (mode == INSERT_VALUES) { 161 n_curr = 0; 162 n_new_est = n_found; 163 ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 164 } 165 166 /* initialize new coords, cell owners, pid */ 167 ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr); 168 ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 169 ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 170 n_found = 0; 171 for (p=0; p<n_estimate; p++) { 172 if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 173 for (b=0; b<bs; b++) { 174 swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]); 175 } 176 swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 177 n_found++; 178 } 179 } 180 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 181 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 182 ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr); 183 184 ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr); 185 ierr = VecDestroy(&pos);CHKERRQ(ierr); 186 PetscFunctionReturn(0); 187 } 188 189 /*@C 190 DMSwarmSetPointCoordinates - Set point coordinates in a DMSwarm from a user defined list 191 192 Collective on dm 193 194 Input parameters: 195 + dm - the DMSwarm 196 . npoints - the number of points to insert 197 . coor - the coordinate values 198 . 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 199 - mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES) 200 201 Level: beginner 202 203 Notes: 204 If the user has specified redundant = PETSC_FALSE, the cell DM will attempt to locate the coordinates provided by coor[] within 205 its sub-domain. If they any values within coor[] are not located in the sub-domain, they will be ignored and will not get 206 added to the DMSwarm. 207 208 .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType, DMSwarmSetPointsUniformCoordinates() 209 @*/ 210 PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinates(DM dm,PetscInt npoints,PetscReal coor[],PetscBool redundant,InsertMode mode) 211 { 212 PetscErrorCode ierr; 213 PetscReal gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL}; 214 PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 215 PetscInt i,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found; 216 Vec coorlocal; 217 const PetscScalar *_coor; 218 DM celldm; 219 Vec pos; 220 PetscScalar *_pos; 221 PetscReal *swarm_coor; 222 PetscInt *swarm_cellid; 223 PetscSF sfcell = NULL; 224 const PetscSFNode *LA_sfcell; 225 PetscReal *my_coor; 226 PetscInt my_npoints; 227 PetscMPIInt rank; 228 MPI_Comm comm; 229 230 PetscFunctionBegin; 231 DMSWARMPICVALID(dm); 232 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 233 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 234 235 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 236 ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr); 237 ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr); 238 ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr); 239 N = N / bs; 240 ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 241 for (i=0; i<N; i++) { 242 for (b=0; b<bs; b++) { 243 gmin[b] = PetscMin(gmin[b],PetscRealPart(_coor[bs*i+b])); 244 gmax[b] = PetscMax(gmax[b],PetscRealPart(_coor[bs*i+b])); 245 } 246 } 247 ierr = VecRestoreArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 248 249 /* broadcast points from rank 0 if requested */ 250 if (redundant) { 251 my_npoints = npoints; 252 ierr = MPI_Bcast(&my_npoints,1,MPIU_INT,0,comm);CHKERRMPI(ierr); 253 254 if (rank > 0) { /* allocate space */ 255 ierr = PetscMalloc1(bs*my_npoints,&my_coor);CHKERRQ(ierr); 256 } else { 257 my_coor = coor; 258 } 259 ierr = MPI_Bcast(my_coor,bs*my_npoints,MPIU_REAL,0,comm);CHKERRMPI(ierr); 260 } else { 261 my_npoints = npoints; 262 my_coor = coor; 263 } 264 265 /* determine the number of points living in the bounding box */ 266 n_estimate = 0; 267 for (i=0; i<my_npoints; i++) { 268 PetscBool point_inside = PETSC_TRUE; 269 270 for (b=0; b<bs; b++) { 271 if (my_coor[bs*i+b] < gmin[b]) { point_inside = PETSC_FALSE; } 272 if (my_coor[bs*i+b] > gmax[b]) { point_inside = PETSC_FALSE; } 273 } 274 if (point_inside) { n_estimate++; } 275 } 276 277 /* create candidate list */ 278 ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr); 279 ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr); 280 ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr); 281 ierr = VecSetFromOptions(pos);CHKERRQ(ierr); 282 ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr); 283 284 n_estimate = 0; 285 for (i=0; i<my_npoints; i++) { 286 PetscBool point_inside = PETSC_TRUE; 287 288 for (b=0; b<bs; b++) { 289 if (my_coor[bs*i+b] < gmin[b]) { point_inside = PETSC_FALSE; } 290 if (my_coor[bs*i+b] > gmax[b]) { point_inside = PETSC_FALSE; } 291 } 292 if (point_inside) { 293 for (b=0; b<bs; b++) { 294 _pos[bs*n_estimate+b] = my_coor[bs*i+b]; 295 } 296 n_estimate++; 297 } 298 } 299 ierr = VecRestoreArray(pos,&_pos);CHKERRQ(ierr); 300 301 /* locate points */ 302 ierr = DMLocatePoints(celldm,pos,DM_POINTLOCATION_NONE,&sfcell);CHKERRQ(ierr); 303 304 ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr); 305 n_found = 0; 306 for (p=0; p<n_estimate; p++) { 307 if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 308 n_found++; 309 } 310 } 311 312 /* adjust size */ 313 if (mode == ADD_VALUES) { 314 ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr); 315 n_new_est = n_curr + n_found; 316 ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 317 } 318 if (mode == INSERT_VALUES) { 319 n_curr = 0; 320 n_new_est = n_found; 321 ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 322 } 323 324 /* initialize new coords, cell owners, pid */ 325 ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr); 326 ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 327 ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 328 n_found = 0; 329 for (p=0; p<n_estimate; p++) { 330 if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 331 for (b=0; b<bs; b++) { 332 swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]); 333 } 334 swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 335 n_found++; 336 } 337 } 338 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 339 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 340 ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr); 341 342 if (redundant) { 343 if (rank > 0) { 344 ierr = PetscFree(my_coor);CHKERRQ(ierr); 345 } 346 } 347 ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr); 348 ierr = VecDestroy(&pos);CHKERRQ(ierr); 349 PetscFunctionReturn(0); 350 } 351 352 extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM,DM,DMSwarmPICLayoutType,PetscInt); 353 extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM,DM,DMSwarmPICLayoutType,PetscInt); 354 355 /*@C 356 DMSwarmInsertPointsUsingCellDM - Insert point coordinates within each cell 357 358 Not collective 359 360 Input parameters: 361 + dm - the DMSwarm 362 . layout_type - method used to fill each cell with the cell DM 363 - fill_param - parameter controlling how many points per cell are added (the meaning of this parameter is dependent on the layout type) 364 365 Level: beginner 366 367 Notes: 368 369 The insert method will reset any previous defined points within the DMSwarm. 370 371 When using a DMDA both 2D and 3D are supported for all layout types provided you are using DMDA_ELEMENT_Q1. 372 373 When using a DMPLEX the following case are supported: 374 (i) DMSWARMPIC_LAYOUT_REGULAR: 2D (triangle), 375 (ii) DMSWARMPIC_LAYOUT_GAUSS: 2D and 3D provided the cell is a tri/tet or a quad/hex, 376 (iii) DMSWARMPIC_LAYOUT_SUBDIVISION: 2D and 3D for quad/hex and 2D tri. 377 378 .seealso: DMSwarmPICLayoutType, DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 379 @*/ 380 PETSC_EXTERN PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm,DMSwarmPICLayoutType layout_type,PetscInt fill_param) 381 { 382 PetscErrorCode ierr; 383 DM celldm; 384 PetscBool isDA,isPLEX; 385 386 PetscFunctionBegin; 387 DMSWARMPICVALID(dm); 388 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 389 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 390 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 391 if (isDA) { 392 ierr = private_DMSwarmInsertPointsUsingCellDM_DA(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 393 } else if (isPLEX) { 394 ierr = private_DMSwarmInsertPointsUsingCellDM_PLEX(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 395 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 396 PetscFunctionReturn(0); 397 } 398 399 extern PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM,DM,PetscInt,PetscReal*); 400 401 /*@C 402 DMSwarmSetPointCoordinatesCellwise - Insert point coordinates (defined over the reference cell) within each cell 403 404 Not collective 405 406 Input parameters: 407 + dm - the DMSwarm 408 . celldm - the cell DM 409 . npoints - the number of points to insert in each cell 410 - xi - the coordinates (defined in the local coordinate system for each cell) to insert 411 412 Level: beginner 413 414 Notes: 415 The method will reset any previous defined points within the DMSwarm. 416 Only supported for DMPLEX. If you are using a DMDA it is recommended to either use 417 DMSwarmInsertPointsUsingCellDM(), or extract and set the coordinates yourself the following code 418 419 $ PetscReal *coor; 420 $ DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 421 $ // user code to define the coordinates here 422 $ DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 423 424 .seealso: DMSwarmSetCellDM(), DMSwarmInsertPointsUsingCellDM() 425 @*/ 426 PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinatesCellwise(DM dm,PetscInt npoints,PetscReal xi[]) 427 { 428 PetscErrorCode ierr; 429 DM celldm; 430 PetscBool isDA,isPLEX; 431 432 PetscFunctionBegin; 433 DMSWARMPICVALID(dm); 434 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 435 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 436 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 437 PetscCheckFalse(isDA,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMPLEX. Recommended you use DMSwarmInsertPointsUsingCellDM()"); 438 else if (isPLEX) { 439 ierr = private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm,celldm,npoints,xi);CHKERRQ(ierr); 440 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 441 PetscFunctionReturn(0); 442 } 443 444 /* Field projection API */ 445 extern PetscErrorCode private_DMSwarmProjectFields_DA(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DMSwarmDataField dfield[],Vec vecs[]); 446 extern PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DMSwarmDataField dfield[],Vec vecs[]); 447 448 /*@C 449 DMSwarmProjectFields - Project a set of swarm fields onto the cell DM 450 451 Collective on dm 452 453 Input parameters: 454 + dm - the DMSwarm 455 . nfields - the number of swarm fields to project 456 . fieldnames - the textual names of the swarm fields to project 457 . fields - an array of Vec's of length nfields 458 - reuse - flag indicating whether the array and contents of fields should be re-used or internally allocated 459 460 Currently, the only available projection method consists of 461 phi_i = \sum_{p=0}^{np} N_i(x_p) phi_p dJ / \sum_{p=0}^{np} N_i(x_p) dJ 462 where phi_p is the swarm field at point p, 463 N_i() is the cell DM basis function at vertex i, 464 dJ is the determinant of the cell Jacobian and 465 phi_i is the projected vertex value of the field phi. 466 467 Level: beginner 468 469 Notes: 470 471 If reuse = PETSC_FALSE, this function will allocate the array of Vec's, and each individual Vec. 472 The user is responsible for destroying both the array and the individual Vec objects. 473 474 Only swarm fields registered with data type = PETSC_REAL can be projected onto the cell DM. 475 476 Only swarm fields of block size = 1 can currently be projected. 477 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 DMSwarmDataField *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 = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldnames[f],&gfield[f]);CHKERRQ(ierr); 500 PetscCheckFalse(gfield[f]->petsc_type != PETSC_REAL,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields using a data type = PETSC_REAL"); 501 PetscCheckFalse(gfield[f]->bs != 1,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 PetscFunctionReturn(0); 527 } 528 529 /*@C 530 DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM 531 532 Not collective 533 534 Input parameter: 535 . dm - the DMSwarm 536 537 Output parameters: 538 + ncells - the number of cells in the cell DM (optional argument, pass NULL to ignore) 539 - count - array of length ncells containing the number of points per cell 540 541 Level: beginner 542 543 Notes: 544 The array count is allocated internally and must be free'd by the user. 545 546 .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 547 @*/ 548 PETSC_EXTERN PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm,PetscInt *ncells,PetscInt **count) 549 { 550 PetscErrorCode ierr; 551 PetscBool isvalid; 552 PetscInt nel; 553 PetscInt *sum; 554 555 PetscFunctionBegin; 556 ierr = DMSwarmSortGetIsValid(dm,&isvalid);CHKERRQ(ierr); 557 nel = 0; 558 if (isvalid) { 559 PetscInt e; 560 561 ierr = DMSwarmSortGetSizes(dm,&nel,NULL);CHKERRQ(ierr); 562 563 ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 564 for (e=0; e<nel; e++) { 565 ierr = DMSwarmSortGetNumberOfPointsPerCell(dm,e,&sum[e]);CHKERRQ(ierr); 566 } 567 } else { 568 DM celldm; 569 PetscBool isda,isplex,isshell; 570 PetscInt p,npoints; 571 PetscInt *swarm_cellid; 572 573 /* get the number of cells */ 574 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 575 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isda);CHKERRQ(ierr); 576 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isplex);CHKERRQ(ierr); 577 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMSHELL,&isshell);CHKERRQ(ierr); 578 if (isda) { 579 PetscInt _nel,_npe; 580 const PetscInt *_element; 581 582 ierr = DMDAGetElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 583 nel = _nel; 584 ierr = DMDARestoreElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 585 } else if (isplex) { 586 PetscInt ps,pe; 587 588 ierr = DMPlexGetHeightStratum(celldm,0,&ps,&pe);CHKERRQ(ierr); 589 nel = pe - ps; 590 } else if (isshell) { 591 PetscErrorCode (*method_DMShellGetNumberOfCells)(DM,PetscInt*); 592 593 ierr = PetscObjectQueryFunction((PetscObject)celldm,"DMGetNumberOfCells_C",&method_DMShellGetNumberOfCells);CHKERRQ(ierr); 594 if (method_DMShellGetNumberOfCells) { 595 ierr = method_DMShellGetNumberOfCells(celldm,&nel);CHKERRQ(ierr); 596 } 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);"); 597 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot determine the number of cells for a DM not of type DA, PLEX or SHELL"); 598 599 ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 600 ierr = PetscArrayzero(sum,nel);CHKERRQ(ierr); 601 ierr = DMSwarmGetLocalSize(dm,&npoints);CHKERRQ(ierr); 602 ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 603 for (p=0; p<npoints; p++) { 604 if (swarm_cellid[p] != DMLOCATEPOINT_POINT_NOT_FOUND) { 605 sum[ swarm_cellid[p] ]++; 606 } 607 } 608 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 609 } 610 if (ncells) { *ncells = nel; } 611 *count = sum; 612 PetscFunctionReturn(0); 613 } 614