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