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