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> 6*35b38c60SMatthew G. Knepley #include <petscdt.h> 7279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h" 80e2ec84fSDave May 9*35b38c60SMatthew G. Knepley #include <petsc/private/petscfeimpl.h> /* For CoordinatesRefToReal() */ 10*35b38c60SMatthew G. Knepley 110e2ec84fSDave May /* 125627991aSBarry Smith Error checking to ensure the swarm type is correct and that a cell DM has been set 130e2ec84fSDave May */ 140e2ec84fSDave May #define DMSWARMPICVALID(dm) \ 150e2ec84fSDave May { \ 160e2ec84fSDave May DM_Swarm *_swarm = (DM_Swarm*)(dm)->data; \ 172c71b3e2SJacob Faibussowitsch PetscCheckFalse(_swarm->swarm_type != DMSWARM_PIC,PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Valid only for DMSwarm-PIC. You must call DMSwarmSetType(dm,DMSWARM_PIC)"); \ 180e2ec84fSDave May else \ 192c71b3e2SJacob Faibussowitsch PetscCheckFalse(!_swarm->dmcell,PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Valid only for DMSwarmPIC if the cell DM is set. You must call DMSwarmSetCellDM(dm,celldm)"); \ 200e2ec84fSDave May } 210e2ec84fSDave May 220e2ec84fSDave May /* Coordinate insertition/addition API */ 230e2ec84fSDave May /*@C 240e2ec84fSDave May DMSwarmSetPointsUniformCoordinates - Set point coordinates in a DMSwarm on a regular (ijk) grid 250e2ec84fSDave May 26d083f849SBarry Smith Collective on dm 270e2ec84fSDave May 280e2ec84fSDave May Input parameters: 290e2ec84fSDave May + dm - the DMSwarm 300e2ec84fSDave May . min - minimum coordinate values in the x, y, z directions (array of length dim) 310e2ec84fSDave May . max - maximum coordinate values in the x, y, z directions (array of length dim) 320e2ec84fSDave May . npoints - number of points in each spatial direction (array of length dim) 330e2ec84fSDave May - mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES) 340e2ec84fSDave May 350e2ec84fSDave May Level: beginner 360e2ec84fSDave May 370e2ec84fSDave May Notes: 380e2ec84fSDave May When using mode = INSERT_VALUES, this method will reset the number of particles in the DMSwarm 390e2ec84fSDave May to be npoints[0]*npoints[1] (2D) or npoints[0]*npoints[1]*npoints[2] (3D). When using mode = ADD_VALUES, 400e2ec84fSDave May new points will be appended to any already existing in the DMSwarm 410e2ec84fSDave May 420e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 430e2ec84fSDave May @*/ 440e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointsUniformCoordinates(DM dm,PetscReal min[],PetscReal max[],PetscInt npoints[],InsertMode mode) 450e2ec84fSDave May { 460e2ec84fSDave May PetscErrorCode ierr; 470e2ec84fSDave May PetscReal gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL}; 480e2ec84fSDave May PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 490e2ec84fSDave May PetscInt i,j,k,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found; 500e2ec84fSDave May Vec coorlocal; 510e2ec84fSDave May const PetscScalar *_coor; 520e2ec84fSDave May DM celldm; 530e2ec84fSDave May PetscReal dx[3]; 542e3d3761SDave May PetscInt _npoints[] = { 0, 0, 1 }; 550e2ec84fSDave May Vec pos; 560e2ec84fSDave May PetscScalar *_pos; 570e2ec84fSDave May PetscReal *swarm_coor; 580e2ec84fSDave May PetscInt *swarm_cellid; 590e2ec84fSDave May PetscSF sfcell = NULL; 600e2ec84fSDave May const PetscSFNode *LA_sfcell; 610e2ec84fSDave May 620e2ec84fSDave May PetscFunctionBegin; 630e2ec84fSDave May DMSWARMPICVALID(dm); 640e2ec84fSDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 650e2ec84fSDave May ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr); 660e2ec84fSDave May ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr); 670e2ec84fSDave May ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr); 680e2ec84fSDave May N = N / bs; 690e2ec84fSDave May ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 700e2ec84fSDave May for (i=0; i<N; i++) { 710e2ec84fSDave May for (b=0; b<bs; b++) { 72a5f152d1SDave May gmin[b] = PetscMin(gmin[b],PetscRealPart(_coor[bs*i+b])); 73a5f152d1SDave May gmax[b] = PetscMax(gmax[b],PetscRealPart(_coor[bs*i+b])); 740e2ec84fSDave May } 750e2ec84fSDave May } 760e2ec84fSDave May ierr = VecRestoreArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 770e2ec84fSDave May 780e2ec84fSDave May for (b=0; b<bs; b++) { 7971844bb8SDave May if (npoints[b] > 1) { 800e2ec84fSDave May dx[b] = (max[b] - min[b])/((PetscReal)(npoints[b]-1)); 8171844bb8SDave May } else { 8271844bb8SDave May dx[b] = 0.0; 8371844bb8SDave May } 842e3d3761SDave May _npoints[b] = npoints[b]; 850e2ec84fSDave May } 860e2ec84fSDave May 870e2ec84fSDave May /* determine number of points living in the bounding box */ 880e2ec84fSDave May n_estimate = 0; 892e3d3761SDave May for (k=0; k<_npoints[2]; k++) { 902e3d3761SDave May for (j=0; j<_npoints[1]; j++) { 912e3d3761SDave May for (i=0; i<_npoints[0]; i++) { 920e2ec84fSDave May PetscReal xp[] = {0.0,0.0,0.0}; 930e2ec84fSDave May PetscInt ijk[3]; 940e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 950e2ec84fSDave May 960e2ec84fSDave May ijk[0] = i; 970e2ec84fSDave May ijk[1] = j; 980e2ec84fSDave May ijk[2] = k; 990e2ec84fSDave May for (b=0; b<bs; b++) { 1000e2ec84fSDave May xp[b] = min[b] + ijk[b] * dx[b]; 1010e2ec84fSDave May } 1020e2ec84fSDave May for (b=0; b<bs; b++) { 1030e2ec84fSDave May if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; } 1040e2ec84fSDave May if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; } 1050e2ec84fSDave May } 1060e2ec84fSDave May if (point_inside) { n_estimate++; } 1070e2ec84fSDave May } 1080e2ec84fSDave May } 1090e2ec84fSDave May } 1100e2ec84fSDave May 1110e2ec84fSDave May /* create candidate list */ 112c28a3c15SDave May ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr); 1130e2ec84fSDave May ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr); 1140e2ec84fSDave May ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr); 1150e2ec84fSDave May ierr = VecSetFromOptions(pos);CHKERRQ(ierr); 1160e2ec84fSDave May ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr); 1170e2ec84fSDave May 1180e2ec84fSDave May n_estimate = 0; 1192e3d3761SDave May for (k=0; k<_npoints[2]; k++) { 1202e3d3761SDave May for (j=0; j<_npoints[1]; j++) { 1212e3d3761SDave May for (i=0; i<_npoints[0]; i++) { 1220e2ec84fSDave May PetscReal xp[] = {0.0,0.0,0.0}; 1230e2ec84fSDave May PetscInt ijk[3]; 1240e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 1250e2ec84fSDave May 1260e2ec84fSDave May ijk[0] = i; 1270e2ec84fSDave May ijk[1] = j; 1280e2ec84fSDave May ijk[2] = k; 1290e2ec84fSDave May for (b=0; b<bs; b++) { 1300e2ec84fSDave May xp[b] = min[b] + ijk[b] * dx[b]; 1310e2ec84fSDave May } 1320e2ec84fSDave May for (b=0; b<bs; b++) { 1330e2ec84fSDave May if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; } 1340e2ec84fSDave May if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; } 1350e2ec84fSDave May } 1360e2ec84fSDave May if (point_inside) { 1370e2ec84fSDave May for (b=0; b<bs; b++) { 1380e2ec84fSDave May _pos[bs*n_estimate+b] = xp[b]; 1390e2ec84fSDave May } 1400e2ec84fSDave May n_estimate++; 1410e2ec84fSDave May } 1420e2ec84fSDave May } 1430e2ec84fSDave May } 1440e2ec84fSDave May } 1450e2ec84fSDave May ierr = VecRestoreArray(pos,&_pos);CHKERRQ(ierr); 1460e2ec84fSDave May 1470e2ec84fSDave May /* locate points */ 1480e2ec84fSDave May ierr = DMLocatePoints(celldm,pos,DM_POINTLOCATION_NONE,&sfcell);CHKERRQ(ierr); 1490e2ec84fSDave May ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr); 1500e2ec84fSDave May n_found = 0; 1510e2ec84fSDave May for (p=0; p<n_estimate; p++) { 1520e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 1530e2ec84fSDave May n_found++; 1540e2ec84fSDave May } 1550e2ec84fSDave May } 1560e2ec84fSDave May 1570e2ec84fSDave May /* adjust size */ 1580e2ec84fSDave May if (mode == ADD_VALUES) { 1590e2ec84fSDave May ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr); 1600e2ec84fSDave May n_new_est = n_curr + n_found; 1610e2ec84fSDave May ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 1620e2ec84fSDave May } 1630e2ec84fSDave May if (mode == INSERT_VALUES) { 1640e2ec84fSDave May n_curr = 0; 1650e2ec84fSDave May n_new_est = n_found; 1660e2ec84fSDave May ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 1670e2ec84fSDave May } 1680e2ec84fSDave May 1690e2ec84fSDave May /* initialize new coords, cell owners, pid */ 1700e2ec84fSDave May ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr); 1710e2ec84fSDave May ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 1720e2ec84fSDave May ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 1730e2ec84fSDave May n_found = 0; 1740e2ec84fSDave May for (p=0; p<n_estimate; p++) { 1750e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 1760e2ec84fSDave May for (b=0; b<bs; b++) { 1770ca99263SDave May swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]); 1780e2ec84fSDave May } 1790e2ec84fSDave May swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 1800e2ec84fSDave May n_found++; 1810e2ec84fSDave May } 1820e2ec84fSDave May } 1830e2ec84fSDave May ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 1840e2ec84fSDave May ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 1850e2ec84fSDave May ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr); 1860e2ec84fSDave May 1870e2ec84fSDave May ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr); 1880e2ec84fSDave May ierr = VecDestroy(&pos);CHKERRQ(ierr); 1890e2ec84fSDave May PetscFunctionReturn(0); 1900e2ec84fSDave May } 1910e2ec84fSDave May 1920e2ec84fSDave May /*@C 1930e2ec84fSDave May DMSwarmSetPointCoordinates - Set point coordinates in a DMSwarm from a user defined list 1940e2ec84fSDave May 195d083f849SBarry Smith Collective on dm 1960e2ec84fSDave May 1970e2ec84fSDave May Input parameters: 1980e2ec84fSDave May + dm - the DMSwarm 1990e2ec84fSDave May . npoints - the number of points to insert 2000e2ec84fSDave May . coor - the coordinate values 2010e2ec84fSDave May . 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 2020e2ec84fSDave May - mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES) 2030e2ec84fSDave May 2040e2ec84fSDave May Level: beginner 2050e2ec84fSDave May 2060e2ec84fSDave May Notes: 2070e2ec84fSDave May If the user has specified redundant = PETSC_FALSE, the cell DM will attempt to locate the coordinates provided by coor[] within 2080e2ec84fSDave May its sub-domain. If they any values within coor[] are not located in the sub-domain, they will be ignored and will not get 2090e2ec84fSDave May added to the DMSwarm. 2100e2ec84fSDave May 2110e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType, DMSwarmSetPointsUniformCoordinates() 2120e2ec84fSDave May @*/ 2130e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinates(DM dm,PetscInt npoints,PetscReal coor[],PetscBool redundant,InsertMode mode) 2140e2ec84fSDave May { 2150e2ec84fSDave May PetscErrorCode ierr; 2160e2ec84fSDave May PetscReal gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL}; 2170e2ec84fSDave May PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 2180e2ec84fSDave May PetscInt i,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found; 2190e2ec84fSDave May Vec coorlocal; 2200e2ec84fSDave May const PetscScalar *_coor; 2210e2ec84fSDave May DM celldm; 2220e2ec84fSDave May Vec pos; 2230e2ec84fSDave May PetscScalar *_pos; 2240e2ec84fSDave May PetscReal *swarm_coor; 2250e2ec84fSDave May PetscInt *swarm_cellid; 2260e2ec84fSDave May PetscSF sfcell = NULL; 2270e2ec84fSDave May const PetscSFNode *LA_sfcell; 2280e2ec84fSDave May PetscReal *my_coor; 2290e2ec84fSDave May PetscInt my_npoints; 2300e2ec84fSDave May PetscMPIInt rank; 2310e2ec84fSDave May MPI_Comm comm; 2320e2ec84fSDave May 2330e2ec84fSDave May PetscFunctionBegin; 2340e2ec84fSDave May DMSWARMPICVALID(dm); 2350e2ec84fSDave May ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 236ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 2370e2ec84fSDave May 2380e2ec84fSDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 2390e2ec84fSDave May ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr); 2400e2ec84fSDave May ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr); 2410e2ec84fSDave May ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr); 2420e2ec84fSDave May N = N / bs; 2430e2ec84fSDave May ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 2440e2ec84fSDave May for (i=0; i<N; i++) { 2450e2ec84fSDave May for (b=0; b<bs; b++) { 246a5f152d1SDave May gmin[b] = PetscMin(gmin[b],PetscRealPart(_coor[bs*i+b])); 247a5f152d1SDave May gmax[b] = PetscMax(gmax[b],PetscRealPart(_coor[bs*i+b])); 2480e2ec84fSDave May } 2490e2ec84fSDave May } 2500e2ec84fSDave May ierr = VecRestoreArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 2510e2ec84fSDave May 2520e2ec84fSDave May /* broadcast points from rank 0 if requested */ 2530e2ec84fSDave May if (redundant) { 2540e2ec84fSDave May my_npoints = npoints; 255ffc4695bSBarry Smith ierr = MPI_Bcast(&my_npoints,1,MPIU_INT,0,comm);CHKERRMPI(ierr); 2560e2ec84fSDave May 2570e2ec84fSDave May if (rank > 0) { /* allocate space */ 25871844bb8SDave May ierr = PetscMalloc1(bs*my_npoints,&my_coor);CHKERRQ(ierr); 2590e2ec84fSDave May } else { 2600e2ec84fSDave May my_coor = coor; 2610e2ec84fSDave May } 262ffc4695bSBarry Smith ierr = MPI_Bcast(my_coor,bs*my_npoints,MPIU_REAL,0,comm);CHKERRMPI(ierr); 2630e2ec84fSDave May } else { 2640e2ec84fSDave May my_npoints = npoints; 2650e2ec84fSDave May my_coor = coor; 2660e2ec84fSDave May } 2670e2ec84fSDave May 2680e2ec84fSDave May /* determine the number of points living in the bounding box */ 2690e2ec84fSDave May n_estimate = 0; 2700e2ec84fSDave May for (i=0; i<my_npoints; i++) { 2710e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 2720e2ec84fSDave May 2730e2ec84fSDave May for (b=0; b<bs; b++) { 2740e2ec84fSDave May if (my_coor[bs*i+b] < gmin[b]) { point_inside = PETSC_FALSE; } 2750e2ec84fSDave May if (my_coor[bs*i+b] > gmax[b]) { point_inside = PETSC_FALSE; } 2760e2ec84fSDave May } 2770e2ec84fSDave May if (point_inside) { n_estimate++; } 2780e2ec84fSDave May } 2790e2ec84fSDave May 2800e2ec84fSDave May /* create candidate list */ 281c28a3c15SDave May ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr); 2820e2ec84fSDave May ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr); 2830e2ec84fSDave May ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr); 2840e2ec84fSDave May ierr = VecSetFromOptions(pos);CHKERRQ(ierr); 2850e2ec84fSDave May ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr); 2860e2ec84fSDave May 2870e2ec84fSDave May n_estimate = 0; 2880e2ec84fSDave May for (i=0; i<my_npoints; i++) { 2890e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 2900e2ec84fSDave May 2910e2ec84fSDave May for (b=0; b<bs; b++) { 2920e2ec84fSDave May if (my_coor[bs*i+b] < gmin[b]) { point_inside = PETSC_FALSE; } 2930e2ec84fSDave May if (my_coor[bs*i+b] > gmax[b]) { point_inside = PETSC_FALSE; } 2940e2ec84fSDave May } 2950e2ec84fSDave May if (point_inside) { 2960e2ec84fSDave May for (b=0; b<bs; b++) { 2970e2ec84fSDave May _pos[bs*n_estimate+b] = my_coor[bs*i+b]; 2980e2ec84fSDave May } 2990e2ec84fSDave May n_estimate++; 3000e2ec84fSDave May } 3010e2ec84fSDave May } 3020e2ec84fSDave May ierr = VecRestoreArray(pos,&_pos);CHKERRQ(ierr); 3030e2ec84fSDave May 3040e2ec84fSDave May /* locate points */ 3050e2ec84fSDave May ierr = DMLocatePoints(celldm,pos,DM_POINTLOCATION_NONE,&sfcell);CHKERRQ(ierr); 3060e2ec84fSDave May 3070e2ec84fSDave May ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr); 3080e2ec84fSDave May n_found = 0; 3090e2ec84fSDave May for (p=0; p<n_estimate; p++) { 3100e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 3110e2ec84fSDave May n_found++; 3120e2ec84fSDave May } 3130e2ec84fSDave May } 3140e2ec84fSDave May 3150e2ec84fSDave May /* adjust size */ 3160e2ec84fSDave May if (mode == ADD_VALUES) { 3170e2ec84fSDave May ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr); 3180e2ec84fSDave May n_new_est = n_curr + n_found; 3190e2ec84fSDave May ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 3200e2ec84fSDave May } 3210e2ec84fSDave May if (mode == INSERT_VALUES) { 3220e2ec84fSDave May n_curr = 0; 3230e2ec84fSDave May n_new_est = n_found; 3240e2ec84fSDave May ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 3250e2ec84fSDave May } 3260e2ec84fSDave May 3270e2ec84fSDave May /* initialize new coords, cell owners, pid */ 3280e2ec84fSDave May ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr); 3290e2ec84fSDave May ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 3300e2ec84fSDave May ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 3310e2ec84fSDave May n_found = 0; 3320e2ec84fSDave May for (p=0; p<n_estimate; p++) { 3330e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 3340e2ec84fSDave May for (b=0; b<bs; b++) { 3350ca99263SDave May swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]); 3360e2ec84fSDave May } 3370e2ec84fSDave May swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 3380e2ec84fSDave May n_found++; 3390e2ec84fSDave May } 3400e2ec84fSDave May } 3410e2ec84fSDave May ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 3420e2ec84fSDave May ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 3430e2ec84fSDave May ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr); 3440e2ec84fSDave May 3450e2ec84fSDave May if (redundant) { 3460e2ec84fSDave May if (rank > 0) { 3470e2ec84fSDave May ierr = PetscFree(my_coor);CHKERRQ(ierr); 3480e2ec84fSDave May } 3490e2ec84fSDave May } 3500e2ec84fSDave May ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr); 3510e2ec84fSDave May ierr = VecDestroy(&pos);CHKERRQ(ierr); 3520e2ec84fSDave May PetscFunctionReturn(0); 3530e2ec84fSDave May } 3540e2ec84fSDave May 3550e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM,DM,DMSwarmPICLayoutType,PetscInt); 3560e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM,DM,DMSwarmPICLayoutType,PetscInt); 3570e2ec84fSDave May 3580e2ec84fSDave May /*@C 3590e2ec84fSDave May DMSwarmInsertPointsUsingCellDM - Insert point coordinates within each cell 3600e2ec84fSDave May 3610e2ec84fSDave May Not collective 3620e2ec84fSDave May 3630e2ec84fSDave May Input parameters: 3640e2ec84fSDave May + dm - the DMSwarm 3650e2ec84fSDave May . layout_type - method used to fill each cell with the cell DM 3660e2ec84fSDave May - fill_param - parameter controlling how many points per cell are added (the meaning of this parameter is dependent on the layout type) 3670e2ec84fSDave May 3680e2ec84fSDave May Level: beginner 3690e2ec84fSDave May 3700e2ec84fSDave May Notes: 371e7af74c8SDave May 372e7af74c8SDave May The insert method will reset any previous defined points within the DMSwarm. 373e7af74c8SDave May 374e7af74c8SDave May When using a DMDA both 2D and 3D are supported for all layout types provided you are using DMDA_ELEMENT_Q1. 375e7af74c8SDave May 376e7af74c8SDave May When using a DMPLEX the following case are supported: 377ea3d7275SDave May (i) DMSWARMPIC_LAYOUT_REGULAR: 2D (triangle), 378ea3d7275SDave May (ii) DMSWARMPIC_LAYOUT_GAUSS: 2D and 3D provided the cell is a tri/tet or a quad/hex, 379ea3d7275SDave May (iii) DMSWARMPIC_LAYOUT_SUBDIVISION: 2D and 3D for quad/hex and 2D tri. 3800e2ec84fSDave May 3810e2ec84fSDave May .seealso: DMSwarmPICLayoutType, DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 3820e2ec84fSDave May @*/ 3830e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm,DMSwarmPICLayoutType layout_type,PetscInt fill_param) 3840e2ec84fSDave May { 3850e2ec84fSDave May PetscErrorCode ierr; 3860e2ec84fSDave May DM celldm; 3870e2ec84fSDave May PetscBool isDA,isPLEX; 3880e2ec84fSDave May 3890e2ec84fSDave May PetscFunctionBegin; 3900e2ec84fSDave May DMSWARMPICVALID(dm); 3910e2ec84fSDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 3920e2ec84fSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 3930e2ec84fSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 3940e2ec84fSDave May if (isDA) { 3950e2ec84fSDave May ierr = private_DMSwarmInsertPointsUsingCellDM_DA(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 3960e2ec84fSDave May } else if (isPLEX) { 3970e2ec84fSDave May ierr = private_DMSwarmInsertPointsUsingCellDM_PLEX(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 3980e2ec84fSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 3990e2ec84fSDave May PetscFunctionReturn(0); 4000e2ec84fSDave May } 4010e2ec84fSDave May 402431382f2SDave May extern PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM,DM,PetscInt,PetscReal*); 403431382f2SDave May 404431382f2SDave May /*@C 405431382f2SDave May DMSwarmSetPointCoordinatesCellwise - Insert point coordinates (defined over the reference cell) within each cell 406431382f2SDave May 407431382f2SDave May Not collective 408431382f2SDave May 409431382f2SDave May Input parameters: 410431382f2SDave May + dm - the DMSwarm 411431382f2SDave May . celldm - the cell DM 412431382f2SDave May . npoints - the number of points to insert in each cell 413431382f2SDave May - xi - the coordinates (defined in the local coordinate system for each cell) to insert 414431382f2SDave May 415431382f2SDave May Level: beginner 416431382f2SDave May 417431382f2SDave May Notes: 418431382f2SDave May The method will reset any previous defined points within the DMSwarm. 419ea3d7275SDave May Only supported for DMPLEX. If you are using a DMDA it is recommended to either use 420e7af74c8SDave May DMSwarmInsertPointsUsingCellDM(), or extract and set the coordinates yourself the following code 421e7af74c8SDave May 422e7af74c8SDave May $ PetscReal *coor; 423e7af74c8SDave May $ DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 424e7af74c8SDave May $ // user code to define the coordinates here 425e7af74c8SDave May $ DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 426431382f2SDave May 427431382f2SDave May .seealso: DMSwarmSetCellDM(), DMSwarmInsertPointsUsingCellDM() 428431382f2SDave May @*/ 429431382f2SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinatesCellwise(DM dm,PetscInt npoints,PetscReal xi[]) 4300e2ec84fSDave May { 431431382f2SDave May PetscErrorCode ierr; 432431382f2SDave May DM celldm; 433431382f2SDave May PetscBool isDA,isPLEX; 434431382f2SDave May 4350e2ec84fSDave May PetscFunctionBegin; 436431382f2SDave May DMSWARMPICVALID(dm); 437431382f2SDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 438431382f2SDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 439431382f2SDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 4402c71b3e2SJacob Faibussowitsch PetscCheckFalse(isDA,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMPLEX. Recommended you use DMSwarmInsertPointsUsingCellDM()"); 441431382f2SDave May else if (isPLEX) { 442431382f2SDave May ierr = private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm,celldm,npoints,xi);CHKERRQ(ierr); 443431382f2SDave May } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 4440e2ec84fSDave May PetscFunctionReturn(0); 4450e2ec84fSDave May } 446431382f2SDave May 4470e2ec84fSDave May /* Field projection API */ 44877048351SPatrick Sanan extern PetscErrorCode private_DMSwarmProjectFields_DA(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DMSwarmDataField dfield[],Vec vecs[]); 44977048351SPatrick Sanan extern PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DMSwarmDataField dfield[],Vec vecs[]); 45094f7d2dcSDave May 45194f7d2dcSDave May /*@C 45294f7d2dcSDave May DMSwarmProjectFields - Project a set of swarm fields onto the cell DM 45394f7d2dcSDave May 454d083f849SBarry Smith Collective on dm 45594f7d2dcSDave May 45694f7d2dcSDave May Input parameters: 45794f7d2dcSDave May + dm - the DMSwarm 45894f7d2dcSDave May . nfields - the number of swarm fields to project 45994f7d2dcSDave May . fieldnames - the textual names of the swarm fields to project 46094f7d2dcSDave May . fields - an array of Vec's of length nfields 46194f7d2dcSDave May - reuse - flag indicating whether the array and contents of fields should be re-used or internally allocated 46294f7d2dcSDave May 46394f7d2dcSDave May Currently, the only available projection method consists of 46494f7d2dcSDave May phi_i = \sum_{p=0}^{np} N_i(x_p) phi_p dJ / \sum_{p=0}^{np} N_i(x_p) dJ 46594f7d2dcSDave May where phi_p is the swarm field at point p, 46694f7d2dcSDave May N_i() is the cell DM basis function at vertex i, 46794f7d2dcSDave May dJ is the determinant of the cell Jacobian and 46894f7d2dcSDave May phi_i is the projected vertex value of the field phi. 46994f7d2dcSDave May 47094f7d2dcSDave May Level: beginner 47194f7d2dcSDave May 47294f7d2dcSDave May Notes: 473e7af74c8SDave May 474e7af74c8SDave May If reuse = PETSC_FALSE, this function will allocate the array of Vec's, and each individual Vec. 47594f7d2dcSDave May The user is responsible for destroying both the array and the individual Vec objects. 476e7af74c8SDave May 477e7af74c8SDave May Only swarm fields registered with data type = PETSC_REAL can be projected onto the cell DM. 478e7af74c8SDave May 479e7af74c8SDave May Only swarm fields of block size = 1 can currently be projected. 480e7af74c8SDave May 481e7af74c8SDave May The only projection methods currently only support the DA (2D) and PLEX (triangles 2D). 48294f7d2dcSDave May 48394f7d2dcSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 48494f7d2dcSDave May @*/ 48594f7d2dcSDave May PETSC_EXTERN PetscErrorCode DMSwarmProjectFields(DM dm,PetscInt nfields,const char *fieldnames[],Vec **fields,PetscBool reuse) 4860e2ec84fSDave May { 48794f7d2dcSDave May DM_Swarm *swarm = (DM_Swarm*)dm->data; 48877048351SPatrick Sanan DMSwarmDataField *gfield; 48994f7d2dcSDave May DM celldm; 49094f7d2dcSDave May PetscBool isDA,isPLEX; 49194f7d2dcSDave May Vec *vecs; 49294f7d2dcSDave May PetscInt f,nvecs; 49394f7d2dcSDave May PetscInt project_type = 0; 49494f7d2dcSDave May PetscErrorCode ierr; 49594f7d2dcSDave May 4960e2ec84fSDave May PetscFunctionBegin; 49794f7d2dcSDave May DMSWARMPICVALID(dm); 49894f7d2dcSDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 49994f7d2dcSDave May ierr = PetscMalloc1(nfields,&gfield);CHKERRQ(ierr); 50094f7d2dcSDave May nvecs = 0; 50194f7d2dcSDave May for (f=0; f<nfields; f++) { 50277048351SPatrick Sanan ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldnames[f],&gfield[f]);CHKERRQ(ierr); 5032c71b3e2SJacob Faibussowitsch PetscCheckFalse(gfield[f]->petsc_type != PETSC_REAL,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields using a data type = PETSC_REAL"); 5042c71b3e2SJacob Faibussowitsch PetscCheckFalse(gfield[f]->bs != 1,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields with block size = 1"); 50594f7d2dcSDave May nvecs += gfield[f]->bs; 50694f7d2dcSDave May } 50794f7d2dcSDave May if (!reuse) { 50894f7d2dcSDave May ierr = PetscMalloc1(nvecs,&vecs);CHKERRQ(ierr); 50994f7d2dcSDave May for (f=0; f<nvecs; f++) { 51094f7d2dcSDave May ierr = DMCreateGlobalVector(celldm,&vecs[f]);CHKERRQ(ierr); 51194f7d2dcSDave May ierr = PetscObjectSetName((PetscObject)vecs[f],gfield[f]->name);CHKERRQ(ierr); 51294f7d2dcSDave May } 51394f7d2dcSDave May } else { 51494f7d2dcSDave May vecs = *fields; 51594f7d2dcSDave May } 51694f7d2dcSDave May 51794f7d2dcSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 51894f7d2dcSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 51994f7d2dcSDave May if (isDA) { 52094f7d2dcSDave May ierr = private_DMSwarmProjectFields_DA(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); 52194f7d2dcSDave May } else if (isPLEX) { 52294f7d2dcSDave May ierr = private_DMSwarmProjectFields_PLEX(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); 52394f7d2dcSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 52494f7d2dcSDave May 52594f7d2dcSDave May ierr = PetscFree(gfield);CHKERRQ(ierr); 52694f7d2dcSDave May if (!reuse) { 52794f7d2dcSDave May *fields = vecs; 52894f7d2dcSDave May } 5290e2ec84fSDave May PetscFunctionReturn(0); 5300e2ec84fSDave May } 5310e2ec84fSDave May 5320e2ec84fSDave May /*@C 533b799feefSDave May DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM 5340e2ec84fSDave May 5350e2ec84fSDave May Not collective 5360e2ec84fSDave May 5370e2ec84fSDave May Input parameter: 5380e2ec84fSDave May . dm - the DMSwarm 5390e2ec84fSDave May 5400e2ec84fSDave May Output parameters: 5410e2ec84fSDave May + ncells - the number of cells in the cell DM (optional argument, pass NULL to ignore) 542b799feefSDave May - count - array of length ncells containing the number of points per cell 5430e2ec84fSDave May 5440e2ec84fSDave May Level: beginner 5450e2ec84fSDave May 5460e2ec84fSDave May Notes: 5470e2ec84fSDave May The array count is allocated internally and must be free'd by the user. 5480e2ec84fSDave May 5490e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 5500e2ec84fSDave May @*/ 5510e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm,PetscInt *ncells,PetscInt **count) 5520e2ec84fSDave May { 553b799feefSDave May PetscErrorCode ierr; 554b799feefSDave May PetscBool isvalid; 555b799feefSDave May PetscInt nel; 556b799feefSDave May PetscInt *sum; 557b799feefSDave May 5580e2ec84fSDave May PetscFunctionBegin; 559b799feefSDave May ierr = DMSwarmSortGetIsValid(dm,&isvalid);CHKERRQ(ierr); 560b799feefSDave May nel = 0; 561b799feefSDave May if (isvalid) { 562b799feefSDave May PetscInt e; 563b799feefSDave May 564b799feefSDave May ierr = DMSwarmSortGetSizes(dm,&nel,NULL);CHKERRQ(ierr); 565b799feefSDave May 566b799feefSDave May ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 567b799feefSDave May for (e=0; e<nel; e++) { 568b799feefSDave May ierr = DMSwarmSortGetNumberOfPointsPerCell(dm,e,&sum[e]);CHKERRQ(ierr); 569b799feefSDave May } 570b799feefSDave May } else { 571b799feefSDave May DM celldm; 572b799feefSDave May PetscBool isda,isplex,isshell; 573b799feefSDave May PetscInt p,npoints; 574b799feefSDave May PetscInt *swarm_cellid; 575b799feefSDave May 576b799feefSDave May /* get the number of cells */ 577b799feefSDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 578b799feefSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isda);CHKERRQ(ierr); 579b799feefSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isplex);CHKERRQ(ierr); 580b799feefSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMSHELL,&isshell);CHKERRQ(ierr); 581b799feefSDave May if (isda) { 582b799feefSDave May PetscInt _nel,_npe; 583b799feefSDave May const PetscInt *_element; 584b799feefSDave May 585b799feefSDave May ierr = DMDAGetElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 586b799feefSDave May nel = _nel; 587b799feefSDave May ierr = DMDARestoreElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 588b799feefSDave May } else if (isplex) { 589b799feefSDave May PetscInt ps,pe; 590b799feefSDave May 591b799feefSDave May ierr = DMPlexGetHeightStratum(celldm,0,&ps,&pe);CHKERRQ(ierr); 592b799feefSDave May nel = pe - ps; 593b799feefSDave May } else if (isshell) { 594b799feefSDave May PetscErrorCode (*method_DMShellGetNumberOfCells)(DM,PetscInt*); 595b799feefSDave May 596b799feefSDave May ierr = PetscObjectQueryFunction((PetscObject)celldm,"DMGetNumberOfCells_C",&method_DMShellGetNumberOfCells);CHKERRQ(ierr); 597b799feefSDave May if (method_DMShellGetNumberOfCells) { 598b799feefSDave May ierr = method_DMShellGetNumberOfCells(celldm,&nel);CHKERRQ(ierr); 599b799feefSDave May } else 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);"); 600b799feefSDave 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"); 601b799feefSDave May 602b799feefSDave May ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 603580bdb30SBarry Smith ierr = PetscArrayzero(sum,nel);CHKERRQ(ierr); 604b799feefSDave May ierr = DMSwarmGetLocalSize(dm,&npoints);CHKERRQ(ierr); 605b799feefSDave May ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 606b799feefSDave May for (p=0; p<npoints; p++) { 607b799feefSDave May if (swarm_cellid[p] != DMLOCATEPOINT_POINT_NOT_FOUND) { 608b799feefSDave May sum[ swarm_cellid[p] ]++; 609b799feefSDave May } 610b799feefSDave May } 611b799feefSDave May ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 612b799feefSDave May } 613b799feefSDave May if (ncells) { *ncells = nel; } 614b799feefSDave May *count = sum; 6150e2ec84fSDave May PetscFunctionReturn(0); 6160e2ec84fSDave May } 617*35b38c60SMatthew G. Knepley 618*35b38c60SMatthew G. Knepley /*@ 619*35b38c60SMatthew G. Knepley DMSwarmGetNumSpecies - Get the number of particle species 620*35b38c60SMatthew G. Knepley 621*35b38c60SMatthew G. Knepley Not collective 622*35b38c60SMatthew G. Knepley 623*35b38c60SMatthew G. Knepley Input parameter: 624*35b38c60SMatthew G. Knepley . dm - the DMSwarm 625*35b38c60SMatthew G. Knepley 626*35b38c60SMatthew G. Knepley Output parameters: 627*35b38c60SMatthew G. Knepley . Ns - the number of species 628*35b38c60SMatthew G. Knepley 629*35b38c60SMatthew G. Knepley Level: intermediate 630*35b38c60SMatthew G. Knepley 631*35b38c60SMatthew G. Knepley .seealso: DMSwarmSetNumSpecies(), DMSwarmSetType(), DMSwarmType 632*35b38c60SMatthew G. Knepley @*/ 633*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmGetNumSpecies(DM sw, PetscInt *Ns) 634*35b38c60SMatthew G. Knepley { 635*35b38c60SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *) sw->data; 636*35b38c60SMatthew G. Knepley 637*35b38c60SMatthew G. Knepley PetscFunctionBegin; 638*35b38c60SMatthew G. Knepley *Ns = swarm->Ns; 639*35b38c60SMatthew G. Knepley PetscFunctionReturn(0); 640*35b38c60SMatthew G. Knepley } 641*35b38c60SMatthew G. Knepley 642*35b38c60SMatthew G. Knepley /*@ 643*35b38c60SMatthew G. Knepley DMSwarmSetNumSpecies - Set the number of particle species 644*35b38c60SMatthew G. Knepley 645*35b38c60SMatthew G. Knepley Not collective 646*35b38c60SMatthew G. Knepley 647*35b38c60SMatthew G. Knepley Input parameter: 648*35b38c60SMatthew G. Knepley + dm - the DMSwarm 649*35b38c60SMatthew G. Knepley - Ns - the number of species 650*35b38c60SMatthew G. Knepley 651*35b38c60SMatthew G. Knepley Level: intermediate 652*35b38c60SMatthew G. Knepley 653*35b38c60SMatthew G. Knepley .seealso: DMSwarmGetNumSpecies(), DMSwarmSetType(), DMSwarmType 654*35b38c60SMatthew G. Knepley @*/ 655*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmSetNumSpecies(DM sw, PetscInt Ns) 656*35b38c60SMatthew G. Knepley { 657*35b38c60SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *) sw->data; 658*35b38c60SMatthew G. Knepley 659*35b38c60SMatthew G. Knepley PetscFunctionBegin; 660*35b38c60SMatthew G. Knepley swarm->Ns = Ns; 661*35b38c60SMatthew G. Knepley PetscFunctionReturn(0); 662*35b38c60SMatthew G. Knepley } 663*35b38c60SMatthew G. Knepley 664*35b38c60SMatthew G. Knepley /*@C 665*35b38c60SMatthew G. Knepley DMSwarmComputeLocalSize - Compute the local number and distribution of particles based upon a density function 666*35b38c60SMatthew G. Knepley 667*35b38c60SMatthew G. Knepley Not collective 668*35b38c60SMatthew G. Knepley 669*35b38c60SMatthew G. Knepley Input Parameters: 670*35b38c60SMatthew G. Knepley + sw - The DMSwarm 671*35b38c60SMatthew G. Knepley . N - The target number of particles 672*35b38c60SMatthew G. Knepley - density - The density field for the particle layout, normalized to unity 673*35b38c60SMatthew G. Knepley 674*35b38c60SMatthew G. Knepley Note: One particle will be created for each species. 675*35b38c60SMatthew G. Knepley 676*35b38c60SMatthew G. Knepley Level: advanced 677*35b38c60SMatthew G. Knepley 678*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSizeFromOptions() 679*35b38c60SMatthew G. Knepley @*/ 680*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmComputeLocalSize(DM sw, PetscInt N, PetscProbFunc density) 681*35b38c60SMatthew G. Knepley { 682*35b38c60SMatthew G. Knepley DM dm; 683*35b38c60SMatthew G. Knepley PetscQuadrature quad; 684*35b38c60SMatthew G. Knepley const PetscReal *xq, *wq; 685*35b38c60SMatthew G. Knepley PetscInt *npc, *cellid; 686*35b38c60SMatthew G. Knepley PetscReal xi0[3], scale[1] = {.01}; 687*35b38c60SMatthew G. Knepley PetscInt Ns, cStart, cEnd, c, dim, d, Nq, q, Np = 0, p; 688*35b38c60SMatthew G. Knepley PetscBool simplex; 689*35b38c60SMatthew G. Knepley PetscErrorCode ierr; 690*35b38c60SMatthew G. Knepley 691*35b38c60SMatthew G. Knepley PetscFunctionBegin; 692*35b38c60SMatthew G. Knepley ierr = DMSwarmGetNumSpecies(sw, &Ns);CHKERRQ(ierr); 693*35b38c60SMatthew G. Knepley ierr = DMSwarmGetCellDM(sw, &dm);CHKERRQ(ierr); 694*35b38c60SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 695*35b38c60SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 696*35b38c60SMatthew G. Knepley ierr = DMPlexIsSimplex(dm, &simplex);CHKERRQ(ierr); 697*35b38c60SMatthew G. Knepley if (simplex) {ierr = PetscDTStroudConicalQuadrature(dim, 1, 5, -1.0, 1.0, &quad);CHKERRQ(ierr);} 698*35b38c60SMatthew G. Knepley else {ierr = PetscDTGaussTensorQuadrature(dim, 1, 5, -1.0, 1.0, &quad);CHKERRQ(ierr);} 699*35b38c60SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, &xq, &wq);CHKERRQ(ierr); 700*35b38c60SMatthew G. Knepley ierr = PetscMalloc1(cEnd-cStart, &npc);CHKERRQ(ierr); 701*35b38c60SMatthew G. Knepley /* Integrate the density function to get the number of particles in each cell */ 702*35b38c60SMatthew G. Knepley for (d = 0; d < dim; ++d) xi0[d] = -1.0; 703*35b38c60SMatthew G. Knepley for (c = 0; c < cEnd-cStart; ++c) { 704*35b38c60SMatthew G. Knepley const PetscInt cell = c + cStart; 705*35b38c60SMatthew G. Knepley PetscReal v0[3], J[9], invJ[9], detJ; 706*35b38c60SMatthew G. Knepley PetscReal n_int = 0.; 707*35b38c60SMatthew G. Knepley 708*35b38c60SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 709*35b38c60SMatthew G. Knepley for (q = 0; q < Nq; ++q) { 710*35b38c60SMatthew G. Knepley PetscReal xr[3], den[3]; 711*35b38c60SMatthew G. Knepley 712*35b38c60SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, v0, J, &xq[q*dim], xr); 713*35b38c60SMatthew G. Knepley ierr = density(xr, scale, den);CHKERRQ(ierr); 714*35b38c60SMatthew G. Knepley n_int += N*den[0]*wq[q]; 715*35b38c60SMatthew G. Knepley } 716*35b38c60SMatthew G. Knepley npc[c] = (PetscInt) n_int; 717*35b38c60SMatthew G. Knepley npc[c] *= Ns; 718*35b38c60SMatthew G. Knepley Np += npc[c]; 719*35b38c60SMatthew G. Knepley } 720*35b38c60SMatthew G. Knepley ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr); 721*35b38c60SMatthew G. Knepley ierr = DMSwarmSetLocalSizes(sw, Np, 0);CHKERRQ(ierr); 722*35b38c60SMatthew G. Knepley 723*35b38c60SMatthew G. Knepley ierr = DMSwarmGetField(sw, DMSwarmPICField_cellid, NULL, NULL, (void **) &cellid);CHKERRQ(ierr); 724*35b38c60SMatthew G. Knepley for (c = 0, p = 0; c < cEnd-cStart; ++c) { 725*35b38c60SMatthew G. Knepley for (q = 0; q < npc[c]; ++q, ++p) cellid[p] = c; 726*35b38c60SMatthew G. Knepley } 727*35b38c60SMatthew G. Knepley ierr = DMSwarmRestoreField(sw, DMSwarmPICField_cellid, NULL, NULL, (void **) &cellid);CHKERRQ(ierr); 728*35b38c60SMatthew G. Knepley ierr = PetscFree(npc);CHKERRQ(ierr); 729*35b38c60SMatthew G. Knepley PetscFunctionReturn(0); 730*35b38c60SMatthew G. Knepley } 731*35b38c60SMatthew G. Knepley 732*35b38c60SMatthew G. Knepley /*@ 733*35b38c60SMatthew G. Knepley DMSwarmComputeLocalSizeFromOptions - Compute the local number and distribution of particles based upon a density function determined by options 734*35b38c60SMatthew G. Knepley 735*35b38c60SMatthew G. Knepley Not collective 736*35b38c60SMatthew G. Knepley 737*35b38c60SMatthew G. Knepley Input Parameters: 738*35b38c60SMatthew G. Knepley , sw - The DMSwarm 739*35b38c60SMatthew G. Knepley 740*35b38c60SMatthew G. Knepley Level: advanced 741*35b38c60SMatthew G. Knepley 742*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSize() 743*35b38c60SMatthew G. Knepley @*/ 744*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmComputeLocalSizeFromOptions(DM sw) 745*35b38c60SMatthew G. Knepley { 746*35b38c60SMatthew G. Knepley DTProbDensityType den = DTPROB_DENSITY_CONSTANT; 747*35b38c60SMatthew G. Knepley PetscProbFunc pdf; 748*35b38c60SMatthew G. Knepley PetscInt N, Ns, dim; 749*35b38c60SMatthew G. Knepley PetscBool flg; 750*35b38c60SMatthew G. Knepley const char *prefix; 751*35b38c60SMatthew G. Knepley PetscErrorCode ierr; 752*35b38c60SMatthew G. Knepley 753*35b38c60SMatthew G. Knepley PetscFunctionBegin; 754*35b38c60SMatthew G. Knepley ierr = PetscOptionsBegin(PetscObjectComm((PetscObject) sw), "", "DMSwarm Options", "DMSWARM");CHKERRQ(ierr); 755*35b38c60SMatthew G. Knepley ierr = PetscOptionsInt("-dm_swarm_num_particles", "The target number of particles", "", N, &N, NULL);CHKERRQ(ierr); 756*35b38c60SMatthew G. Knepley ierr = PetscOptionsInt("-dm_swarm_num_species", "The number of species", "DMSwarmSetNumSpecies", Ns, &Ns, &flg);CHKERRQ(ierr); 757*35b38c60SMatthew G. Knepley if (flg) {ierr = DMSwarmSetNumSpecies(sw, Ns);CHKERRQ(ierr);} 758*35b38c60SMatthew G. Knepley ierr = PetscOptionsEnum("-dm_swarm_density", "Method to compute particle density <constant, gaussian>", "", DTProbDensityTypes, (PetscEnum) den, (PetscEnum *) &den, NULL);CHKERRQ(ierr); 759*35b38c60SMatthew G. Knepley ierr = PetscOptionsEnd();CHKERRQ(ierr); 760*35b38c60SMatthew G. Knepley 761*35b38c60SMatthew G. Knepley ierr = DMGetDimension(sw, &dim);CHKERRQ(ierr); 762*35b38c60SMatthew G. Knepley ierr = PetscObjectGetOptionsPrefix((PetscObject) sw, &prefix);CHKERRQ(ierr); 763*35b38c60SMatthew G. Knepley ierr = PetscProbCreateFromOptions(dim, prefix, "-dm_swarm_coordinate_density", &pdf, NULL, NULL);CHKERRQ(ierr); 764*35b38c60SMatthew G. Knepley ierr = DMSwarmComputeLocalSize(sw, N, pdf);CHKERRQ(ierr); 765*35b38c60SMatthew G. Knepley PetscFunctionReturn(0); 766*35b38c60SMatthew G. Knepley } 767*35b38c60SMatthew G. Knepley 768*35b38c60SMatthew G. Knepley /*@ 769*35b38c60SMatthew G. Knepley DMSwarmInitializeCoordinates - Determine the initial coordinates of particles for a PIC method 770*35b38c60SMatthew G. Knepley 771*35b38c60SMatthew G. Knepley Not collective 772*35b38c60SMatthew G. Knepley 773*35b38c60SMatthew G. Knepley Input Parameters: 774*35b38c60SMatthew G. Knepley , sw - The DMSwarm 775*35b38c60SMatthew G. Knepley 776*35b38c60SMatthew G. Knepley Note: Currently, we randomly place particles in their assigned cell 777*35b38c60SMatthew G. Knepley 778*35b38c60SMatthew G. Knepley Level: advanced 779*35b38c60SMatthew G. Knepley 780*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSize(), DMSwarmInitializeVelocities() 781*35b38c60SMatthew G. Knepley @*/ 782*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmInitializeCoordinates(DM sw) 783*35b38c60SMatthew G. Knepley { 784*35b38c60SMatthew G. Knepley DM dm; 785*35b38c60SMatthew G. Knepley PetscRandom rnd; 786*35b38c60SMatthew G. Knepley PetscScalar *weight; 787*35b38c60SMatthew G. Knepley PetscReal *x, xi0[3]; 788*35b38c60SMatthew G. Knepley PetscInt *species; 789*35b38c60SMatthew G. Knepley PetscBool removePoints = PETSC_TRUE; 790*35b38c60SMatthew G. Knepley PetscDataType dtype; 791*35b38c60SMatthew G. Knepley PetscInt Ns, cStart, cEnd, c, dim, d, s, bs; 792*35b38c60SMatthew G. Knepley PetscErrorCode ierr; 793*35b38c60SMatthew G. Knepley 794*35b38c60SMatthew G. Knepley PetscFunctionBeginUser; 795*35b38c60SMatthew G. Knepley ierr = DMSwarmGetNumSpecies(sw, &Ns);CHKERRQ(ierr); 796*35b38c60SMatthew G. Knepley ierr = DMSwarmGetCellDM(sw, &dm);CHKERRQ(ierr); 797*35b38c60SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 798*35b38c60SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 799*35b38c60SMatthew G. Knepley 800*35b38c60SMatthew G. Knepley /* Set particle position randomly in cell, set weights to 1 */ 801*35b38c60SMatthew G. Knepley ierr = PetscRandomCreate(PetscObjectComm((PetscObject) dm), &rnd);CHKERRQ(ierr); 802*35b38c60SMatthew G. Knepley ierr = PetscRandomSetInterval(rnd, -1.0, 1.0);CHKERRQ(ierr); 803*35b38c60SMatthew G. Knepley ierr = PetscRandomSetFromOptions(rnd);CHKERRQ(ierr); 804*35b38c60SMatthew G. Knepley ierr = DMSwarmGetField(sw, "w_q", &bs, &dtype, (void **) &weight);CHKERRQ(ierr); 805*35b38c60SMatthew G. Knepley ierr = DMSwarmGetField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void **) &x);CHKERRQ(ierr); 806*35b38c60SMatthew G. Knepley ierr = DMSwarmGetField(sw, "species", NULL, NULL, (void **) &species); 807*35b38c60SMatthew G. Knepley ierr = DMSwarmSortGetAccess(sw);CHKERRQ(ierr); 808*35b38c60SMatthew G. Knepley for (d = 0; d < dim; ++d) xi0[d] = -1.0; 809*35b38c60SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 810*35b38c60SMatthew G. Knepley PetscReal v0[3], J[9], invJ[9], detJ; 811*35b38c60SMatthew G. Knepley PetscInt *pidx, Npc, q; 812*35b38c60SMatthew G. Knepley 813*35b38c60SMatthew G. Knepley ierr = DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx);CHKERRQ(ierr); 814*35b38c60SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 815*35b38c60SMatthew G. Knepley for (q = 0; q < Npc; ++q) { 816*35b38c60SMatthew G. Knepley const PetscInt p = pidx[q]; 817*35b38c60SMatthew G. Knepley PetscReal xref[3]; 818*35b38c60SMatthew G. Knepley 819*35b38c60SMatthew G. Knepley for (d = 0; d < dim; ++d) {ierr = PetscRandomGetValueReal(rnd, &xref[d]);CHKERRQ(ierr);} 820*35b38c60SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, v0, J, xref, &x[p*dim]); 821*35b38c60SMatthew G. Knepley 822*35b38c60SMatthew G. Knepley weight[p] = 1.0; 823*35b38c60SMatthew G. Knepley for (s = 0; s < Ns; ++s) species[p] = p % Ns; 824*35b38c60SMatthew G. Knepley } 825*35b38c60SMatthew G. Knepley ierr = PetscFree(pidx);CHKERRQ(ierr); 826*35b38c60SMatthew G. Knepley } 827*35b38c60SMatthew G. Knepley ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr); 828*35b38c60SMatthew G. Knepley ierr = DMSwarmSortRestoreAccess(sw);CHKERRQ(ierr); 829*35b38c60SMatthew G. Knepley ierr = DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **) &weight);CHKERRQ(ierr); 830*35b38c60SMatthew G. Knepley ierr = DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **) &x);CHKERRQ(ierr); 831*35b38c60SMatthew G. Knepley ierr = DMSwarmRestoreField(sw, "species", NULL, NULL, (void **) &species);CHKERRQ(ierr); 832*35b38c60SMatthew G. Knepley ierr = DMSwarmMigrate(sw, removePoints);CHKERRQ(ierr); 833*35b38c60SMatthew G. Knepley ierr = DMLocalizeCoordinates(sw);CHKERRQ(ierr); 834*35b38c60SMatthew G. Knepley PetscFunctionReturn(0); 835*35b38c60SMatthew G. Knepley } 836*35b38c60SMatthew G. Knepley 837*35b38c60SMatthew G. Knepley /*@C 838*35b38c60SMatthew G. Knepley DMSwarmInitializeVelocities - Set the initial velocities of particles using a distribution. 839*35b38c60SMatthew G. Knepley 840*35b38c60SMatthew G. Knepley Collective on dm 841*35b38c60SMatthew G. Knepley 842*35b38c60SMatthew G. Knepley Input Parameters: 843*35b38c60SMatthew G. Knepley + sw - The DMSwarm object 844*35b38c60SMatthew G. Knepley . sampler - A function which uniformly samples the velocity PDF 845*35b38c60SMatthew G. Knepley - v0 - The velocity scale for nondimensionalization for each species 846*35b38c60SMatthew G. Knepley 847*35b38c60SMatthew G. Knepley Level: advanced 848*35b38c60SMatthew G. Knepley 849*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSize(), DMSwarmInitializeCoordinates(), DMSwarmInitializeVelocitiesFromOptions() 850*35b38c60SMatthew G. Knepley @*/ 851*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmInitializeVelocities(DM sw, PetscProbFunc sampler, const PetscReal v0[]) 852*35b38c60SMatthew G. Knepley { 853*35b38c60SMatthew G. Knepley PetscRandom rnd; 854*35b38c60SMatthew G. Knepley PetscReal *v; 855*35b38c60SMatthew G. Knepley PetscInt *species; 856*35b38c60SMatthew G. Knepley PetscInt dim, Np, p; 857*35b38c60SMatthew G. Knepley PetscErrorCode ierr; 858*35b38c60SMatthew G. Knepley 859*35b38c60SMatthew G. Knepley PetscFunctionBegin; 860*35b38c60SMatthew G. Knepley ierr = PetscRandomCreate(PetscObjectComm((PetscObject) sw), &rnd);CHKERRQ(ierr); 861*35b38c60SMatthew G. Knepley ierr = PetscRandomSetInterval(rnd, 0, 1.);CHKERRQ(ierr); 862*35b38c60SMatthew G. Knepley ierr = PetscRandomSetFromOptions(rnd);CHKERRQ(ierr); 863*35b38c60SMatthew G. Knepley 864*35b38c60SMatthew G. Knepley ierr = DMGetDimension(sw, &dim);CHKERRQ(ierr); 865*35b38c60SMatthew G. Knepley ierr = DMSwarmGetLocalSize(sw, &Np);CHKERRQ(ierr); 866*35b38c60SMatthew G. Knepley ierr = DMSwarmGetField(sw, "velocity", NULL, NULL, (void **) &v);CHKERRQ(ierr); 867*35b38c60SMatthew G. Knepley ierr = DMSwarmGetField(sw, "species", NULL, NULL, (void **) &species); 868*35b38c60SMatthew G. Knepley for (p = 0; p < Np; ++p) { 869*35b38c60SMatthew G. Knepley PetscInt s = species[p], d; 870*35b38c60SMatthew G. Knepley PetscReal a[3], vel[3]; 871*35b38c60SMatthew G. Knepley 872*35b38c60SMatthew G. Knepley for (d = 0; d < dim; ++d) {ierr = PetscRandomGetValueReal(rnd, &a[d]);CHKERRQ(ierr);} 873*35b38c60SMatthew G. Knepley ierr = sampler(a, NULL, vel);CHKERRQ(ierr); 874*35b38c60SMatthew G. Knepley for (d = 0; d < dim; ++d) {v[p*dim+d] = (v0[s] / v0[0]) * vel[d];} 875*35b38c60SMatthew G. Knepley } 876*35b38c60SMatthew G. Knepley ierr = DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **) &v);CHKERRQ(ierr); 877*35b38c60SMatthew G. Knepley ierr = DMSwarmRestoreField(sw, "species", NULL, NULL, (void **) &species);CHKERRQ(ierr); 878*35b38c60SMatthew G. Knepley ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr); 879*35b38c60SMatthew G. Knepley PetscFunctionReturn(0); 880*35b38c60SMatthew G. Knepley } 881*35b38c60SMatthew G. Knepley 882*35b38c60SMatthew G. Knepley /*@ 883*35b38c60SMatthew G. Knepley DMSwarmInitializeVelocitiesFromOptions - Set the initial velocities of particles using a distribution determined from options. 884*35b38c60SMatthew G. Knepley 885*35b38c60SMatthew G. Knepley Collective on dm 886*35b38c60SMatthew G. Knepley 887*35b38c60SMatthew G. Knepley Input Parameters: 888*35b38c60SMatthew G. Knepley + sw - The DMSwarm object 889*35b38c60SMatthew G. Knepley - v0 - The velocity scale for nondimensionalization for each species 890*35b38c60SMatthew G. Knepley 891*35b38c60SMatthew G. Knepley Level: advanced 892*35b38c60SMatthew G. Knepley 893*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSize(), DMSwarmInitializeCoordinates(), DMSwarmInitializeVelocities() 894*35b38c60SMatthew G. Knepley @*/ 895*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmInitializeVelocitiesFromOptions(DM sw, const PetscReal v0[]) 896*35b38c60SMatthew G. Knepley { 897*35b38c60SMatthew G. Knepley PetscProbFunc sampler; 898*35b38c60SMatthew G. Knepley PetscInt dim; 899*35b38c60SMatthew G. Knepley const char *prefix; 900*35b38c60SMatthew G. Knepley PetscErrorCode ierr; 901*35b38c60SMatthew G. Knepley 902*35b38c60SMatthew G. Knepley PetscFunctionBegin; 903*35b38c60SMatthew G. Knepley ierr = DMGetDimension(sw, &dim);CHKERRQ(ierr); 904*35b38c60SMatthew G. Knepley ierr = PetscObjectGetOptionsPrefix((PetscObject) sw, &prefix);CHKERRQ(ierr); 905*35b38c60SMatthew G. Knepley ierr = PetscProbCreateFromOptions(dim, prefix, "-dm_swarm_velocity_density", NULL, NULL, &sampler);CHKERRQ(ierr); 906*35b38c60SMatthew G. Knepley ierr = DMSwarmInitializeVelocities(sw, sampler, v0);CHKERRQ(ierr); 907*35b38c60SMatthew G. Knepley PetscFunctionReturn(0); 908*35b38c60SMatthew G. Knepley } 909