1 2 #define PETSCDM_DLL 3 #include <petsc/private/dmswarmimpl.h> /*I "petscdmswarm.h" I*/ 4 #include "data_bucket.h" 5 6 PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort; 7 PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd; 8 PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack; 9 10 const char* DMSwarmTypeNames[] = { "basic", "pic", 0 }; 11 const char* DMSwarmMigrateTypeNames[] = { "basic", "dmcellnscatter", "dmcellexact", "user", 0 }; 12 const char* DMSwarmCollectTypeNames[] = { "basic", "boundingbox", "general", "user", 0 }; 13 const char* DMSwarmPICLayoutTypeNames[] = { "regular", "gauss", "subdivision", 0 }; 14 15 const char DMSwarmField_pid[] = "DMSwarm_pid"; 16 const char DMSwarmField_rank[] = "DMSwarm_rank"; 17 const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor"; 18 const char DMSwarmPICField_cellid[] = "DMSwarm_cellid"; 19 20 /*@C 21 DMSwarmVectorDefineField - Sets the field from which to define a Vec object 22 when DMCreateLocalVector(), or DMCreateGlobalVector() is called 23 24 Collective on DM 25 26 Input parameters: 27 + dm - a DMSwarm 28 - fieldname - the textual name given to a registered field 29 30 Level: beginner 31 32 Notes: 33 The field with name fieldname must be defined as having a data type of PetscScalar. 34 This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector(). 35 Mutiple calls to DMSwarmVectorDefineField() are permitted. 36 37 .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector() 38 @*/ 39 PETSC_EXTERN PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[]) 40 { 41 DM_Swarm *swarm = (DM_Swarm*)dm->data; 42 PetscErrorCode ierr; 43 PetscInt bs,n; 44 PetscScalar *array; 45 PetscDataType type; 46 47 PetscFunctionBegin; 48 if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); } 49 ierr = DataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr); 50 ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr); 51 52 /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */ 53 if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL"); 54 ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr); 55 swarm->vec_field_set = PETSC_TRUE; 56 swarm->vec_field_bs = bs; 57 swarm->vec_field_nlocal = n; 58 ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr); 59 PetscFunctionReturn(0); 60 } 61 62 /* requires DMSwarmDefineFieldVector has been called */ 63 PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec) 64 { 65 DM_Swarm *swarm = (DM_Swarm*)dm->data; 66 PetscErrorCode ierr; 67 Vec x; 68 char name[PETSC_MAX_PATH_LEN]; 69 70 PetscFunctionBegin; 71 if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); } 72 if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first"); 73 if (swarm->vec_field_nlocal != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since last call to VectorDefineField first"); /* Stale data */ 74 75 ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr); 76 ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr); 77 ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr); 78 ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr); 79 ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr); 80 ierr = VecSetFromOptions(x);CHKERRQ(ierr); 81 *vec = x; 82 PetscFunctionReturn(0); 83 } 84 85 /* requires DMSwarmDefineFieldVector has been called */ 86 PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec) 87 { 88 DM_Swarm *swarm = (DM_Swarm*)dm->data; 89 PetscErrorCode ierr; 90 Vec x; 91 char name[PETSC_MAX_PATH_LEN]; 92 93 PetscFunctionBegin; 94 if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); } 95 if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first"); 96 if (swarm->vec_field_nlocal != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since last call to VectorDefineField first"); /* Stale data */ 97 98 ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr); 99 ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr); 100 ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr); 101 ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr); 102 ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr); 103 ierr = VecSetFromOptions(x);CHKERRQ(ierr); 104 *vec = x; 105 PetscFunctionReturn(0); 106 } 107 108 static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec) 109 { 110 DM_Swarm *swarm = (DM_Swarm *) dm->data; 111 DataField gfield; 112 void (*fptr)(void); 113 PetscInt bs, nlocal; 114 char name[PETSC_MAX_PATH_LEN]; 115 PetscErrorCode ierr; 116 117 PetscFunctionBegin; 118 ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr); 119 ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr); 120 if (nlocal/bs != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since vector was created - cannot ensure pointers are valid"); /* Stale data */ 121 ierr = DataBucketGetDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr); 122 /* check vector is an inplace array */ 123 ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr); 124 ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr); 125 if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname); 126 ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr); 127 ierr = VecDestroy(vec);CHKERRQ(ierr); 128 PetscFunctionReturn(0); 129 } 130 131 static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec) 132 { 133 DM_Swarm *swarm = (DM_Swarm *) dm->data; 134 PetscDataType type; 135 PetscScalar *array; 136 PetscInt bs, n; 137 char name[PETSC_MAX_PATH_LEN]; 138 PetscMPIInt commsize; 139 PetscErrorCode ierr; 140 141 PetscFunctionBegin; 142 if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);} 143 ierr = DataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr); 144 ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr); 145 if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL"); 146 147 ierr = MPI_Comm_size(comm, &commsize);CHKERRQ(ierr); 148 if (commsize == 1) { 149 ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr); 150 } else { 151 ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr); 152 } 153 ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr); 154 ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr); 155 156 /* Set guard */ 157 ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr); 158 ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr); 159 PetscFunctionReturn(0); 160 } 161 162 /*@C 163 DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field 164 165 Collective on DM 166 167 Input parameters: 168 + dm - a DMSwarm 169 - fieldname - the textual name given to a registered field 170 171 Output parameter: 172 . vec - the vector 173 174 Level: beginner 175 176 Notes: 177 The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField(). 178 179 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField() 180 @*/ 181 PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec) 182 { 183 MPI_Comm comm = PetscObjectComm((PetscObject) dm); 184 PetscErrorCode ierr; 185 186 PetscFunctionBegin; 187 ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr); 188 PetscFunctionReturn(0); 189 } 190 191 /*@C 192 DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field 193 194 Collective on DM 195 196 Input parameters: 197 + dm - a DMSwarm 198 - fieldname - the textual name given to a registered field 199 200 Output parameter: 201 . vec - the vector 202 203 Level: beginner 204 205 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField() 206 @*/ 207 PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec) 208 { 209 PetscErrorCode ierr; 210 211 PetscFunctionBegin; 212 ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr); 213 PetscFunctionReturn(0); 214 } 215 216 /*@C 217 DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field 218 219 Collective on DM 220 221 Input parameters: 222 + dm - a DMSwarm 223 - fieldname - the textual name given to a registered field 224 225 Output parameter: 226 . vec - the vector 227 228 Level: beginner 229 230 Notes: 231 The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField(). 232 233 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField() 234 @*/ 235 PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec) 236 { 237 MPI_Comm comm = PETSC_COMM_SELF; 238 PetscErrorCode ierr; 239 240 PetscFunctionBegin; 241 ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr); 242 PetscFunctionReturn(0); 243 } 244 245 /*@C 246 DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field 247 248 Collective on DM 249 250 Input parameters: 251 + dm - a DMSwarm 252 - fieldname - the textual name given to a registered field 253 254 Output parameter: 255 . vec - the vector 256 257 Level: beginner 258 259 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField() 260 @*/ 261 PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec) 262 { 263 PetscErrorCode ierr; 264 265 PetscFunctionBegin; 266 ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr); 267 PetscFunctionReturn(0); 268 } 269 270 /* 271 PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec) 272 { 273 PetscFunctionReturn(0); 274 } 275 276 PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec) 277 { 278 PetscFunctionReturn(0); 279 } 280 */ 281 282 /*@C 283 DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm 284 285 Collective on DM 286 287 Input parameter: 288 . dm - a DMSwarm 289 290 Level: beginner 291 292 Notes: 293 After all fields have been registered, you must call DMSwarmFinalizeFieldRegister(). 294 295 .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(), 296 DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField() 297 @*/ 298 PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm) 299 { 300 DM_Swarm *swarm = (DM_Swarm *) dm->data; 301 PetscErrorCode ierr; 302 303 PetscFunctionBegin; 304 if (!swarm->field_registration_initialized) { 305 swarm->field_registration_initialized = PETSC_TRUE; 306 ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */ 307 ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */ 308 } 309 PetscFunctionReturn(0); 310 } 311 312 /*@C 313 DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm 314 315 Collective on DM 316 317 Input parameter: 318 . dm - a DMSwarm 319 320 Level: beginner 321 322 Notes: 323 After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm. 324 325 .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(), 326 DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField() 327 @*/ 328 PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm) 329 { 330 DM_Swarm *swarm = (DM_Swarm*)dm->data; 331 PetscErrorCode ierr; 332 333 PetscFunctionBegin; 334 if (!swarm->field_registration_finalized) { 335 ierr = DataBucketFinalize(swarm->db);CHKERRQ(ierr); 336 } 337 swarm->field_registration_finalized = PETSC_TRUE; 338 PetscFunctionReturn(0); 339 } 340 341 /*@C 342 DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm 343 344 Not collective 345 346 Input parameters: 347 + dm - a DMSwarm 348 . nlocal - the length of each registered field 349 - buffer - the length of the buffer used to efficient dynamic re-sizing 350 351 Level: beginner 352 353 .seealso: DMSwarmGetLocalSize() 354 @*/ 355 PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer) 356 { 357 DM_Swarm *swarm = (DM_Swarm*)dm->data; 358 PetscErrorCode ierr; 359 360 PetscFunctionBegin; 361 ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr); 362 ierr = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr); 363 ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr); 364 PetscFunctionReturn(0); 365 } 366 367 /*@C 368 DMSwarmSetCellDM - Attachs a DM to a DMSwarm 369 370 Collective on DM 371 372 Input parameters: 373 + dm - a DMSwarm 374 - dmcell - the DM to attach to the DMSwarm 375 376 Level: beginner 377 378 Notes: 379 The attached DM (dmcell) will be queried for point location and 380 neighbor MPI-rank information if DMSwarmMigrate() is called. 381 382 .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate() 383 @*/ 384 PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell) 385 { 386 DM_Swarm *swarm = (DM_Swarm*)dm->data; 387 388 PetscFunctionBegin; 389 swarm->dmcell = dmcell; 390 PetscFunctionReturn(0); 391 } 392 393 /*@C 394 DMSwarmGetCellDM - Fetches the attached cell DM 395 396 Collective on DM 397 398 Input parameter: 399 . dm - a DMSwarm 400 401 Output parameter: 402 . dmcell - the DM which was attached to the DMSwarm 403 404 Level: beginner 405 406 .seealso: DMSwarmSetCellDM() 407 @*/ 408 PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell) 409 { 410 DM_Swarm *swarm = (DM_Swarm*)dm->data; 411 412 PetscFunctionBegin; 413 *dmcell = swarm->dmcell; 414 PetscFunctionReturn(0); 415 } 416 417 /*@C 418 DMSwarmGetLocalSize - Retrives the local length of fields registered 419 420 Not collective 421 422 Input parameter: 423 . dm - a DMSwarm 424 425 Output parameter: 426 . nlocal - the length of each registered field 427 428 Level: beginner 429 430 .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes() 431 @*/ 432 PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal) 433 { 434 DM_Swarm *swarm = (DM_Swarm*)dm->data; 435 PetscErrorCode ierr; 436 437 PetscFunctionBegin; 438 if (nlocal) {ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);} 439 PetscFunctionReturn(0); 440 } 441 442 /*@C 443 DMSwarmGetSize - Retrives the total length of fields registered 444 445 Collective on DM 446 447 Input parameter: 448 . dm - a DMSwarm 449 450 Output parameter: 451 . n - the total length of each registered field 452 453 Level: beginner 454 455 Note: 456 This calls MPI_Allreduce upon each call (inefficient but safe) 457 458 .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes() 459 @*/ 460 PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n) 461 { 462 DM_Swarm *swarm = (DM_Swarm*)dm->data; 463 PetscErrorCode ierr; 464 PetscInt nlocal,ng; 465 466 PetscFunctionBegin; 467 ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr); 468 ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 469 if (n) { *n = ng; } 470 PetscFunctionReturn(0); 471 } 472 473 /*@C 474 DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type 475 476 Collective on DM 477 478 Input parameters: 479 + dm - a DMSwarm 480 . fieldname - the textual name to identify this field 481 . blocksize - the number of each data type 482 - type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG) 483 484 Level: beginner 485 486 Notes: 487 The textual name for each registered field must be unique. 488 489 .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField() 490 @*/ 491 PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type) 492 { 493 PetscErrorCode ierr; 494 DM_Swarm *swarm = (DM_Swarm*)dm->data; 495 size_t size; 496 497 PetscFunctionBegin; 498 if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first"); 499 if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first"); 500 501 if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 502 if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 503 if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 504 if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 505 if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 506 507 ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr); 508 /* Load a specific data type into data bucket, specifying textual name and its size in bytes */ 509 ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr); 510 { 511 DataField gfield; 512 513 ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr); 514 ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr); 515 } 516 swarm->db->field[swarm->db->nfields-1]->petsc_type = type; 517 PetscFunctionReturn(0); 518 } 519 520 /*@C 521 DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm 522 523 Collective on DM 524 525 Input parameters: 526 + dm - a DMSwarm 527 . fieldname - the textual name to identify this field 528 - size - the size in bytes of the user struct of each data type 529 530 Level: beginner 531 532 Notes: 533 The textual name for each registered field must be unique. 534 535 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField() 536 @*/ 537 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size) 538 { 539 PetscErrorCode ierr; 540 DM_Swarm *swarm = (DM_Swarm*)dm->data; 541 542 PetscFunctionBegin; 543 ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr); 544 swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ; 545 PetscFunctionReturn(0); 546 } 547 548 /*@C 549 DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm 550 551 Collective on DM 552 553 Input parameters: 554 + dm - a DMSwarm 555 . fieldname - the textual name to identify this field 556 . size - the size in bytes of the user data type 557 - blocksize - the number of each data type 558 559 Level: beginner 560 561 Notes: 562 The textual name for each registered field must be unique. 563 564 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField() 565 @*/ 566 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize) 567 { 568 DM_Swarm *swarm = (DM_Swarm*)dm->data; 569 PetscErrorCode ierr; 570 571 PetscFunctionBegin; 572 ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr); 573 { 574 DataField gfield; 575 576 ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr); 577 ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr); 578 } 579 swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN; 580 PetscFunctionReturn(0); 581 } 582 583 /*@C 584 DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field 585 586 Not collective 587 588 Input parameters: 589 + dm - a DMSwarm 590 - fieldname - the textual name to identify this field 591 592 Output parameters: 593 + blocksize - the number of each data type 594 . type - the data type 595 - data - pointer to raw array 596 597 Level: beginner 598 599 Notes: 600 The array must be returned using a matching call to DMSwarmRestoreField(). 601 602 .seealso: DMSwarmRestoreField() 603 @*/ 604 PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data) 605 { 606 DM_Swarm *swarm = (DM_Swarm*)dm->data; 607 DataField gfield; 608 PetscErrorCode ierr; 609 610 PetscFunctionBegin; 611 if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); } 612 ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr); 613 ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr); 614 ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr); 615 if (blocksize) {*blocksize = gfield->bs; } 616 if (type) { *type = gfield->petsc_type; } 617 PetscFunctionReturn(0); 618 } 619 620 /*@C 621 DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field 622 623 Not collective 624 625 Input parameters: 626 + dm - a DMSwarm 627 - fieldname - the textual name to identify this field 628 629 Output parameters: 630 + blocksize - the number of each data type 631 . type - the data type 632 - data - pointer to raw array 633 634 Level: beginner 635 636 Notes: 637 The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField(). 638 639 .seealso: DMSwarmGetField() 640 @*/ 641 PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data) 642 { 643 DM_Swarm *swarm = (DM_Swarm*)dm->data; 644 DataField gfield; 645 PetscErrorCode ierr; 646 647 PetscFunctionBegin; 648 ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr); 649 ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr); 650 if (data) *data = NULL; 651 PetscFunctionReturn(0); 652 } 653 654 /*@C 655 DMSwarmAddPoint - Add space for one new point in the DMSwarm 656 657 Not collective 658 659 Input parameter: 660 . dm - a DMSwarm 661 662 Level: beginner 663 664 Notes: 665 The new point will have all fields initialized to zero. 666 667 .seealso: DMSwarmAddNPoints() 668 @*/ 669 PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm) 670 { 671 DM_Swarm *swarm = (DM_Swarm*)dm->data; 672 PetscErrorCode ierr; 673 674 PetscFunctionBegin; 675 if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);} 676 ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr); 677 ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr); 678 ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr); 679 PetscFunctionReturn(0); 680 } 681 682 /*@C 683 DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm 684 685 Not collective 686 687 Input parameters: 688 + dm - a DMSwarm 689 - npoints - the number of new points to add 690 691 Level: beginner 692 693 Notes: 694 The new point will have all fields initialized to zero. 695 696 .seealso: DMSwarmAddPoint() 697 @*/ 698 PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints) 699 { 700 DM_Swarm *swarm = (DM_Swarm*)dm->data; 701 PetscErrorCode ierr; 702 PetscInt nlocal; 703 704 PetscFunctionBegin; 705 ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr); 706 ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr); 707 nlocal = nlocal + npoints; 708 ierr = DataBucketSetSizes(swarm->db,nlocal,DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr); 709 ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr); 710 PetscFunctionReturn(0); 711 } 712 713 /*@C 714 DMSwarmRemovePoint - Remove the last point from the DMSwarm 715 716 Not collective 717 718 Input parameter: 719 . dm - a DMSwarm 720 721 Level: beginner 722 723 .seealso: DMSwarmRemovePointAtIndex() 724 @*/ 725 PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm) 726 { 727 DM_Swarm *swarm = (DM_Swarm*)dm->data; 728 PetscErrorCode ierr; 729 730 PetscFunctionBegin; 731 ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr); 732 ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr); 733 ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr); 734 PetscFunctionReturn(0); 735 } 736 737 /*@C 738 DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm 739 740 Not collective 741 742 Input parameters: 743 + dm - a DMSwarm 744 - idx - index of point to remove 745 746 Level: beginner 747 748 .seealso: DMSwarmRemovePoint() 749 @*/ 750 PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx) 751 { 752 DM_Swarm *swarm = (DM_Swarm*)dm->data; 753 PetscErrorCode ierr; 754 755 PetscFunctionBegin; 756 ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr); 757 ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr); 758 ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr); 759 PetscFunctionReturn(0); 760 } 761 762 /*@C 763 DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm 764 765 Not collective 766 767 Input parameters: 768 + dm - a DMSwarm 769 . pi - the index of the point to copy 770 - pj - the point index where the copy should be located 771 772 Level: beginner 773 774 .seealso: DMSwarmRemovePoint() 775 @*/ 776 PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj) 777 { 778 DM_Swarm *swarm = (DM_Swarm*)dm->data; 779 PetscErrorCode ierr; 780 781 PetscFunctionBegin; 782 if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);} 783 ierr = DataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr); 784 PetscFunctionReturn(0); 785 } 786 787 PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points) 788 { 789 PetscErrorCode ierr; 790 791 PetscFunctionBegin; 792 ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr); 793 PetscFunctionReturn(0); 794 } 795 796 /*@C 797 DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks 798 799 Collective on DM 800 801 Input parameters: 802 + dm - the DMSwarm 803 - remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank 804 805 Notes: 806 The DM will be modified to accomodate received points. 807 If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM. 808 Different styles of migration are supported. See DMSwarmSetMigrateType(). 809 810 Level: advanced 811 812 .seealso: DMSwarmSetMigrateType() 813 @*/ 814 PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points) 815 { 816 DM_Swarm *swarm = (DM_Swarm*)dm->data; 817 PetscErrorCode ierr; 818 819 PetscFunctionBegin; 820 ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr); 821 switch (swarm->migrate_type) { 822 case DMSWARM_MIGRATE_BASIC: 823 ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr); 824 break; 825 case DMSWARM_MIGRATE_DMCELLNSCATTER: 826 ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr); 827 break; 828 case DMSWARM_MIGRATE_DMCELLEXACT: 829 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented"); 830 /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/ 831 break; 832 case DMSWARM_MIGRATE_USER: 833 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented"); 834 /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/ 835 break; 836 default: 837 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown"); 838 break; 839 } 840 ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr); 841 PetscFunctionReturn(0); 842 } 843 844 PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize); 845 846 /* 847 DMSwarmCollectViewCreate 848 849 * Applies a collection method and gathers point neighbour points into dm 850 851 Notes: 852 Users should call DMSwarmCollectViewDestroy() after 853 they have finished computations associated with the collected points 854 */ 855 856 /*@C 857 DMSwarmCollectViewCreate - Applies a collection method and gathers points 858 in neighbour MPI-ranks into the DMSwarm 859 860 Collective on DM 861 862 Input parameter: 863 . dm - the DMSwarm 864 865 Notes: 866 Users should call DMSwarmCollectViewDestroy() after 867 they have finished computations associated with the collected points 868 Different collect methods are supported. See DMSwarmSetCollectType(). 869 870 Level: advanced 871 872 .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType() 873 @*/ 874 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm) 875 { 876 PetscErrorCode ierr; 877 DM_Swarm *swarm = (DM_Swarm*)dm->data; 878 PetscInt ng; 879 880 PetscFunctionBegin; 881 if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active"); 882 ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr); 883 switch (swarm->collect_type) { 884 885 case DMSWARM_COLLECT_BASIC: 886 ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr); 887 break; 888 case DMSWARM_COLLECT_DMDABOUNDINGBOX: 889 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented"); 890 /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/ 891 break; 892 case DMSWARM_COLLECT_GENERAL: 893 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented"); 894 /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/ 895 break; 896 default: 897 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown"); 898 break; 899 } 900 swarm->collect_view_active = PETSC_TRUE; 901 swarm->collect_view_reset_nlocal = ng; 902 PetscFunctionReturn(0); 903 } 904 905 /*@C 906 DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate() 907 908 Collective on DM 909 910 Input parameters: 911 . dm - the DMSwarm 912 913 Notes: 914 Users should call DMSwarmCollectViewCreate() before this function is called. 915 916 Level: advanced 917 918 .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType() 919 @*/ 920 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm) 921 { 922 PetscErrorCode ierr; 923 DM_Swarm *swarm = (DM_Swarm*)dm->data; 924 925 PetscFunctionBegin; 926 if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active"); 927 ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr); 928 swarm->collect_view_active = PETSC_FALSE; 929 PetscFunctionReturn(0); 930 } 931 932 PetscErrorCode DMSwarmSetUpPIC(DM dm) 933 { 934 PetscInt dim; 935 PetscErrorCode ierr; 936 937 PetscFunctionBegin; 938 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 939 if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim); 940 if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim); 941 ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr); 942 ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr); 943 PetscFunctionReturn(0); 944 } 945 946 /*@C 947 DMSwarmSetType - Set particular flavor of DMSwarm 948 949 Collective on DM 950 951 Input parameters: 952 + dm - the DMSwarm 953 - stype - the DMSwarm type (e.g. DMSWARM_PIC) 954 955 Level: advanced 956 957 .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType() 958 @*/ 959 PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype) 960 { 961 DM_Swarm *swarm = (DM_Swarm*)dm->data; 962 PetscErrorCode ierr; 963 964 PetscFunctionBegin; 965 swarm->swarm_type = stype; 966 if (swarm->swarm_type == DMSWARM_PIC) { 967 ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr); 968 } 969 PetscFunctionReturn(0); 970 } 971 972 PetscErrorCode DMSetup_Swarm(DM dm) 973 { 974 DM_Swarm *swarm = (DM_Swarm*)dm->data; 975 PetscErrorCode ierr; 976 PetscMPIInt rank; 977 PetscInt p,npoints,*rankval; 978 979 PetscFunctionBegin; 980 if (swarm->issetup) PetscFunctionReturn(0); 981 982 swarm->issetup = PETSC_TRUE; 983 984 if (swarm->swarm_type == DMSWARM_PIC) { 985 /* check dmcell exists */ 986 if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM"); 987 988 if (swarm->dmcell->ops->locatepointssubdomain) { 989 /* check methods exists for exact ownership identificiation */ 990 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm)," DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr); 991 swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT; 992 } else { 993 /* check methods exist for point location AND rank neighbor identification */ 994 if (swarm->dmcell->ops->locatepoints) { 995 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm)," DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr); 996 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined"); 997 998 if (swarm->dmcell->ops->getneighbors) { 999 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm)," DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr); 1000 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined"); 1001 1002 swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER; 1003 } 1004 } 1005 1006 ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr); 1007 1008 /* check some fields were registered */ 1009 if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()"); 1010 1011 /* check local sizes were set */ 1012 if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()"); 1013 1014 /* initialize values in pid and rank placeholders */ 1015 /* TODO: [pid - use MPI_Scan] */ 1016 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr); 1017 ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr); 1018 ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr); 1019 for (p=0; p<npoints; p++) { 1020 rankval[p] = (PetscInt)rank; 1021 } 1022 ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr); 1023 PetscFunctionReturn(0); 1024 } 1025 1026 extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx); 1027 1028 PetscErrorCode DMDestroy_Swarm(DM dm) 1029 { 1030 DM_Swarm *swarm = (DM_Swarm*)dm->data; 1031 PetscErrorCode ierr; 1032 1033 PetscFunctionBegin; 1034 ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr); 1035 if (swarm->sort_context) { 1036 ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr); 1037 } 1038 ierr = PetscFree(swarm);CHKERRQ(ierr); 1039 PetscFunctionReturn(0); 1040 } 1041 1042 PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer) 1043 { 1044 DM cdm; 1045 PetscDraw draw; 1046 PetscReal *coords, oldPause; 1047 PetscInt Np, p, bs; 1048 PetscErrorCode ierr; 1049 1050 PetscFunctionBegin; 1051 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1052 ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr); 1053 ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr); 1054 ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr); 1055 ierr = DMView(cdm, viewer);CHKERRQ(ierr); 1056 ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr); 1057 1058 ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr); 1059 ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr); 1060 for (p = 0; p < Np; ++p) { 1061 const PetscInt i = p*bs; 1062 1063 ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr); 1064 } 1065 ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr); 1066 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1067 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1068 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1069 PetscFunctionReturn(0); 1070 } 1071 1072 PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer) 1073 { 1074 DM_Swarm *swarm = (DM_Swarm*)dm->data; 1075 PetscBool iascii,ibinary,ishdf5,isvtk,isdraw; 1076 PetscErrorCode ierr; 1077 1078 PetscFunctionBegin; 1079 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1080 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 1081 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1082 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr); 1083 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1084 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1085 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1086 if (iascii) { 1087 ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr); 1088 } else if (ibinary) { 1089 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support"); 1090 } else if (ishdf5) { 1091 #if defined(PETSC_HAVE_HDF5) 1092 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support"); 1093 #else 1094 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5"); 1095 #endif 1096 } else if (isvtk) { 1097 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support"); 1098 } else if (isdraw) { 1099 ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr); 1100 } 1101 PetscFunctionReturn(0); 1102 } 1103 1104 /*MC 1105 1106 DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type. 1107 This implementation was designed for particle methods in which the underlying 1108 data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type. 1109 1110 User data can be represented by DMSwarm through a registering "fields". 1111 To register a field, the user must provide; 1112 (a) a unique name; 1113 (b) the data type (or size in bytes); 1114 (c) the block size of the data. 1115 1116 For example, suppose the application requires a unique id, energy, momentum and density to be stored 1117 on a set of of particles. Then the following code could be used 1118 1119 $ DMSwarmInitializeFieldRegister(dm) 1120 $ DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG); 1121 $ DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL); 1122 $ DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL); 1123 $ DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT); 1124 $ DMSwarmFinalizeFieldRegister(dm) 1125 1126 The fields represented by DMSwarm are dynamic and can be re-sized at any time. 1127 The only restriction imposed by DMSwarm is that all fields contain the same number of points. 1128 1129 To support particle methods, "migration" techniques are provided. These methods migrate data 1130 between MPI-ranks. 1131 1132 DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector(). 1133 As a DMSwarm may internally define and store values of different data types, 1134 before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which 1135 fields should be used to define a Vec object via 1136 DMSwarmVectorDefineField() 1137 The specified field can can changed be changed at any time - thereby permitting vectors 1138 compatable with different fields to be created. 1139 1140 A dual representation of fields in the DMSwarm and a Vec object is permitted via 1141 DMSwarmCreateGlobalVectorFromField() 1142 Here the data defining the field in the DMSwarm is shared with a Vec. 1143 This is inherently unsafe if you alter the size of the field at any time between 1144 calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField(). 1145 If the local size of the DMSwarm does not match the local size of the global vector 1146 when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown. 1147 1148 Additional high-level support is provided for Particle-In-Cell methods. 1149 Please refer to the man page for DMSwarmSetType(). 1150 1151 Level: beginner 1152 1153 .seealso: DMType, DMCreate(), DMSetType() 1154 M*/ 1155 PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm) 1156 { 1157 DM_Swarm *swarm; 1158 PetscErrorCode ierr; 1159 1160 PetscFunctionBegin; 1161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1162 ierr = PetscNewLog(dm,&swarm);CHKERRQ(ierr); 1163 dm->data = swarm; 1164 1165 ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr); 1166 ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr); 1167 1168 swarm->vec_field_set = PETSC_FALSE; 1169 swarm->issetup = PETSC_FALSE; 1170 swarm->swarm_type = DMSWARM_BASIC; 1171 swarm->migrate_type = DMSWARM_MIGRATE_BASIC; 1172 swarm->collect_type = DMSWARM_COLLECT_BASIC; 1173 swarm->migrate_error_on_missing_point = PETSC_FALSE; 1174 1175 swarm->dmcell = NULL; 1176 swarm->collect_view_active = PETSC_FALSE; 1177 swarm->collect_view_reset_nlocal = -1; 1178 1179 dm->dim = 0; 1180 dm->ops->view = DMView_Swarm; 1181 dm->ops->load = NULL; 1182 dm->ops->setfromoptions = NULL; 1183 dm->ops->clone = NULL; 1184 dm->ops->setup = DMSetup_Swarm; 1185 dm->ops->createdefaultsection = NULL; 1186 dm->ops->createdefaultconstraints = NULL; 1187 dm->ops->createglobalvector = DMCreateGlobalVector_Swarm; 1188 dm->ops->createlocalvector = DMCreateLocalVector_Swarm; 1189 dm->ops->getlocaltoglobalmapping = NULL; 1190 dm->ops->createfieldis = NULL; 1191 dm->ops->createcoordinatedm = NULL; 1192 dm->ops->getcoloring = NULL; 1193 dm->ops->creatematrix = NULL; 1194 dm->ops->createinterpolation = NULL; 1195 dm->ops->getaggregates = NULL; 1196 dm->ops->getinjection = NULL; 1197 dm->ops->refine = NULL; 1198 dm->ops->coarsen = NULL; 1199 dm->ops->refinehierarchy = NULL; 1200 dm->ops->coarsenhierarchy = NULL; 1201 dm->ops->globaltolocalbegin = NULL; 1202 dm->ops->globaltolocalend = NULL; 1203 dm->ops->localtoglobalbegin = NULL; 1204 dm->ops->localtoglobalend = NULL; 1205 dm->ops->destroy = DMDestroy_Swarm; 1206 dm->ops->createsubdm = NULL; 1207 dm->ops->getdimpoints = NULL; 1208 dm->ops->locatepoints = NULL; 1209 PetscFunctionReturn(0); 1210 } 1211