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