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