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