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