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 373 The insert method will reset any previous defined points within the DMSwarm. 374 375 When using a DMDA both 2D and 3D are supported for all layout types provided you are using DMDA_ELEMENT_Q1. 376 377 When using a DMPLEX the following case are supported: 378 (i ) DMSWARMPIC_LAYOUT_REGULAR: 2D (triangle), 379 (ii ) DMSWARMPIC_LAYOUT_GAUSS: 2D and 3D provided the cell is a tri/tet or a quad/hex, 380 (iii) DMSWARMPIC_LAYOUT_SUBDIVISION: 2D and 3D for quad/hex and 2D tri. 381 382 .seealso: DMSwarmPICLayoutType, DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 383 @*/ 384 PETSC_EXTERN PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm,DMSwarmPICLayoutType layout_type,PetscInt fill_param) 385 { 386 PetscErrorCode ierr; 387 DM celldm; 388 PetscBool isDA,isPLEX; 389 390 PetscFunctionBegin; 391 DMSWARMPICVALID(dm); 392 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 393 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 394 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 395 if (isDA) { 396 ierr = private_DMSwarmInsertPointsUsingCellDM_DA(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 397 } else if (isPLEX) { 398 ierr = private_DMSwarmInsertPointsUsingCellDM_PLEX(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 399 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 400 401 PetscFunctionReturn(0); 402 } 403 404 405 extern PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM,DM,PetscInt,PetscReal*); 406 407 /*@C 408 DMSwarmSetPointCoordinatesCellwise - Insert point coordinates (defined over the reference cell) within each cell 409 410 Not collective 411 412 Input parameters: 413 + dm - the DMSwarm 414 . celldm - the cell DM 415 . npoints - the number of points to insert in each cell 416 - xi - the coordinates (defined in the local coordinate system for each cell) to insert 417 418 Level: beginner 419 420 Notes: 421 The method will reset any previous defined points within the DMSwarm. 422 Only supported for DMPLEX. If you are using a DMDA it is recommended to either use 423 DMSwarmInsertPointsUsingCellDM(), or extract and set the coordinates yourself the following code 424 425 $ PetscReal *coor; 426 $ DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 427 $ // user code to define the coordinates here 428 $ DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 429 430 .seealso: DMSwarmSetCellDM(), DMSwarmInsertPointsUsingCellDM() 431 @*/ 432 PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinatesCellwise(DM dm,PetscInt npoints,PetscReal xi[]) 433 { 434 PetscErrorCode ierr; 435 DM celldm; 436 PetscBool isDA,isPLEX; 437 438 PetscFunctionBegin; 439 DMSWARMPICVALID(dm); 440 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 441 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 442 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 443 if (isDA) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMPLEX. Recommended you use DMSwarmInsertPointsUsingCellDM()"); 444 else if (isPLEX) { 445 ierr = private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm,celldm,npoints,xi);CHKERRQ(ierr); 446 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 447 448 PetscFunctionReturn(0); 449 } 450 451 452 /* Field projection API */ 453 extern PetscErrorCode private_DMSwarmProjectFields_DA(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]); 454 extern PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]); 455 456 /*@C 457 DMSwarmProjectFields - Project a set of swarm fields onto the cell DM 458 459 Collective on Vec 460 461 Input parameters: 462 + dm - the DMSwarm 463 . nfields - the number of swarm fields to project 464 . fieldnames - the textual names of the swarm fields to project 465 . fields - an array of Vec's of length nfields 466 - reuse - flag indicating whether the array and contents of fields should be re-used or internally allocated 467 468 Currently, the only available projection method consists of 469 phi_i = \sum_{p=0}^{np} N_i(x_p) phi_p dJ / \sum_{p=0}^{np} N_i(x_p) dJ 470 where phi_p is the swarm field at point p, 471 N_i() is the cell DM basis function at vertex i, 472 dJ is the determinant of the cell Jacobian and 473 phi_i is the projected vertex value of the field phi. 474 475 Level: beginner 476 477 Notes: 478 479 If reuse = PETSC_FALSE, this function will allocate the array of Vec's, and each individual Vec. 480 The user is responsible for destroying both the array and the individual Vec objects. 481 482 Only swarm fields registered with data type = PETSC_REAL can be projected onto the cell DM. 483 484 Only swarm fields of block size = 1 can currently be projected. 485 486 The only projection methods currently only support the DA (2D) and PLEX (triangles 2D). 487 488 .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 489 @*/ 490 PETSC_EXTERN PetscErrorCode DMSwarmProjectFields(DM dm,PetscInt nfields,const char *fieldnames[],Vec **fields,PetscBool reuse) 491 { 492 DM_Swarm *swarm = (DM_Swarm*)dm->data; 493 DataField *gfield; 494 DM celldm; 495 PetscBool isDA,isPLEX; 496 Vec *vecs; 497 PetscInt f,nvecs; 498 PetscInt project_type = 0; 499 PetscErrorCode ierr; 500 501 PetscFunctionBegin; 502 DMSWARMPICVALID(dm); 503 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 504 ierr = PetscMalloc1(nfields,&gfield);CHKERRQ(ierr); 505 nvecs = 0; 506 for (f=0; f<nfields; f++) { 507 ierr = DataBucketGetDataFieldByName(swarm->db,fieldnames[f],&gfield[f]);CHKERRQ(ierr); 508 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"); 509 if (gfield[f]->bs != 1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields with block size = 1"); 510 nvecs += gfield[f]->bs; 511 } 512 if (!reuse) { 513 ierr = PetscMalloc1(nvecs,&vecs);CHKERRQ(ierr); 514 for (f=0; f<nvecs; f++) { 515 ierr = DMCreateGlobalVector(celldm,&vecs[f]);CHKERRQ(ierr); 516 ierr = PetscObjectSetName((PetscObject)vecs[f],gfield[f]->name);CHKERRQ(ierr); 517 } 518 } else { 519 vecs = *fields; 520 } 521 522 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 523 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 524 if (isDA) { 525 ierr = private_DMSwarmProjectFields_DA(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); 526 } else if (isPLEX) { 527 ierr = private_DMSwarmProjectFields_PLEX(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); 528 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 529 530 ierr = PetscFree(gfield);CHKERRQ(ierr); 531 if (!reuse) { 532 *fields = vecs; 533 } 534 535 PetscFunctionReturn(0); 536 } 537 538 /*@C 539 DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM 540 541 Not collective 542 543 Input parameter: 544 . dm - the DMSwarm 545 546 Output parameters: 547 + ncells - the number of cells in the cell DM (optional argument, pass NULL to ignore) 548 - count - array of length ncells containing the number of points per cell 549 550 Level: beginner 551 552 Notes: 553 The array count is allocated internally and must be free'd by the user. 554 555 .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 556 @*/ 557 PETSC_EXTERN PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm,PetscInt *ncells,PetscInt **count) 558 { 559 PetscErrorCode ierr; 560 PetscBool isvalid; 561 PetscInt nel; 562 PetscInt *sum; 563 564 PetscFunctionBegin; 565 ierr = DMSwarmSortGetIsValid(dm,&isvalid);CHKERRQ(ierr); 566 nel = 0; 567 if (isvalid) { 568 PetscInt e; 569 570 ierr = DMSwarmSortGetSizes(dm,&nel,NULL);CHKERRQ(ierr); 571 572 ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 573 for (e=0; e<nel; e++) { 574 ierr = DMSwarmSortGetNumberOfPointsPerCell(dm,e,&sum[e]);CHKERRQ(ierr); 575 } 576 } else { 577 DM celldm; 578 PetscBool isda,isplex,isshell; 579 PetscInt p,npoints; 580 PetscInt *swarm_cellid; 581 582 /* get the number of cells */ 583 ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 584 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isda);CHKERRQ(ierr); 585 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isplex);CHKERRQ(ierr); 586 ierr = PetscObjectTypeCompare((PetscObject)celldm,DMSHELL,&isshell);CHKERRQ(ierr); 587 if (isda) { 588 PetscInt _nel,_npe; 589 const PetscInt *_element; 590 591 ierr = DMDAGetElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 592 nel = _nel; 593 ierr = DMDARestoreElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 594 } else if (isplex) { 595 PetscInt ps,pe; 596 597 ierr = DMPlexGetHeightStratum(celldm,0,&ps,&pe);CHKERRQ(ierr); 598 nel = pe - ps; 599 } else if (isshell) { 600 PetscErrorCode (*method_DMShellGetNumberOfCells)(DM,PetscInt*); 601 602 ierr = PetscObjectQueryFunction((PetscObject)celldm,"DMGetNumberOfCells_C",&method_DMShellGetNumberOfCells);CHKERRQ(ierr); 603 if (method_DMShellGetNumberOfCells) { 604 ierr = method_DMShellGetNumberOfCells(celldm,&nel);CHKERRQ(ierr); 605 } 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 );"); 606 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot determine the number of cells for a DM not of type DA, PLEX or SHELL"); 607 608 ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 609 ierr = PetscMemzero(sum,sizeof(PetscInt)*nel);CHKERRQ(ierr); 610 ierr = DMSwarmGetLocalSize(dm,&npoints);CHKERRQ(ierr); 611 ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 612 for (p=0; p<npoints; p++) { 613 if (swarm_cellid[p] != DMLOCATEPOINT_POINT_NOT_FOUND) { 614 sum[ swarm_cellid[p] ]++; 615 } 616 } 617 ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 618 } 619 if (ncells) { *ncells = nel; } 620 *count = sum; 621 PetscFunctionReturn(0); 622 } 623