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; 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 = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr); 362 PetscFunctionReturn(0); 363 } 364 365 /*@C 366 DMSwarmSetCellDM - Attachs a DM to a DMSwarm 367 368 Collective on DM 369 370 Input parameters: 371 + dm - a DMSwarm 372 - dmcell - the DM to attach to the DMSwarm 373 374 Level: beginner 375 376 Notes: 377 The attached DM (dmcell) will be queried for point location and 378 neighbor MPI-rank information if DMSwarmMigrate() is called. 379 380 .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate() 381 @*/ 382 PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell) 383 { 384 DM_Swarm *swarm = (DM_Swarm*)dm->data; 385 386 PetscFunctionBegin; 387 swarm->dmcell = dmcell; 388 PetscFunctionReturn(0); 389 } 390 391 /*@C 392 DMSwarmGetCellDM - Fetches the attached cell DM 393 394 Collective on DM 395 396 Input parameter: 397 . dm - a DMSwarm 398 399 Output parameter: 400 . dmcell - the DM which was attached to the DMSwarm 401 402 Level: beginner 403 404 .seealso: DMSwarmSetCellDM() 405 @*/ 406 PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell) 407 { 408 DM_Swarm *swarm = (DM_Swarm*)dm->data; 409 410 PetscFunctionBegin; 411 *dmcell = swarm->dmcell; 412 PetscFunctionReturn(0); 413 } 414 415 /*@C 416 DMSwarmGetLocalSize - Retrives the local length of fields registered 417 418 Not collective 419 420 Input parameter: 421 . dm - a DMSwarm 422 423 Output parameter: 424 . nlocal - the length of each registered field 425 426 Level: beginner 427 428 .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes() 429 @*/ 430 PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal) 431 { 432 DM_Swarm *swarm = (DM_Swarm*)dm->data; 433 PetscErrorCode ierr; 434 435 PetscFunctionBegin; 436 if (nlocal) {ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);} 437 PetscFunctionReturn(0); 438 } 439 440 /*@C 441 DMSwarmGetSize - Retrives the total length of fields registered 442 443 Collective on DM 444 445 Input parameter: 446 . dm - a DMSwarm 447 448 Output parameter: 449 . n - the total length of each registered field 450 451 Level: beginner 452 453 Note: 454 This calls MPI_Allreduce upon each call (inefficient but safe) 455 456 .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes() 457 @*/ 458 PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n) 459 { 460 DM_Swarm *swarm = (DM_Swarm*)dm->data; 461 PetscErrorCode ierr; 462 PetscInt nlocal,ng; 463 464 PetscFunctionBegin; 465 ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr); 466 ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 467 if (n) { *n = ng; } 468 PetscFunctionReturn(0); 469 } 470 471 /*@C 472 DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type 473 474 Collective on DM 475 476 Input parameters: 477 + dm - a DMSwarm 478 . fieldname - the textual name to identify this field 479 . blocksize - the number of each data type 480 - type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG) 481 482 Level: beginner 483 484 Notes: 485 The textual name for each registered field must be unique. 486 487 .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField() 488 @*/ 489 PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type) 490 { 491 PetscErrorCode ierr; 492 DM_Swarm *swarm = (DM_Swarm*)dm->data; 493 size_t size; 494 495 PetscFunctionBegin; 496 if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first"); 497 if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first"); 498 499 if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 500 if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 501 if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 502 if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 503 if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}"); 504 505 ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr); 506 /* Load a specific data type into data bucket, specifying textual name and its size in bytes */ 507 ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr); 508 { 509 DataField gfield; 510 511 ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr); 512 ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr); 513 } 514 swarm->db->field[swarm->db->nfields-1]->petsc_type = type; 515 PetscFunctionReturn(0); 516 } 517 518 /*@C 519 DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm 520 521 Collective on DM 522 523 Input parameters: 524 + dm - a DMSwarm 525 . fieldname - the textual name to identify this field 526 - size - the size in bytes of the user struct of each data type 527 528 Level: beginner 529 530 Notes: 531 The textual name for each registered field must be unique. 532 533 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField() 534 @*/ 535 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size) 536 { 537 PetscErrorCode ierr; 538 DM_Swarm *swarm = (DM_Swarm*)dm->data; 539 540 PetscFunctionBegin; 541 ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr); 542 swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ; 543 PetscFunctionReturn(0); 544 } 545 546 /*@C 547 DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm 548 549 Collective on DM 550 551 Input parameters: 552 + dm - a DMSwarm 553 . fieldname - the textual name to identify this field 554 . size - the size in bytes of the user data type 555 - blocksize - the number of each data type 556 557 Level: beginner 558 559 Notes: 560 The textual name for each registered field must be unique. 561 562 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField() 563 @*/ 564 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize) 565 { 566 DM_Swarm *swarm = (DM_Swarm*)dm->data; 567 PetscErrorCode ierr; 568 569 PetscFunctionBegin; 570 ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr); 571 { 572 DataField gfield; 573 574 ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr); 575 ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr); 576 } 577 swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN; 578 PetscFunctionReturn(0); 579 } 580 581 /*@C 582 DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field 583 584 Not collective 585 586 Input parameters: 587 + dm - a DMSwarm 588 - fieldname - the textual name to identify this field 589 590 Output parameters: 591 + blocksize - the number of each data type 592 . type - the data type 593 - data - pointer to raw array 594 595 Level: beginner 596 597 Notes: 598 The array must be returned using a matching call to DMSwarmRestoreField(). 599 600 .seealso: DMSwarmRestoreField() 601 @*/ 602 PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data) 603 { 604 DM_Swarm *swarm = (DM_Swarm*)dm->data; 605 DataField gfield; 606 PetscErrorCode ierr; 607 608 PetscFunctionBegin; 609 if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); } 610 ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr); 611 ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr); 612 ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr); 613 if (blocksize) {*blocksize = gfield->bs; } 614 if (type) { *type = gfield->petsc_type; } 615 PetscFunctionReturn(0); 616 } 617 618 /*@C 619 DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field 620 621 Not collective 622 623 Input parameters: 624 + dm - a DMSwarm 625 - fieldname - the textual name to identify this field 626 627 Output parameters: 628 + blocksize - the number of each data type 629 . type - the data type 630 - data - pointer to raw array 631 632 Level: beginner 633 634 Notes: 635 The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField(). 636 637 .seealso: DMSwarmGetField() 638 @*/ 639 PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data) 640 { 641 DM_Swarm *swarm = (DM_Swarm*)dm->data; 642 DataField gfield; 643 PetscErrorCode ierr; 644 645 PetscFunctionBegin; 646 ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr); 647 ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr); 648 if (data) *data = NULL; 649 PetscFunctionReturn(0); 650 } 651 652 /*@C 653 DMSwarmAddPoint - Add space for one new point in the DMSwarm 654 655 Not collective 656 657 Input parameter: 658 . dm - a DMSwarm 659 660 Level: beginner 661 662 Notes: 663 The new point will have all fields initialized to zero. 664 665 .seealso: DMSwarmAddNPoints() 666 @*/ 667 PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm) 668 { 669 DM_Swarm *swarm = (DM_Swarm*)dm->data; 670 PetscErrorCode ierr; 671 672 PetscFunctionBegin; 673 if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);} 674 ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr); 675 PetscFunctionReturn(0); 676 } 677 678 /*@C 679 DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm 680 681 Not collective 682 683 Input parameters: 684 + dm - a DMSwarm 685 - npoints - the number of new points to add 686 687 Level: beginner 688 689 Notes: 690 The new point will have all fields initialized to zero. 691 692 .seealso: DMSwarmAddPoint() 693 @*/ 694 PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints) 695 { 696 DM_Swarm *swarm = (DM_Swarm*)dm->data; 697 PetscErrorCode ierr; 698 PetscInt nlocal; 699 700 PetscFunctionBegin; 701 ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr); 702 nlocal = nlocal + npoints; 703 ierr = DataBucketSetSizes(swarm->db,nlocal,DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr); 704 PetscFunctionReturn(0); 705 } 706 707 /*@C 708 DMSwarmRemovePoint - Remove the last point from the DMSwarm 709 710 Not collective 711 712 Input parameter: 713 . dm - a DMSwarm 714 715 Level: beginner 716 717 .seealso: DMSwarmRemovePointAtIndex() 718 @*/ 719 PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm) 720 { 721 DM_Swarm *swarm = (DM_Swarm*)dm->data; 722 PetscErrorCode ierr; 723 724 PetscFunctionBegin; 725 ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr); 726 PetscFunctionReturn(0); 727 } 728 729 /*@C 730 DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm 731 732 Not collective 733 734 Input parameters: 735 + dm - a DMSwarm 736 - idx - index of point to remove 737 738 Level: beginner 739 740 .seealso: DMSwarmRemovePoint() 741 @*/ 742 PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx) 743 { 744 DM_Swarm *swarm = (DM_Swarm*)dm->data; 745 PetscErrorCode ierr; 746 747 PetscFunctionBegin; 748 ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr); 749 PetscFunctionReturn(0); 750 } 751 752 PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points) 753 { 754 PetscErrorCode ierr; 755 756 PetscFunctionBegin; 757 ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr); 758 PetscFunctionReturn(0); 759 } 760 761 /*@C 762 DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks 763 764 Collective on DM 765 766 Input parameters: 767 + dm - the DMSwarm 768 - remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank 769 770 Notes: 771 The DM will be modified to accomodate received points. 772 If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM. 773 Different styles of migration are supported. See DMSwarmSetMigrateType(). 774 775 Level: advanced 776 777 .seealso: DMSwarmSetMigrateType() 778 @*/ 779 PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points) 780 { 781 DM_Swarm *swarm = (DM_Swarm*)dm->data; 782 PetscErrorCode ierr; 783 784 PetscFunctionBegin; 785 ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr); 786 switch (swarm->migrate_type) { 787 case DMSWARM_MIGRATE_BASIC: 788 ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr); 789 break; 790 case DMSWARM_MIGRATE_DMCELLNSCATTER: 791 ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr); 792 break; 793 case DMSWARM_MIGRATE_DMCELLEXACT: 794 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented"); 795 /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/ 796 break; 797 case DMSWARM_MIGRATE_USER: 798 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented"); 799 /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/ 800 break; 801 default: 802 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown"); 803 break; 804 } 805 ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr); 806 PetscFunctionReturn(0); 807 } 808 809 PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize); 810 811 /* 812 DMSwarmCollectViewCreate 813 814 * Applies a collection method and gathers point neighbour points into dm 815 816 Notes: 817 Users should call DMSwarmCollectViewDestroy() after 818 they have finished computations associated with the collected points 819 */ 820 821 /*@C 822 DMSwarmCollectViewCreate - Applies a collection method and gathers points 823 in neighbour MPI-ranks into the DMSwarm 824 825 Collective on DM 826 827 Input parameter: 828 . dm - the DMSwarm 829 830 Notes: 831 Users should call DMSwarmCollectViewDestroy() after 832 they have finished computations associated with the collected points 833 Different collect methods are supported. See DMSwarmSetCollectType(). 834 835 Level: advanced 836 837 .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType() 838 @*/ 839 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm) 840 { 841 PetscErrorCode ierr; 842 DM_Swarm *swarm = (DM_Swarm*)dm->data; 843 PetscInt ng; 844 845 PetscFunctionBegin; 846 if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active"); 847 ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr); 848 switch (swarm->collect_type) { 849 850 case DMSWARM_COLLECT_BASIC: 851 ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr); 852 break; 853 case DMSWARM_COLLECT_DMDABOUNDINGBOX: 854 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented"); 855 /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/ 856 break; 857 case DMSWARM_COLLECT_GENERAL: 858 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented"); 859 /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/ 860 break; 861 default: 862 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown"); 863 break; 864 } 865 swarm->collect_view_active = PETSC_TRUE; 866 swarm->collect_view_reset_nlocal = ng; 867 PetscFunctionReturn(0); 868 } 869 870 /*@C 871 DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate() 872 873 Collective on DM 874 875 Input parameters: 876 . dm - the DMSwarm 877 878 Notes: 879 Users should call DMSwarmCollectViewCreate() before this function is called. 880 881 Level: advanced 882 883 .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType() 884 @*/ 885 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm) 886 { 887 PetscErrorCode ierr; 888 DM_Swarm *swarm = (DM_Swarm*)dm->data; 889 890 PetscFunctionBegin; 891 if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active"); 892 ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr); 893 swarm->collect_view_active = PETSC_FALSE; 894 PetscFunctionReturn(0); 895 } 896 897 PetscErrorCode DMSwarmSetUpPIC(DM dm) 898 { 899 PetscInt dim; 900 PetscErrorCode ierr; 901 902 PetscFunctionBegin; 903 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 904 if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim); 905 if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim); 906 ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr); 907 ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr); 908 PetscFunctionReturn(0); 909 } 910 911 /*@C 912 DMSwarmSetType - Set particular flavor of DMSwarm 913 914 Collective on DM 915 916 Input parameters: 917 + dm - the DMSwarm 918 - stype - the DMSwarm type (e.g. DMSWARM_PIC) 919 920 Level: advanced 921 922 .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType() 923 @*/ 924 PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype) 925 { 926 DM_Swarm *swarm = (DM_Swarm*)dm->data; 927 PetscErrorCode ierr; 928 929 PetscFunctionBegin; 930 swarm->swarm_type = stype; 931 if (swarm->swarm_type == DMSWARM_PIC) { 932 ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr); 933 } 934 PetscFunctionReturn(0); 935 } 936 937 PetscErrorCode DMSetup_Swarm(DM dm) 938 { 939 DM_Swarm *swarm = (DM_Swarm*)dm->data; 940 PetscErrorCode ierr; 941 PetscMPIInt rank; 942 PetscInt p,npoints,*rankval; 943 944 PetscFunctionBegin; 945 if (swarm->issetup) PetscFunctionReturn(0); 946 947 swarm->issetup = PETSC_TRUE; 948 949 if (swarm->swarm_type == DMSWARM_PIC) { 950 /* check dmcell exists */ 951 if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM"); 952 953 if (swarm->dmcell->ops->locatepointssubdomain) { 954 /* check methods exists for exact ownership identificiation */ 955 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm)," DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr); 956 swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT; 957 } else { 958 /* check methods exist for point location AND rank neighbor identification */ 959 if (swarm->dmcell->ops->locatepoints) { 960 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm)," DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr); 961 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined"); 962 963 if (swarm->dmcell->ops->getneighbors) { 964 ierr = PetscPrintf(PetscObjectComm((PetscObject)dm)," DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr); 965 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined"); 966 967 swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER; 968 } 969 } 970 971 ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr); 972 973 /* check some fields were registered */ 974 if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()"); 975 976 /* check local sizes were set */ 977 if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()"); 978 979 /* initialize values in pid and rank placeholders */ 980 /* TODO: [pid - use MPI_Scan] */ 981 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr); 982 ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr); 983 ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr); 984 for (p=0; p<npoints; p++) { 985 rankval[p] = (PetscInt)rank; 986 } 987 ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr); 988 PetscFunctionReturn(0); 989 } 990 991 extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx); 992 993 PetscErrorCode DMDestroy_Swarm(DM dm) 994 { 995 DM_Swarm *swarm = (DM_Swarm*)dm->data; 996 PetscErrorCode ierr; 997 998 PetscFunctionBegin; 999 ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr); 1000 if (swarm->sort_context) { 1001 ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr); 1002 } 1003 ierr = PetscFree(swarm);CHKERRQ(ierr); 1004 PetscFunctionReturn(0); 1005 } 1006 1007 PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer) 1008 { 1009 DM cdm; 1010 PetscDraw draw; 1011 PetscReal *coords, oldPause; 1012 PetscInt Np, p, bs; 1013 PetscErrorCode ierr; 1014 1015 PetscFunctionBegin; 1016 ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1017 ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr); 1018 ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr); 1019 ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr); 1020 ierr = DMView(cdm, viewer);CHKERRQ(ierr); 1021 ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr); 1022 1023 ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr); 1024 ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr); 1025 for (p = 0; p < Np; ++p) { 1026 const PetscInt i = p*bs; 1027 1028 ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr); 1029 } 1030 ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr); 1031 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1032 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1033 ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1034 PetscFunctionReturn(0); 1035 } 1036 1037 PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer) 1038 { 1039 DM_Swarm *swarm = (DM_Swarm*)dm->data; 1040 PetscBool iascii,ibinary,ishdf5,isvtk,isdraw; 1041 PetscErrorCode ierr; 1042 1043 PetscFunctionBegin; 1044 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1045 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 1046 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1047 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr); 1048 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1049 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1050 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 1051 if (iascii) { 1052 ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr); 1053 } else if (ibinary) { 1054 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support"); 1055 } else if (ishdf5) { 1056 #if defined(PETSC_HAVE_HDF5) 1057 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support"); 1058 #else 1059 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5"); 1060 #endif 1061 } else if (isvtk) { 1062 SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support"); 1063 } else if (isdraw) { 1064 ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr); 1065 } 1066 PetscFunctionReturn(0); 1067 } 1068 1069 /*MC 1070 1071 DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type. 1072 This implementation was designed for particle methods in which the underlying 1073 data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type. 1074 1075 User data can be represented by DMSwarm through a registering "fields". 1076 To register a field, the user must provide; 1077 (a) a unique name; 1078 (b) the data type (or size in bytes); 1079 (c) the block size of the data. 1080 1081 For example, suppose the application requires a unique id, energy, momentum and density to be stored 1082 on a set of of particles. Then the following code could be used 1083 1084 $ DMSwarmInitializeFieldRegister(dm) 1085 $ DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG); 1086 $ DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL); 1087 $ DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL); 1088 $ DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT); 1089 $ DMSwarmFinalizeFieldRegister(dm) 1090 1091 The fields represented by DMSwarm are dynamic and can be re-sized at any time. 1092 The only restriction imposed by DMSwarm is that all fields contain the same number of points. 1093 1094 To support particle methods, "migration" techniques are provided. These methods migrate data 1095 between MPI-ranks. 1096 1097 DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector(). 1098 As a DMSwarm may internally define and store values of different data types, 1099 before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which 1100 fields should be used to define a Vec object via 1101 DMSwarmVectorDefineField() 1102 The specified field can can changed be changed at any time - thereby permitting vectors 1103 compatable with different fields to be created. 1104 1105 A dual representation of fields in the DMSwarm and a Vec object is permitted via 1106 DMSwarmCreateGlobalVectorFromField() 1107 Here the data defining the field in the DMSwarm is shared with a Vec. 1108 This is inherently unsafe if you alter the size of the field at any time between 1109 calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField(). 1110 If the local size of the DMSwarm does not match the local size of the global vector 1111 when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown. 1112 1113 Additional high-level support is provided for Particle-In-Cell methods. 1114 Please refer to the man page for DMSwarmSetType(). 1115 1116 Level: beginner 1117 1118 .seealso: DMType, DMCreate(), DMSetType() 1119 M*/ 1120 PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm) 1121 { 1122 DM_Swarm *swarm; 1123 PetscErrorCode ierr; 1124 1125 PetscFunctionBegin; 1126 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1127 ierr = PetscNewLog(dm,&swarm);CHKERRQ(ierr); 1128 dm->data = swarm; 1129 1130 ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr); 1131 ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr); 1132 1133 swarm->vec_field_set = PETSC_FALSE; 1134 swarm->issetup = PETSC_FALSE; 1135 swarm->swarm_type = DMSWARM_BASIC; 1136 swarm->migrate_type = DMSWARM_MIGRATE_BASIC; 1137 swarm->collect_type = DMSWARM_COLLECT_BASIC; 1138 swarm->migrate_error_on_missing_point = PETSC_FALSE; 1139 1140 swarm->dmcell = NULL; 1141 swarm->collect_view_active = PETSC_FALSE; 1142 swarm->collect_view_reset_nlocal = -1; 1143 1144 dm->dim = 0; 1145 dm->ops->view = DMView_Swarm; 1146 dm->ops->load = NULL; 1147 dm->ops->setfromoptions = NULL; 1148 dm->ops->clone = NULL; 1149 dm->ops->setup = DMSetup_Swarm; 1150 dm->ops->createdefaultsection = NULL; 1151 dm->ops->createdefaultconstraints = NULL; 1152 dm->ops->createglobalvector = DMCreateGlobalVector_Swarm; 1153 dm->ops->createlocalvector = DMCreateLocalVector_Swarm; 1154 dm->ops->getlocaltoglobalmapping = NULL; 1155 dm->ops->createfieldis = NULL; 1156 dm->ops->createcoordinatedm = NULL; 1157 dm->ops->getcoloring = NULL; 1158 dm->ops->creatematrix = NULL; 1159 dm->ops->createinterpolation = NULL; 1160 dm->ops->getaggregates = NULL; 1161 dm->ops->getinjection = NULL; 1162 dm->ops->refine = NULL; 1163 dm->ops->coarsen = NULL; 1164 dm->ops->refinehierarchy = NULL; 1165 dm->ops->coarsenhierarchy = NULL; 1166 dm->ops->globaltolocalbegin = NULL; 1167 dm->ops->globaltolocalend = NULL; 1168 dm->ops->localtoglobalbegin = NULL; 1169 dm->ops->localtoglobalend = NULL; 1170 dm->ops->destroy = DMDestroy_Swarm; 1171 dm->ops->createsubdm = NULL; 1172 dm->ops->getdimpoints = NULL; 1173 dm->ops->locatepoints = NULL; 1174 PetscFunctionReturn(0); 1175 } 1176