10e2ec84fSDave May #define PETSCDM_DLL 20e2ec84fSDave May #include <petsc/private/dmswarmimpl.h> /*I "petscdmswarm.h" I*/ 30e2ec84fSDave May #include <petscsf.h> 4b799feefSDave May #include <petscdmda.h> 5b799feefSDave May #include <petscdmplex.h> 635b38c60SMatthew G. Knepley #include <petscdt.h> 7279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h" 80e2ec84fSDave May 935b38c60SMatthew G. Knepley #include <petsc/private/petscfeimpl.h> /* For CoordinatesRefToReal() */ 1035b38c60SMatthew G. Knepley 110e2ec84fSDave May /* Coordinate insertition/addition API */ 120e2ec84fSDave May /*@C 1320f4b53cSBarry Smith DMSwarmSetPointsUniformCoordinates - Set point coordinates in a `DMSWARM` on a regular (ijk) grid 140e2ec84fSDave May 1520f4b53cSBarry Smith Collective 160e2ec84fSDave May 1760225df5SJacob Faibussowitsch Input Parameters: 1820f4b53cSBarry Smith + dm - the `DMSWARM` 190e2ec84fSDave May . min - minimum coordinate values in the x, y, z directions (array of length dim) 200e2ec84fSDave May . max - maximum coordinate values in the x, y, z directions (array of length dim) 210e2ec84fSDave May . npoints - number of points in each spatial direction (array of length dim) 2220f4b53cSBarry Smith - mode - indicates whether to append points to the swarm (`ADD_VALUES`), or over-ride existing points (`INSERT_VALUES`) 230e2ec84fSDave May 240e2ec84fSDave May Level: beginner 250e2ec84fSDave May 260e2ec84fSDave May Notes: 2720f4b53cSBarry Smith When using mode = `INSERT_VALUES`, this method will reset the number of particles in the `DMSWARM` 2820f4b53cSBarry Smith to be npoints[0]*npoints[1] (2D) or npoints[0]*npoints[1]*npoints[2] (3D). When using mode = `ADD_VALUES`, 2920f4b53cSBarry Smith new points will be appended to any already existing in the `DMSWARM` 300e2ec84fSDave May 3120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmSetCellDM()`, `DMSwarmType` 320e2ec84fSDave May @*/ 33d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMSwarmSetPointsUniformCoordinates(DM dm, PetscReal min[], PetscReal max[], PetscInt npoints[], InsertMode mode) 34d71ae5a4SJacob Faibussowitsch { 350e2ec84fSDave May PetscReal gmin[] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 360e2ec84fSDave May PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 370e2ec84fSDave May PetscInt i, j, k, N, bs, b, n_estimate, n_curr, n_new_est, p, n_found; 380e2ec84fSDave May Vec coorlocal; 390e2ec84fSDave May const PetscScalar *_coor; 400e2ec84fSDave May DM celldm; 410e2ec84fSDave May PetscReal dx[3]; 422e3d3761SDave May PetscInt _npoints[] = {0, 0, 1}; 430e2ec84fSDave May Vec pos; 440e2ec84fSDave May PetscScalar *_pos; 450e2ec84fSDave May PetscReal *swarm_coor; 460e2ec84fSDave May PetscInt *swarm_cellid; 470e2ec84fSDave May PetscSF sfcell = NULL; 480e2ec84fSDave May const PetscSFNode *LA_sfcell; 490e2ec84fSDave May 500e2ec84fSDave May PetscFunctionBegin; 510e2ec84fSDave May DMSWARMPICVALID(dm); 529566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(celldm, &coorlocal)); 549566063dSJacob Faibussowitsch PetscCall(VecGetSize(coorlocal, &N)); 559566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(coorlocal, &bs)); 560e2ec84fSDave May N = N / bs; 579566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coorlocal, &_coor)); 580e2ec84fSDave May for (i = 0; i < N; i++) { 590e2ec84fSDave May for (b = 0; b < bs; b++) { 60a5f152d1SDave May gmin[b] = PetscMin(gmin[b], PetscRealPart(_coor[bs * i + b])); 61a5f152d1SDave May gmax[b] = PetscMax(gmax[b], PetscRealPart(_coor[bs * i + b])); 620e2ec84fSDave May } 630e2ec84fSDave May } 649566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coorlocal, &_coor)); 650e2ec84fSDave May 660e2ec84fSDave May for (b = 0; b < bs; b++) { 6771844bb8SDave May if (npoints[b] > 1) { 680e2ec84fSDave May dx[b] = (max[b] - min[b]) / ((PetscReal)(npoints[b] - 1)); 6971844bb8SDave May } else { 7071844bb8SDave May dx[b] = 0.0; 7171844bb8SDave May } 722e3d3761SDave May _npoints[b] = npoints[b]; 730e2ec84fSDave May } 740e2ec84fSDave May 750e2ec84fSDave May /* determine number of points living in the bounding box */ 760e2ec84fSDave May n_estimate = 0; 772e3d3761SDave May for (k = 0; k < _npoints[2]; k++) { 782e3d3761SDave May for (j = 0; j < _npoints[1]; j++) { 792e3d3761SDave May for (i = 0; i < _npoints[0]; i++) { 800e2ec84fSDave May PetscReal xp[] = {0.0, 0.0, 0.0}; 810e2ec84fSDave May PetscInt ijk[3]; 820e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 830e2ec84fSDave May 840e2ec84fSDave May ijk[0] = i; 850e2ec84fSDave May ijk[1] = j; 860e2ec84fSDave May ijk[2] = k; 87ad540459SPierre Jolivet for (b = 0; b < bs; b++) xp[b] = min[b] + ijk[b] * dx[b]; 880e2ec84fSDave May for (b = 0; b < bs; b++) { 89ad540459SPierre Jolivet if (xp[b] < gmin[b]) point_inside = PETSC_FALSE; 90ad540459SPierre Jolivet if (xp[b] > gmax[b]) point_inside = PETSC_FALSE; 910e2ec84fSDave May } 92ad540459SPierre Jolivet if (point_inside) n_estimate++; 930e2ec84fSDave May } 940e2ec84fSDave May } 950e2ec84fSDave May } 960e2ec84fSDave May 970e2ec84fSDave May /* create candidate list */ 989566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &pos)); 999566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pos, bs * n_estimate, PETSC_DECIDE)); 1009566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(pos, bs)); 1019566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(pos)); 1029566063dSJacob Faibussowitsch PetscCall(VecGetArray(pos, &_pos)); 1030e2ec84fSDave May 1040e2ec84fSDave May n_estimate = 0; 1052e3d3761SDave May for (k = 0; k < _npoints[2]; k++) { 1062e3d3761SDave May for (j = 0; j < _npoints[1]; j++) { 1072e3d3761SDave May for (i = 0; i < _npoints[0]; i++) { 1080e2ec84fSDave May PetscReal xp[] = {0.0, 0.0, 0.0}; 1090e2ec84fSDave May PetscInt ijk[3]; 1100e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 1110e2ec84fSDave May 1120e2ec84fSDave May ijk[0] = i; 1130e2ec84fSDave May ijk[1] = j; 1140e2ec84fSDave May ijk[2] = k; 115ad540459SPierre Jolivet for (b = 0; b < bs; b++) xp[b] = min[b] + ijk[b] * dx[b]; 1160e2ec84fSDave May for (b = 0; b < bs; b++) { 117ad540459SPierre Jolivet if (xp[b] < gmin[b]) point_inside = PETSC_FALSE; 118ad540459SPierre Jolivet if (xp[b] > gmax[b]) point_inside = PETSC_FALSE; 1190e2ec84fSDave May } 1200e2ec84fSDave May if (point_inside) { 121ad540459SPierre Jolivet for (b = 0; b < bs; b++) _pos[bs * n_estimate + b] = xp[b]; 1220e2ec84fSDave May n_estimate++; 1230e2ec84fSDave May } 1240e2ec84fSDave May } 1250e2ec84fSDave May } 1260e2ec84fSDave May } 1279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pos, &_pos)); 1280e2ec84fSDave May 1290e2ec84fSDave May /* locate points */ 1309566063dSJacob Faibussowitsch PetscCall(DMLocatePoints(celldm, pos, DM_POINTLOCATION_NONE, &sfcell)); 1319566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell)); 1320e2ec84fSDave May n_found = 0; 1330e2ec84fSDave May for (p = 0; p < n_estimate; p++) { 134ad540459SPierre Jolivet if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) n_found++; 1350e2ec84fSDave May } 1360e2ec84fSDave May 1370e2ec84fSDave May /* adjust size */ 1380e2ec84fSDave May if (mode == ADD_VALUES) { 1399566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &n_curr)); 1400e2ec84fSDave May n_new_est = n_curr + n_found; 1419566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, n_new_est, -1)); 1420e2ec84fSDave May } 1430e2ec84fSDave May if (mode == INSERT_VALUES) { 1440e2ec84fSDave May n_curr = 0; 1450e2ec84fSDave May n_new_est = n_found; 1469566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, n_new_est, -1)); 1470e2ec84fSDave May } 1480e2ec84fSDave May 1490e2ec84fSDave May /* initialize new coords, cell owners, pid */ 1509566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pos, &_coor)); 1519566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor)); 1529566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 1530e2ec84fSDave May n_found = 0; 1540e2ec84fSDave May for (p = 0; p < n_estimate; p++) { 1550e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 156ad540459SPierre Jolivet for (b = 0; b < bs; b++) swarm_coor[bs * (n_curr + n_found) + b] = PetscRealPart(_coor[bs * p + b]); 1570e2ec84fSDave May swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 1580e2ec84fSDave May n_found++; 1590e2ec84fSDave May } 1600e2ec84fSDave May } 1619566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 1629566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor)); 1639566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pos, &_coor)); 1640e2ec84fSDave May 1659566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfcell)); 1669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pos)); 1673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1680e2ec84fSDave May } 1690e2ec84fSDave May 1700e2ec84fSDave May /*@C 17120f4b53cSBarry Smith DMSwarmSetPointCoordinates - Set point coordinates in a `DMSWARM` from a user defined list 1720e2ec84fSDave May 17320f4b53cSBarry Smith Collective 1740e2ec84fSDave May 17560225df5SJacob Faibussowitsch Input Parameters: 17620f4b53cSBarry Smith + dm - the `DMSWARM` 1770e2ec84fSDave May . npoints - the number of points to insert 1780e2ec84fSDave May . coor - the coordinate values 17920f4b53cSBarry Smith . redundant - if set to `PETSC_TRUE`, it is assumed that `npoints` and `coor` are only valid on rank 0 and should be broadcast to other ranks 18020f4b53cSBarry Smith - mode - indicates whether to append points to the swarm (`ADD_VALUES`), or over-ride existing points (`INSERT_VALUES`) 1810e2ec84fSDave May 1820e2ec84fSDave May Level: beginner 1830e2ec84fSDave May 1840e2ec84fSDave May Notes: 18520f4b53cSBarry Smith If the user has specified `redundant` as `PETSC_FALSE`, the cell `DM` will attempt to locate the coordinates provided by `coor` within 18620f4b53cSBarry Smith its sub-domain. If they any values within `coor` are not located in the sub-domain, they will be ignored and will not get 18720f4b53cSBarry Smith added to the `DMSWARM`. 1880e2ec84fSDave May 18920f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmSetType()`, `DMSwarmSetCellDM()`, `DMSwarmType`, `DMSwarmSetPointsUniformCoordinates()` 1900e2ec84fSDave May @*/ 191d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinates(DM dm, PetscInt npoints, PetscReal coor[], PetscBool redundant, InsertMode mode) 192d71ae5a4SJacob Faibussowitsch { 1930e2ec84fSDave May PetscReal gmin[] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 1940e2ec84fSDave May PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1950e2ec84fSDave May PetscInt i, N, bs, b, n_estimate, n_curr, n_new_est, p, n_found; 1960e2ec84fSDave May Vec coorlocal; 1970e2ec84fSDave May const PetscScalar *_coor; 1980e2ec84fSDave May DM celldm; 1990e2ec84fSDave May Vec pos; 2000e2ec84fSDave May PetscScalar *_pos; 2010e2ec84fSDave May PetscReal *swarm_coor; 2020e2ec84fSDave May PetscInt *swarm_cellid; 2030e2ec84fSDave May PetscSF sfcell = NULL; 2040e2ec84fSDave May const PetscSFNode *LA_sfcell; 2050e2ec84fSDave May PetscReal *my_coor; 2060e2ec84fSDave May PetscInt my_npoints; 2070e2ec84fSDave May PetscMPIInt rank; 2080e2ec84fSDave May MPI_Comm comm; 2090e2ec84fSDave May 2100e2ec84fSDave May PetscFunctionBegin; 2110e2ec84fSDave May DMSWARMPICVALID(dm); 2129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 2139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2140e2ec84fSDave May 2159566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 2169566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(celldm, &coorlocal)); 2179566063dSJacob Faibussowitsch PetscCall(VecGetSize(coorlocal, &N)); 2189566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(coorlocal, &bs)); 2190e2ec84fSDave May N = N / bs; 2209566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coorlocal, &_coor)); 2210e2ec84fSDave May for (i = 0; i < N; i++) { 2220e2ec84fSDave May for (b = 0; b < bs; b++) { 223a5f152d1SDave May gmin[b] = PetscMin(gmin[b], PetscRealPart(_coor[bs * i + b])); 224a5f152d1SDave May gmax[b] = PetscMax(gmax[b], PetscRealPart(_coor[bs * i + b])); 2250e2ec84fSDave May } 2260e2ec84fSDave May } 2279566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coorlocal, &_coor)); 2280e2ec84fSDave May 2290e2ec84fSDave May /* broadcast points from rank 0 if requested */ 2300e2ec84fSDave May if (redundant) { 2310e2ec84fSDave May my_npoints = npoints; 2329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&my_npoints, 1, MPIU_INT, 0, comm)); 2330e2ec84fSDave May 2340e2ec84fSDave May if (rank > 0) { /* allocate space */ 2359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs * my_npoints, &my_coor)); 2360e2ec84fSDave May } else { 2370e2ec84fSDave May my_coor = coor; 2380e2ec84fSDave May } 2399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(my_coor, bs * my_npoints, MPIU_REAL, 0, comm)); 2400e2ec84fSDave May } else { 2410e2ec84fSDave May my_npoints = npoints; 2420e2ec84fSDave May my_coor = coor; 2430e2ec84fSDave May } 2440e2ec84fSDave May 2450e2ec84fSDave May /* determine the number of points living in the bounding box */ 2460e2ec84fSDave May n_estimate = 0; 2470e2ec84fSDave May for (i = 0; i < my_npoints; i++) { 2480e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 2490e2ec84fSDave May 2500e2ec84fSDave May for (b = 0; b < bs; b++) { 251ad540459SPierre Jolivet if (my_coor[bs * i + b] < gmin[b]) point_inside = PETSC_FALSE; 252ad540459SPierre Jolivet if (my_coor[bs * i + b] > gmax[b]) point_inside = PETSC_FALSE; 2530e2ec84fSDave May } 254ad540459SPierre Jolivet if (point_inside) n_estimate++; 2550e2ec84fSDave May } 2560e2ec84fSDave May 2570e2ec84fSDave May /* create candidate list */ 2589566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &pos)); 2599566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pos, bs * n_estimate, PETSC_DECIDE)); 2609566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(pos, bs)); 2619566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(pos)); 2629566063dSJacob Faibussowitsch PetscCall(VecGetArray(pos, &_pos)); 2630e2ec84fSDave May 2640e2ec84fSDave May n_estimate = 0; 2650e2ec84fSDave May for (i = 0; i < my_npoints; i++) { 2660e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 2670e2ec84fSDave May 2680e2ec84fSDave May for (b = 0; b < bs; b++) { 269ad540459SPierre Jolivet if (my_coor[bs * i + b] < gmin[b]) point_inside = PETSC_FALSE; 270ad540459SPierre Jolivet if (my_coor[bs * i + b] > gmax[b]) point_inside = PETSC_FALSE; 2710e2ec84fSDave May } 2720e2ec84fSDave May if (point_inside) { 273ad540459SPierre Jolivet for (b = 0; b < bs; b++) _pos[bs * n_estimate + b] = my_coor[bs * i + b]; 2740e2ec84fSDave May n_estimate++; 2750e2ec84fSDave May } 2760e2ec84fSDave May } 2779566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pos, &_pos)); 2780e2ec84fSDave May 2790e2ec84fSDave May /* locate points */ 2809566063dSJacob Faibussowitsch PetscCall(DMLocatePoints(celldm, pos, DM_POINTLOCATION_NONE, &sfcell)); 2810e2ec84fSDave May 2829566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell)); 2830e2ec84fSDave May n_found = 0; 2840e2ec84fSDave May for (p = 0; p < n_estimate; p++) { 285ad540459SPierre Jolivet if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) n_found++; 2860e2ec84fSDave May } 2870e2ec84fSDave May 2880e2ec84fSDave May /* adjust size */ 2890e2ec84fSDave May if (mode == ADD_VALUES) { 2909566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &n_curr)); 2910e2ec84fSDave May n_new_est = n_curr + n_found; 2929566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, n_new_est, -1)); 2930e2ec84fSDave May } 2940e2ec84fSDave May if (mode == INSERT_VALUES) { 2950e2ec84fSDave May n_curr = 0; 2960e2ec84fSDave May n_new_est = n_found; 2979566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, n_new_est, -1)); 2980e2ec84fSDave May } 2990e2ec84fSDave May 3000e2ec84fSDave May /* initialize new coords, cell owners, pid */ 3019566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pos, &_coor)); 3029566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor)); 3039566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 3040e2ec84fSDave May n_found = 0; 3050e2ec84fSDave May for (p = 0; p < n_estimate; p++) { 3060e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 307ad540459SPierre Jolivet for (b = 0; b < bs; b++) swarm_coor[bs * (n_curr + n_found) + b] = PetscRealPart(_coor[bs * p + b]); 3080e2ec84fSDave May swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 3090e2ec84fSDave May n_found++; 3100e2ec84fSDave May } 3110e2ec84fSDave May } 3129566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 3139566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor)); 3149566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pos, &_coor)); 3150e2ec84fSDave May 3160e2ec84fSDave May if (redundant) { 31748a46eb9SPierre Jolivet if (rank > 0) PetscCall(PetscFree(my_coor)); 3180e2ec84fSDave May } 3199566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfcell)); 3209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pos)); 3213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3220e2ec84fSDave May } 3230e2ec84fSDave May 3240e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM, DM, DMSwarmPICLayoutType, PetscInt); 3250e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM, DM, DMSwarmPICLayoutType, PetscInt); 3260e2ec84fSDave May 3270e2ec84fSDave May /*@C 3280e2ec84fSDave May DMSwarmInsertPointsUsingCellDM - Insert point coordinates within each cell 3290e2ec84fSDave May 33020f4b53cSBarry Smith Not Collective 3310e2ec84fSDave May 33260225df5SJacob Faibussowitsch Input Parameters: 33320f4b53cSBarry Smith + dm - the `DMSWARM` 33420f4b53cSBarry Smith . layout_type - method used to fill each cell with the cell `DM` 3350e2ec84fSDave May - fill_param - parameter controlling how many points per cell are added (the meaning of this parameter is dependent on the layout type) 3360e2ec84fSDave May 3370e2ec84fSDave May Level: beginner 3380e2ec84fSDave May 3390e2ec84fSDave May Notes: 34020f4b53cSBarry Smith The insert method will reset any previous defined points within the `DMSWARM`. 341e7af74c8SDave May 34220f4b53cSBarry Smith When using a `DMDA` both 2D and 3D are supported for all layout types provided you are using `DMDA_ELEMENT_Q1`. 343e7af74c8SDave May 344a4e35b19SJacob Faibussowitsch When using a `DMPLEX` the following case are supported\: 34520f4b53cSBarry Smith .vb 346ea3d7275SDave May (i) DMSWARMPIC_LAYOUT_REGULAR: 2D (triangle), 347ea3d7275SDave May (ii) DMSWARMPIC_LAYOUT_GAUSS: 2D and 3D provided the cell is a tri/tet or a quad/hex, 348ea3d7275SDave May (iii) DMSWARMPIC_LAYOUT_SUBDIVISION: 2D and 3D for quad/hex and 2D tri. 34920f4b53cSBarry Smith .ve 3500e2ec84fSDave May 35120f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmPICLayoutType`, `DMSwarmSetType()`, `DMSwarmSetCellDM()`, `DMSwarmType` 3520e2ec84fSDave May @*/ 353d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm, DMSwarmPICLayoutType layout_type, PetscInt fill_param) 354d71ae5a4SJacob Faibussowitsch { 3550e2ec84fSDave May DM celldm; 3560e2ec84fSDave May PetscBool isDA, isPLEX; 3570e2ec84fSDave May 3580e2ec84fSDave May PetscFunctionBegin; 3590e2ec84fSDave May DMSWARMPICVALID(dm); 3609566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 3619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMDA, &isDA)); 3629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMPLEX, &isPLEX)); 3630e2ec84fSDave May if (isDA) { 3649566063dSJacob Faibussowitsch PetscCall(private_DMSwarmInsertPointsUsingCellDM_DA(dm, celldm, layout_type, fill_param)); 3650e2ec84fSDave May } else if (isPLEX) { 3669566063dSJacob Faibussowitsch PetscCall(private_DMSwarmInsertPointsUsingCellDM_PLEX(dm, celldm, layout_type, fill_param)); 3670e2ec84fSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only supported for cell DMs of type DMDA and DMPLEX"); 3683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3690e2ec84fSDave May } 3700e2ec84fSDave May 371431382f2SDave May extern PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM, DM, PetscInt, PetscReal *); 372431382f2SDave May 373431382f2SDave May /*@C 374431382f2SDave May DMSwarmSetPointCoordinatesCellwise - Insert point coordinates (defined over the reference cell) within each cell 375431382f2SDave May 37620f4b53cSBarry Smith Not Collective 377431382f2SDave May 37860225df5SJacob Faibussowitsch Input Parameters: 37920f4b53cSBarry Smith + dm - the `DMSWARM` 380431382f2SDave May . npoints - the number of points to insert in each cell 381431382f2SDave May - xi - the coordinates (defined in the local coordinate system for each cell) to insert 382431382f2SDave May 383431382f2SDave May Level: beginner 384431382f2SDave May 385431382f2SDave May Notes: 38620f4b53cSBarry Smith The method will reset any previous defined points within the `DMSWARM`. 38720f4b53cSBarry Smith Only supported for `DMPLEX`. If you are using a `DMDA` it is recommended to either use 38820f4b53cSBarry Smith `DMSwarmInsertPointsUsingCellDM()`, or extract and set the coordinates yourself the following code 38920f4b53cSBarry Smith .vb 39020f4b53cSBarry Smith PetscReal *coor; 39120f4b53cSBarry Smith DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 39220f4b53cSBarry Smith // user code to define the coordinates here 39320f4b53cSBarry Smith DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 39420f4b53cSBarry Smith .ve 395e7af74c8SDave May 39620f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmSetCellDM()`, `DMSwarmInsertPointsUsingCellDM()` 397431382f2SDave May @*/ 398d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinatesCellwise(DM dm, PetscInt npoints, PetscReal xi[]) 399d71ae5a4SJacob Faibussowitsch { 400431382f2SDave May DM celldm; 401431382f2SDave May PetscBool isDA, isPLEX; 402431382f2SDave May 4030e2ec84fSDave May PetscFunctionBegin; 404431382f2SDave May DMSWARMPICVALID(dm); 4059566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 4069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMDA, &isDA)); 4079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMPLEX, &isPLEX)); 40828b400f6SJacob Faibussowitsch PetscCheck(!isDA, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only supported for cell DMs of type DMPLEX. Recommended you use DMSwarmInsertPointsUsingCellDM()"); 409f7d195e4SLawrence Mitchell if (isPLEX) { 4109566063dSJacob Faibussowitsch PetscCall(private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm, celldm, npoints, xi)); 411431382f2SDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only supported for cell DMs of type DMDA and DMPLEX"); 4123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4130e2ec84fSDave May } 414431382f2SDave May 4150e2ec84fSDave May /*@C 416b799feefSDave May DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM 4170e2ec84fSDave May 41820f4b53cSBarry Smith Not Collective 4190e2ec84fSDave May 42060225df5SJacob Faibussowitsch Input Parameter: 42120f4b53cSBarry Smith . dm - the `DMSWARM` 4220e2ec84fSDave May 42360225df5SJacob Faibussowitsch Output Parameters: 42420f4b53cSBarry Smith + ncells - the number of cells in the cell `DM` (optional argument, pass `NULL` to ignore) 425b799feefSDave May - count - array of length ncells containing the number of points per cell 4260e2ec84fSDave May 4270e2ec84fSDave May Level: beginner 4280e2ec84fSDave May 4290e2ec84fSDave May Notes: 4300e2ec84fSDave May The array count is allocated internally and must be free'd by the user. 4310e2ec84fSDave May 43220f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmSetType()`, `DMSwarmSetCellDM()`, `DMSwarmType` 4330e2ec84fSDave May @*/ 434d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm, PetscInt *ncells, PetscInt **count) 435d71ae5a4SJacob Faibussowitsch { 436b799feefSDave May PetscBool isvalid; 437b799feefSDave May PetscInt nel; 438b799feefSDave May PetscInt *sum; 439b799feefSDave May 4400e2ec84fSDave May PetscFunctionBegin; 4419566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetIsValid(dm, &isvalid)); 442b799feefSDave May nel = 0; 443b799feefSDave May if (isvalid) { 444b799feefSDave May PetscInt e; 445b799feefSDave May 4469566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetSizes(dm, &nel, NULL)); 447b799feefSDave May 4489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nel, &sum)); 44948a46eb9SPierre Jolivet for (e = 0; e < nel; e++) PetscCall(DMSwarmSortGetNumberOfPointsPerCell(dm, e, &sum[e])); 450b799feefSDave May } else { 451b799feefSDave May DM celldm; 452b799feefSDave May PetscBool isda, isplex, isshell; 453b799feefSDave May PetscInt p, npoints; 454b799feefSDave May PetscInt *swarm_cellid; 455b799feefSDave May 456b799feefSDave May /* get the number of cells */ 4579566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 4589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMDA, &isda)); 4599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMPLEX, &isplex)); 4609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMSHELL, &isshell)); 461b799feefSDave May if (isda) { 462b799feefSDave May PetscInt _nel, _npe; 463b799feefSDave May const PetscInt *_element; 464b799feefSDave May 4659566063dSJacob Faibussowitsch PetscCall(DMDAGetElements(celldm, &_nel, &_npe, &_element)); 466b799feefSDave May nel = _nel; 4679566063dSJacob Faibussowitsch PetscCall(DMDARestoreElements(celldm, &_nel, &_npe, &_element)); 468b799feefSDave May } else if (isplex) { 469b799feefSDave May PetscInt ps, pe; 470b799feefSDave May 4719566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(celldm, 0, &ps, &pe)); 472b799feefSDave May nel = pe - ps; 473b799feefSDave May } else if (isshell) { 474b799feefSDave May PetscErrorCode (*method_DMShellGetNumberOfCells)(DM, PetscInt *); 475b799feefSDave May 4769566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)celldm, "DMGetNumberOfCells_C", &method_DMShellGetNumberOfCells)); 477b799feefSDave May if (method_DMShellGetNumberOfCells) { 4789566063dSJacob Faibussowitsch PetscCall(method_DMShellGetNumberOfCells(celldm, &nel)); 4799371c9d4SSatish Balay } else 4809371c9d4SSatish Balay SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot determine the number of cells for the DMSHELL object. User must provide a method via PetscObjectComposeFunction( (PetscObject)shelldm, \"DMGetNumberOfCells_C\", your_function_to_compute_number_of_cells);"); 481b799feefSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot determine the number of cells for a DM not of type DA, PLEX or SHELL"); 482b799feefSDave May 4839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nel, &sum)); 4849566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sum, nel)); 4859566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &npoints)); 4869566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 487b799feefSDave May for (p = 0; p < npoints; p++) { 488ad540459SPierre Jolivet if (swarm_cellid[p] != DMLOCATEPOINT_POINT_NOT_FOUND) sum[swarm_cellid[p]]++; 489b799feefSDave May } 4909566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 491b799feefSDave May } 492ad540459SPierre Jolivet if (ncells) *ncells = nel; 493b799feefSDave May *count = sum; 4943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4950e2ec84fSDave May } 49635b38c60SMatthew G. Knepley 49735b38c60SMatthew G. Knepley /*@ 49835b38c60SMatthew G. Knepley DMSwarmGetNumSpecies - Get the number of particle species 49935b38c60SMatthew G. Knepley 50020f4b53cSBarry Smith Not Collective 50135b38c60SMatthew G. Knepley 50260225df5SJacob Faibussowitsch Input Parameter: 50360225df5SJacob Faibussowitsch . sw - the `DMSWARM` 50435b38c60SMatthew G. Knepley 50560225df5SJacob Faibussowitsch Output Parameters: 50635b38c60SMatthew G. Knepley . Ns - the number of species 50735b38c60SMatthew G. Knepley 50835b38c60SMatthew G. Knepley Level: intermediate 50935b38c60SMatthew G. Knepley 51020f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmSetNumSpecies()`, `DMSwarmSetType()`, `DMSwarmType` 51135b38c60SMatthew G. Knepley @*/ 512d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetNumSpecies(DM sw, PetscInt *Ns) 513d71ae5a4SJacob Faibussowitsch { 51435b38c60SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 51535b38c60SMatthew G. Knepley 51635b38c60SMatthew G. Knepley PetscFunctionBegin; 51735b38c60SMatthew G. Knepley *Ns = swarm->Ns; 5183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51935b38c60SMatthew G. Knepley } 52035b38c60SMatthew G. Knepley 52135b38c60SMatthew G. Knepley /*@ 52235b38c60SMatthew G. Knepley DMSwarmSetNumSpecies - Set the number of particle species 52335b38c60SMatthew G. Knepley 52420f4b53cSBarry Smith Not Collective 52535b38c60SMatthew G. Knepley 52660225df5SJacob Faibussowitsch Input Parameters: 52760225df5SJacob Faibussowitsch + sw - the `DMSWARM` 52835b38c60SMatthew G. Knepley - Ns - the number of species 52935b38c60SMatthew G. Knepley 53035b38c60SMatthew G. Knepley Level: intermediate 53135b38c60SMatthew G. Knepley 53220f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmGetNumSpecies()`, `DMSwarmSetType()`, `DMSwarmType` 53335b38c60SMatthew G. Knepley @*/ 534d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetNumSpecies(DM sw, PetscInt Ns) 535d71ae5a4SJacob Faibussowitsch { 53635b38c60SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 53735b38c60SMatthew G. Knepley 53835b38c60SMatthew G. Knepley PetscFunctionBegin; 53935b38c60SMatthew G. Knepley swarm->Ns = Ns; 5403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54135b38c60SMatthew G. Knepley } 54235b38c60SMatthew G. Knepley 54335b38c60SMatthew G. Knepley /*@C 5446c5a79ebSMatthew G. Knepley DMSwarmGetCoordinateFunction - Get the function setting initial particle positions, if it exists 5456c5a79ebSMatthew G. Knepley 54620f4b53cSBarry Smith Not Collective 5476c5a79ebSMatthew G. Knepley 54860225df5SJacob Faibussowitsch Input Parameter: 54960225df5SJacob Faibussowitsch . sw - the `DMSWARM` 5506c5a79ebSMatthew G. Knepley 5516c5a79ebSMatthew G. Knepley Output Parameter: 552*8434afd1SBarry Smith . coordFunc - the function setting initial particle positions, or `NULL`, see `PetscSimplePointFn` for the calling sequence 5536c5a79ebSMatthew G. Knepley 5546c5a79ebSMatthew G. Knepley Level: intermediate 5556c5a79ebSMatthew G. Knepley 556*8434afd1SBarry Smith .seealso: `DMSWARM`, `DMSwarmSetCoordinateFunction()`, `DMSwarmGetVelocityFunction()`, `DMSwarmInitializeCoordinates()`, `PetscSimplePointFn` 5576c5a79ebSMatthew G. Knepley @*/ 558*8434afd1SBarry Smith PetscErrorCode DMSwarmGetCoordinateFunction(DM sw, PetscSimplePointFn **coordFunc) 559d71ae5a4SJacob Faibussowitsch { 5606c5a79ebSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 5616c5a79ebSMatthew G. Knepley 5626c5a79ebSMatthew G. Knepley PetscFunctionBegin; 5636c5a79ebSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 5644f572ea9SToby Isaac PetscAssertPointer(coordFunc, 2); 5656c5a79ebSMatthew G. Knepley *coordFunc = swarm->coordFunc; 5663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5676c5a79ebSMatthew G. Knepley } 5686c5a79ebSMatthew G. Knepley 5696c5a79ebSMatthew G. Knepley /*@C 5706c5a79ebSMatthew G. Knepley DMSwarmSetCoordinateFunction - Set the function setting initial particle positions 5716c5a79ebSMatthew G. Knepley 57220f4b53cSBarry Smith Not Collective 5736c5a79ebSMatthew G. Knepley 57460225df5SJacob Faibussowitsch Input Parameters: 57560225df5SJacob Faibussowitsch + sw - the `DMSWARM` 576*8434afd1SBarry Smith - coordFunc - the function setting initial particle positions, see `PetscSimplePointFn` for the calling sequence 5776c5a79ebSMatthew G. Knepley 5786c5a79ebSMatthew G. Knepley Level: intermediate 5796c5a79ebSMatthew G. Knepley 580*8434afd1SBarry Smith .seealso: `DMSWARM`, `DMSwarmGetCoordinateFunction()`, `DMSwarmSetVelocityFunction()`, `DMSwarmInitializeCoordinates()`, `PetscSimplePointFn` 5816c5a79ebSMatthew G. Knepley @*/ 582*8434afd1SBarry Smith PetscErrorCode DMSwarmSetCoordinateFunction(DM sw, PetscSimplePointFn *coordFunc) 583d71ae5a4SJacob Faibussowitsch { 5846c5a79ebSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 5856c5a79ebSMatthew G. Knepley 5866c5a79ebSMatthew G. Knepley PetscFunctionBegin; 5876c5a79ebSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 5886c5a79ebSMatthew G. Knepley PetscValidFunction(coordFunc, 2); 5896c5a79ebSMatthew G. Knepley swarm->coordFunc = coordFunc; 5903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5916c5a79ebSMatthew G. Knepley } 5926c5a79ebSMatthew G. Knepley 5936c5a79ebSMatthew G. Knepley /*@C 59460225df5SJacob Faibussowitsch DMSwarmGetVelocityFunction - Get the function setting initial particle velocities, if it exists 5956c5a79ebSMatthew G. Knepley 59620f4b53cSBarry Smith Not Collective 5976c5a79ebSMatthew G. Knepley 59860225df5SJacob Faibussowitsch Input Parameter: 59960225df5SJacob Faibussowitsch . sw - the `DMSWARM` 6006c5a79ebSMatthew G. Knepley 6016c5a79ebSMatthew G. Knepley Output Parameter: 602*8434afd1SBarry Smith . velFunc - the function setting initial particle velocities, or `NULL`, see `PetscSimplePointFn` for the calling sequence 6036c5a79ebSMatthew G. Knepley 6046c5a79ebSMatthew G. Knepley Level: intermediate 6056c5a79ebSMatthew G. Knepley 606*8434afd1SBarry Smith .seealso: `DMSWARM`, `DMSwarmSetVelocityFunction()`, `DMSwarmGetCoordinateFunction()`, `DMSwarmInitializeVelocities()`, `PetscSimplePointFn` 6076c5a79ebSMatthew G. Knepley @*/ 608*8434afd1SBarry Smith PetscErrorCode DMSwarmGetVelocityFunction(DM sw, PetscSimplePointFn **velFunc) 609d71ae5a4SJacob Faibussowitsch { 6106c5a79ebSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 6116c5a79ebSMatthew G. Knepley 6126c5a79ebSMatthew G. Knepley PetscFunctionBegin; 6136c5a79ebSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 6144f572ea9SToby Isaac PetscAssertPointer(velFunc, 2); 6156c5a79ebSMatthew G. Knepley *velFunc = swarm->velFunc; 6163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6176c5a79ebSMatthew G. Knepley } 6186c5a79ebSMatthew G. Knepley 6196c5a79ebSMatthew G. Knepley /*@C 6206c5a79ebSMatthew G. Knepley DMSwarmSetVelocityFunction - Set the function setting initial particle velocities 6216c5a79ebSMatthew G. Knepley 62220f4b53cSBarry Smith Not Collective 6236c5a79ebSMatthew G. Knepley 62460225df5SJacob Faibussowitsch Input Parameters: 625a4e35b19SJacob Faibussowitsch + sw - the `DMSWARM` 626*8434afd1SBarry Smith - velFunc - the function setting initial particle velocities, see `PetscSimplePointFn` for the calling sequence 6276c5a79ebSMatthew G. Knepley 6286c5a79ebSMatthew G. Knepley Level: intermediate 6296c5a79ebSMatthew G. Knepley 630*8434afd1SBarry Smith .seealso: `DMSWARM`, `DMSwarmGetVelocityFunction()`, `DMSwarmSetCoordinateFunction()`, `DMSwarmInitializeVelocities()`, `PetscSimplePointFn` 6316c5a79ebSMatthew G. Knepley @*/ 632*8434afd1SBarry Smith PetscErrorCode DMSwarmSetVelocityFunction(DM sw, PetscSimplePointFn *velFunc) 633d71ae5a4SJacob Faibussowitsch { 6346c5a79ebSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 6356c5a79ebSMatthew G. Knepley 6366c5a79ebSMatthew G. Knepley PetscFunctionBegin; 6376c5a79ebSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 6386c5a79ebSMatthew G. Knepley PetscValidFunction(velFunc, 2); 6396c5a79ebSMatthew G. Knepley swarm->velFunc = velFunc; 6403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6416c5a79ebSMatthew G. Knepley } 6426c5a79ebSMatthew G. Knepley 6436c5a79ebSMatthew G. Knepley /*@C 64435b38c60SMatthew G. Knepley DMSwarmComputeLocalSize - Compute the local number and distribution of particles based upon a density function 64535b38c60SMatthew G. Knepley 64620f4b53cSBarry Smith Not Collective 64735b38c60SMatthew G. Knepley 64835b38c60SMatthew G. Knepley Input Parameters: 64920f4b53cSBarry Smith + sw - The `DMSWARM` 65035b38c60SMatthew G. Knepley . N - The target number of particles 65135b38c60SMatthew G. Knepley - density - The density field for the particle layout, normalized to unity 65235b38c60SMatthew G. Knepley 65335b38c60SMatthew G. Knepley Level: advanced 65435b38c60SMatthew G. Knepley 65520f4b53cSBarry Smith Note: 65620f4b53cSBarry Smith One particle will be created for each species. 65720f4b53cSBarry Smith 65820f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSizeFromOptions()` 65935b38c60SMatthew G. Knepley @*/ 660d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmComputeLocalSize(DM sw, PetscInt N, PetscProbFunc density) 661d71ae5a4SJacob Faibussowitsch { 66235b38c60SMatthew G. Knepley DM dm; 66335b38c60SMatthew G. Knepley PetscQuadrature quad; 66435b38c60SMatthew G. Knepley const PetscReal *xq, *wq; 665ea7032a0SMatthew G. Knepley PetscReal *n_int; 666ea7032a0SMatthew G. Knepley PetscInt *npc_s, *cellid, Ni; 667ea7032a0SMatthew G. Knepley PetscReal gmin[3], gmax[3], xi0[3]; 668ea7032a0SMatthew G. Knepley PetscInt Ns, cStart, cEnd, c, dim, d, Nq, q, Np = 0, p, s; 66935b38c60SMatthew G. Knepley PetscBool simplex; 67035b38c60SMatthew G. Knepley 67135b38c60SMatthew G. Knepley PetscFunctionBegin; 6729566063dSJacob Faibussowitsch PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 6739566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(sw, &dm)); 6749566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 675ea7032a0SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, gmin, gmax)); 6769566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 6779566063dSJacob Faibussowitsch PetscCall(DMPlexIsSimplex(dm, &simplex)); 6786858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 6799566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscDTStroudConicalQuadrature(dim, 1, 5, -1.0, 1.0, &quad)); 6809566063dSJacob Faibussowitsch else PetscCall(PetscDTGaussTensorQuadrature(dim, 1, 5, -1.0, 1.0, &quad)); 6819566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, &xq, &wq)); 682ea7032a0SMatthew G. Knepley PetscCall(PetscCalloc2(Ns, &n_int, (cEnd - cStart) * Ns, &npc_s)); 68335b38c60SMatthew G. Knepley /* Integrate the density function to get the number of particles in each cell */ 68435b38c60SMatthew G. Knepley for (d = 0; d < dim; ++d) xi0[d] = -1.0; 68535b38c60SMatthew G. Knepley for (c = 0; c < cEnd - cStart; ++c) { 68635b38c60SMatthew G. Knepley const PetscInt cell = c + cStart; 687ea7032a0SMatthew G. Knepley PetscReal v0[3], J[9], invJ[9], detJ, detJp = 2. / (gmax[0] - gmin[0]), xr[3], den; 68835b38c60SMatthew G. Knepley 689ea7032a0SMatthew G. Knepley /*Have to transform quadrature points/weights to cell domain*/ 6909566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, invJ, &detJ)); 691ea7032a0SMatthew G. Knepley PetscCall(PetscArrayzero(n_int, Ns)); 69235b38c60SMatthew G. Knepley for (q = 0; q < Nq; ++q) { 69335b38c60SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, v0, J, &xq[q * dim], xr); 694ea7032a0SMatthew G. Knepley /* Have to transform mesh to domain of definition of PDF, [-1, 1], and weight PDF by |J|/2 */ 695ea7032a0SMatthew G. Knepley xr[0] = detJp * (xr[0] - gmin[0]) - 1.; 696ea7032a0SMatthew G. Knepley 697ea7032a0SMatthew G. Knepley for (s = 0; s < Ns; ++s) { 698ea7032a0SMatthew G. Knepley PetscCall(density(xr, NULL, &den)); 699ea7032a0SMatthew G. Knepley n_int[s] += (detJp * den) * (detJ * wq[q]) / (PetscReal)Ns; 70035b38c60SMatthew G. Knepley } 701ea7032a0SMatthew G. Knepley } 702ea7032a0SMatthew G. Knepley for (s = 0; s < Ns; ++s) { 703ea7032a0SMatthew G. Knepley Ni = N; 704ea7032a0SMatthew G. Knepley npc_s[c * Ns + s] += (PetscInt)(Ni * n_int[s]); 705ea7032a0SMatthew G. Knepley Np += npc_s[c * Ns + s]; 706ea7032a0SMatthew G. Knepley } 70735b38c60SMatthew G. Knepley } 7089566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&quad)); 7099566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(sw, Np, 0)); 7109566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, DMSwarmPICField_cellid, NULL, NULL, (void **)&cellid)); 71135b38c60SMatthew G. Knepley for (c = 0, p = 0; c < cEnd - cStart; ++c) { 712ea7032a0SMatthew G. Knepley for (s = 0; s < Ns; ++s) { 713ea7032a0SMatthew G. Knepley for (q = 0; q < npc_s[c * Ns + s]; ++q, ++p) cellid[p] = c; 714ea7032a0SMatthew G. Knepley } 71535b38c60SMatthew G. Knepley } 7169566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_cellid, NULL, NULL, (void **)&cellid)); 717ea7032a0SMatthew G. Knepley PetscCall(PetscFree2(n_int, npc_s)); 7183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71935b38c60SMatthew G. Knepley } 72035b38c60SMatthew G. Knepley 72135b38c60SMatthew G. Knepley /*@ 72235b38c60SMatthew G. Knepley DMSwarmComputeLocalSizeFromOptions - Compute the local number and distribution of particles based upon a density function determined by options 72335b38c60SMatthew G. Knepley 72420f4b53cSBarry Smith Not Collective 72535b38c60SMatthew G. Knepley 7262fe279fdSBarry Smith Input Parameter: 7272fe279fdSBarry Smith . sw - The `DMSWARM` 72835b38c60SMatthew G. Knepley 72935b38c60SMatthew G. Knepley Level: advanced 73035b38c60SMatthew G. Knepley 73120f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSize()` 73235b38c60SMatthew G. Knepley @*/ 733d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmComputeLocalSizeFromOptions(DM sw) 734d71ae5a4SJacob Faibussowitsch { 73535b38c60SMatthew G. Knepley PetscProbFunc pdf; 73635b38c60SMatthew G. Knepley const char *prefix; 7376c5a79ebSMatthew G. Knepley char funcname[PETSC_MAX_PATH_LEN]; 7386c5a79ebSMatthew G. Knepley PetscInt *N, Ns, dim, n; 7396c5a79ebSMatthew G. Knepley PetscBool flg; 7406c5a79ebSMatthew G. Knepley PetscMPIInt size, rank; 74135b38c60SMatthew G. Knepley 74235b38c60SMatthew G. Knepley PetscFunctionBegin; 7436c5a79ebSMatthew G. Knepley PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sw), &size)); 7446c5a79ebSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sw), &rank)); 7456c5a79ebSMatthew G. Knepley PetscCall(PetscCalloc1(size, &N)); 746d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)sw), "", "DMSwarm Options", "DMSWARM"); 7476c5a79ebSMatthew G. Knepley n = size; 7486c5a79ebSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_swarm_num_particles", "The target number of particles", "", N, &n, NULL)); 7496c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 7509566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_swarm_num_species", "The number of species", "DMSwarmSetNumSpecies", Ns, &Ns, &flg)); 7519566063dSJacob Faibussowitsch if (flg) PetscCall(DMSwarmSetNumSpecies(sw, Ns)); 7526c5a79ebSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_swarm_coordinate_function", "Function to determine particle coordinates", "DMSwarmSetCoordinateFunction", funcname, funcname, sizeof(funcname), &flg)); 753d0609cedSBarry Smith PetscOptionsEnd(); 7546c5a79ebSMatthew G. Knepley if (flg) { 755*8434afd1SBarry Smith PetscSimplePointFn *coordFunc; 75635b38c60SMatthew G. Knepley 7576c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 7586c5a79ebSMatthew G. Knepley PetscCall(PetscDLSym(NULL, funcname, (void **)&coordFunc)); 7596c5a79ebSMatthew G. Knepley PetscCheck(coordFunc, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONG, "Could not locate function %s", funcname); 7606c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 7616c5a79ebSMatthew G. Knepley PetscCall(DMSwarmSetLocalSizes(sw, N[rank] * Ns, 0)); 7626c5a79ebSMatthew G. Knepley PetscCall(DMSwarmSetCoordinateFunction(sw, coordFunc)); 7636c5a79ebSMatthew G. Knepley } else { 7649566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sw, &dim)); 7659566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sw, &prefix)); 7669566063dSJacob Faibussowitsch PetscCall(PetscProbCreateFromOptions(dim, prefix, "-dm_swarm_coordinate_density", &pdf, NULL, NULL)); 7676c5a79ebSMatthew G. Knepley PetscCall(DMSwarmComputeLocalSize(sw, N[rank], pdf)); 7686c5a79ebSMatthew G. Knepley } 7696c5a79ebSMatthew G. Knepley PetscCall(PetscFree(N)); 7703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77135b38c60SMatthew G. Knepley } 77235b38c60SMatthew G. Knepley 77335b38c60SMatthew G. Knepley /*@ 77435b38c60SMatthew G. Knepley DMSwarmInitializeCoordinates - Determine the initial coordinates of particles for a PIC method 77535b38c60SMatthew G. Knepley 77620f4b53cSBarry Smith Not Collective 77735b38c60SMatthew G. Knepley 77820f4b53cSBarry Smith Input Parameter: 77920f4b53cSBarry Smith . sw - The `DMSWARM` 78035b38c60SMatthew G. Knepley 78135b38c60SMatthew G. Knepley Level: advanced 78235b38c60SMatthew G. Knepley 78320f4b53cSBarry Smith Note: 78420f4b53cSBarry Smith Currently, we randomly place particles in their assigned cell 78520f4b53cSBarry Smith 78620f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSize()`, `DMSwarmInitializeVelocities()` 78735b38c60SMatthew G. Knepley @*/ 788d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeCoordinates(DM sw) 789d71ae5a4SJacob Faibussowitsch { 790*8434afd1SBarry Smith PetscSimplePointFn *coordFunc; 79135b38c60SMatthew G. Knepley PetscScalar *weight; 7926c5a79ebSMatthew G. Knepley PetscReal *x; 79335b38c60SMatthew G. Knepley PetscInt *species; 7946c5a79ebSMatthew G. Knepley void *ctx; 79535b38c60SMatthew G. Knepley PetscBool removePoints = PETSC_TRUE; 79635b38c60SMatthew G. Knepley PetscDataType dtype; 7976c5a79ebSMatthew G. Knepley PetscInt Np, p, Ns, dim, d, bs; 79835b38c60SMatthew G. Knepley 79935b38c60SMatthew G. Knepley PetscFunctionBeginUser; 8006c5a79ebSMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 8016c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 8029566063dSJacob Faibussowitsch PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 8036c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetCoordinateFunction(sw, &coordFunc)); 8046c5a79ebSMatthew G. Knepley 8056c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, &bs, &dtype, (void **)&x)); 8066c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", &bs, &dtype, (void **)&weight)); 8076c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species)); 8086c5a79ebSMatthew G. Knepley if (coordFunc) { 8096c5a79ebSMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx)); 8106c5a79ebSMatthew G. Knepley for (p = 0; p < Np; ++p) { 8116c5a79ebSMatthew G. Knepley PetscScalar X[3]; 8126c5a79ebSMatthew G. Knepley 8136c5a79ebSMatthew G. Knepley PetscCall((*coordFunc)(dim, 0., NULL, p, X, ctx)); 8146c5a79ebSMatthew G. Knepley for (d = 0; d < dim; ++d) x[p * dim + d] = PetscRealPart(X[d]); 8156c5a79ebSMatthew G. Knepley weight[p] = 1.0; 8166c5a79ebSMatthew G. Knepley species[p] = p % Ns; 8176c5a79ebSMatthew G. Knepley } 8186c5a79ebSMatthew G. Knepley } else { 8196c5a79ebSMatthew G. Knepley DM dm; 8206c5a79ebSMatthew G. Knepley PetscRandom rnd; 8216c5a79ebSMatthew G. Knepley PetscReal xi0[3]; 8226c5a79ebSMatthew G. Knepley PetscInt cStart, cEnd, c; 8236c5a79ebSMatthew G. Knepley 8249566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(sw, &dm)); 8259566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 826ea7032a0SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx)); 82735b38c60SMatthew G. Knepley 82835b38c60SMatthew G. Knepley /* Set particle position randomly in cell, set weights to 1 */ 8299566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd)); 8309566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0)); 8319566063dSJacob Faibussowitsch PetscCall(PetscRandomSetFromOptions(rnd)); 8329566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(sw)); 83335b38c60SMatthew G. Knepley for (d = 0; d < dim; ++d) xi0[d] = -1.0; 83435b38c60SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 83535b38c60SMatthew G. Knepley PetscReal v0[3], J[9], invJ[9], detJ; 83635b38c60SMatthew G. Knepley PetscInt *pidx, Npc, q; 83735b38c60SMatthew G. Knepley 8389566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx)); 8399566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ)); 84035b38c60SMatthew G. Knepley for (q = 0; q < Npc; ++q) { 84135b38c60SMatthew G. Knepley const PetscInt p = pidx[q]; 84235b38c60SMatthew G. Knepley PetscReal xref[3]; 84335b38c60SMatthew G. Knepley 8449566063dSJacob Faibussowitsch for (d = 0; d < dim; ++d) PetscCall(PetscRandomGetValueReal(rnd, &xref[d])); 84535b38c60SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, v0, J, xref, &x[p * dim]); 84635b38c60SMatthew G. Knepley 847ea7032a0SMatthew G. Knepley weight[p] = 1.0 / Np; 8486c5a79ebSMatthew G. Knepley species[p] = p % Ns; 84935b38c60SMatthew G. Knepley } 8509566063dSJacob Faibussowitsch PetscCall(PetscFree(pidx)); 85135b38c60SMatthew G. Knepley } 8529566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rnd)); 8539566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(sw)); 8546c5a79ebSMatthew G. Knepley } 8559566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 8566c5a79ebSMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight)); 8579566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species)); 8586c5a79ebSMatthew G. Knepley 8599566063dSJacob Faibussowitsch PetscCall(DMSwarmMigrate(sw, removePoints)); 8609566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(sw)); 8613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 86235b38c60SMatthew G. Knepley } 86335b38c60SMatthew G. Knepley 86435b38c60SMatthew G. Knepley /*@C 86535b38c60SMatthew G. Knepley DMSwarmInitializeVelocities - Set the initial velocities of particles using a distribution. 86635b38c60SMatthew G. Knepley 86720f4b53cSBarry Smith Collective 86835b38c60SMatthew G. Knepley 86935b38c60SMatthew G. Knepley Input Parameters: 87020f4b53cSBarry Smith + sw - The `DMSWARM` object 87135b38c60SMatthew G. Knepley . sampler - A function which uniformly samples the velocity PDF 87235b38c60SMatthew G. Knepley - v0 - The velocity scale for nondimensionalization for each species 87335b38c60SMatthew G. Knepley 87435b38c60SMatthew G. Knepley Level: advanced 87535b38c60SMatthew G. Knepley 87620f4b53cSBarry Smith Note: 87720f4b53cSBarry Smith If `v0` is zero for the first species, all velocities are set to zero. If it is zero for any other species, the effect will be to give that species zero velocity. 87820f4b53cSBarry Smith 87920f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSize()`, `DMSwarmInitializeCoordinates()`, `DMSwarmInitializeVelocitiesFromOptions()` 88035b38c60SMatthew G. Knepley @*/ 881d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeVelocities(DM sw, PetscProbFunc sampler, const PetscReal v0[]) 882d71ae5a4SJacob Faibussowitsch { 883*8434afd1SBarry Smith PetscSimplePointFn *velFunc; 88435b38c60SMatthew G. Knepley PetscReal *v; 88535b38c60SMatthew G. Knepley PetscInt *species; 8866c5a79ebSMatthew G. Knepley void *ctx; 88735b38c60SMatthew G. Knepley PetscInt dim, Np, p; 88835b38c60SMatthew G. Knepley 88935b38c60SMatthew G. Knepley PetscFunctionBegin; 8906c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetVelocityFunction(sw, &velFunc)); 89135b38c60SMatthew G. Knepley 8929566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sw, &dim)); 8939566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(sw, &Np)); 8949566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&v)); 8959566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species)); 8966c5a79ebSMatthew G. Knepley if (v0[0] == 0.) { 8976c5a79ebSMatthew G. Knepley PetscCall(PetscArrayzero(v, Np * dim)); 8986c5a79ebSMatthew G. Knepley } else if (velFunc) { 8996c5a79ebSMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx)); 9006c5a79ebSMatthew G. Knepley for (p = 0; p < Np; ++p) { 9016c5a79ebSMatthew G. Knepley PetscInt s = species[p], d; 9026c5a79ebSMatthew G. Knepley PetscScalar vel[3]; 9036c5a79ebSMatthew G. Knepley 9046c5a79ebSMatthew G. Knepley PetscCall((*velFunc)(dim, 0., NULL, p, vel, ctx)); 9056c5a79ebSMatthew G. Knepley for (d = 0; d < dim; ++d) v[p * dim + d] = (v0[s] / v0[0]) * PetscRealPart(vel[d]); 9066c5a79ebSMatthew G. Knepley } 9076c5a79ebSMatthew G. Knepley } else { 9086c5a79ebSMatthew G. Knepley PetscRandom rnd; 9096c5a79ebSMatthew G. Knepley 9106c5a79ebSMatthew G. Knepley PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)sw), &rnd)); 9116c5a79ebSMatthew G. Knepley PetscCall(PetscRandomSetInterval(rnd, 0, 1.)); 9126c5a79ebSMatthew G. Knepley PetscCall(PetscRandomSetFromOptions(rnd)); 9136c5a79ebSMatthew G. Knepley 91435b38c60SMatthew G. Knepley for (p = 0; p < Np; ++p) { 91535b38c60SMatthew G. Knepley PetscInt s = species[p], d; 91635b38c60SMatthew G. Knepley PetscReal a[3], vel[3]; 91735b38c60SMatthew G. Knepley 9189566063dSJacob Faibussowitsch for (d = 0; d < dim; ++d) PetscCall(PetscRandomGetValueReal(rnd, &a[d])); 9199566063dSJacob Faibussowitsch PetscCall(sampler(a, NULL, vel)); 920ad540459SPierre Jolivet for (d = 0; d < dim; ++d) v[p * dim + d] = (v0[s] / v0[0]) * vel[d]; 92135b38c60SMatthew G. Knepley } 9226c5a79ebSMatthew G. Knepley PetscCall(PetscRandomDestroy(&rnd)); 9236c5a79ebSMatthew G. Knepley } 9249566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&v)); 9259566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species)); 9263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92735b38c60SMatthew G. Knepley } 92835b38c60SMatthew G. Knepley 92935b38c60SMatthew G. Knepley /*@ 93035b38c60SMatthew G. Knepley DMSwarmInitializeVelocitiesFromOptions - Set the initial velocities of particles using a distribution determined from options. 93135b38c60SMatthew G. Knepley 93220f4b53cSBarry Smith Collective 93335b38c60SMatthew G. Knepley 93435b38c60SMatthew G. Knepley Input Parameters: 93520f4b53cSBarry Smith + sw - The `DMSWARM` object 93635b38c60SMatthew G. Knepley - v0 - The velocity scale for nondimensionalization for each species 93735b38c60SMatthew G. Knepley 93835b38c60SMatthew G. Knepley Level: advanced 93935b38c60SMatthew G. Knepley 94020f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSize()`, `DMSwarmInitializeCoordinates()`, `DMSwarmInitializeVelocities()` 94135b38c60SMatthew G. Knepley @*/ 942d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeVelocitiesFromOptions(DM sw, const PetscReal v0[]) 943d71ae5a4SJacob Faibussowitsch { 94435b38c60SMatthew G. Knepley PetscProbFunc sampler; 94535b38c60SMatthew G. Knepley PetscInt dim; 94635b38c60SMatthew G. Knepley const char *prefix; 9476c5a79ebSMatthew G. Knepley char funcname[PETSC_MAX_PATH_LEN]; 9486c5a79ebSMatthew G. Knepley PetscBool flg; 94935b38c60SMatthew G. Knepley 95035b38c60SMatthew G. Knepley PetscFunctionBegin; 951d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)sw), "", "DMSwarm Options", "DMSWARM"); 9526c5a79ebSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_swarm_velocity_function", "Function to determine particle velocities", "DMSwarmSetVelocityFunction", funcname, funcname, sizeof(funcname), &flg)); 953d0609cedSBarry Smith PetscOptionsEnd(); 9546c5a79ebSMatthew G. Knepley if (flg) { 955*8434afd1SBarry Smith PetscSimplePointFn *velFunc; 9566c5a79ebSMatthew G. Knepley 9576c5a79ebSMatthew G. Knepley PetscCall(PetscDLSym(NULL, funcname, (void **)&velFunc)); 9586c5a79ebSMatthew G. Knepley PetscCheck(velFunc, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONG, "Could not locate function %s", funcname); 9596c5a79ebSMatthew G. Knepley PetscCall(DMSwarmSetVelocityFunction(sw, velFunc)); 9606c5a79ebSMatthew G. Knepley } 9619566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sw, &dim)); 9629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sw, &prefix)); 9639566063dSJacob Faibussowitsch PetscCall(PetscProbCreateFromOptions(dim, prefix, "-dm_swarm_velocity_density", NULL, NULL, &sampler)); 9649566063dSJacob Faibussowitsch PetscCall(DMSwarmInitializeVelocities(sw, sampler, v0)); 9653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 96635b38c60SMatthew G. Knepley } 967