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> 694f7d2dcSDave May #include "data_bucket.h" 70e2ec84fSDave May 80e2ec84fSDave May /* 90e2ec84fSDave May Error chceking macto to ensure the swarm type is correct and that a cell DM has been set 100e2ec84fSDave May */ 110e2ec84fSDave May #define DMSWARMPICVALID(dm) \ 120e2ec84fSDave May { \ 130e2ec84fSDave May DM_Swarm *_swarm = (DM_Swarm*)(dm)->data; \ 140e2ec84fSDave May if (_swarm->swarm_type != DMSWARM_PIC) SETERRQ(PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Only valid for DMSwarm-PIC. You must call DMSwarmSetType(dm,DMSWARM_PIC)"); \ 150e2ec84fSDave May else \ 160e2ec84fSDave May if (!_swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Only valid for DMSwarmPIC if the cell DM is set. You must call DMSwarmSetCellDM(dm,celldm)"); \ 170e2ec84fSDave May } 180e2ec84fSDave May 190e2ec84fSDave May /* Coordinate insertition/addition API */ 200e2ec84fSDave May /*@C 210e2ec84fSDave May DMSwarmSetPointsUniformCoordinates - Set point coordinates in a DMSwarm on a regular (ijk) grid 220e2ec84fSDave May 230e2ec84fSDave May Collective on DM 240e2ec84fSDave May 250e2ec84fSDave May Input parameters: 260e2ec84fSDave May + dm - the DMSwarm 270e2ec84fSDave May . min - minimum coordinate values in the x, y, z directions (array of length dim) 280e2ec84fSDave May . max - maximum coordinate values in the x, y, z directions (array of length dim) 290e2ec84fSDave May . npoints - number of points in each spatial direction (array of length dim) 300e2ec84fSDave May - mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES) 310e2ec84fSDave May 320e2ec84fSDave May Level: beginner 330e2ec84fSDave May 340e2ec84fSDave May Notes: 350e2ec84fSDave May When using mode = INSERT_VALUES, this method will reset the number of particles in the DMSwarm 360e2ec84fSDave May to be npoints[0]*npoints[1] (2D) or npoints[0]*npoints[1]*npoints[2] (3D). When using mode = ADD_VALUES, 370e2ec84fSDave May new points will be appended to any already existing in the DMSwarm 380e2ec84fSDave May 390e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 400e2ec84fSDave May @*/ 410e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointsUniformCoordinates(DM dm,PetscReal min[],PetscReal max[],PetscInt npoints[],InsertMode mode) 420e2ec84fSDave May { 430e2ec84fSDave May PetscErrorCode ierr; 440e2ec84fSDave May PetscReal gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL}; 450e2ec84fSDave May PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 460e2ec84fSDave May PetscInt i,j,k,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found; 470e2ec84fSDave May Vec coorlocal; 480e2ec84fSDave May const PetscScalar *_coor; 490e2ec84fSDave May DM celldm; 500e2ec84fSDave May PetscReal dx[3]; 512e3d3761SDave May PetscInt _npoints[] = { 0, 0, 1 }; 520e2ec84fSDave May Vec pos; 530e2ec84fSDave May PetscScalar *_pos; 540e2ec84fSDave May PetscReal *swarm_coor; 550e2ec84fSDave May PetscInt *swarm_cellid; 560e2ec84fSDave May PetscSF sfcell = NULL; 570e2ec84fSDave May const PetscSFNode *LA_sfcell; 580e2ec84fSDave May 590e2ec84fSDave May PetscFunctionBegin; 600e2ec84fSDave May DMSWARMPICVALID(dm); 610e2ec84fSDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 620e2ec84fSDave May ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr); 630e2ec84fSDave May ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr); 640e2ec84fSDave May ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr); 650e2ec84fSDave May N = N / bs; 660e2ec84fSDave May ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 670e2ec84fSDave May for (i=0; i<N; i++) { 680e2ec84fSDave May for (b=0; b<bs; b++) { 69a5f152d1SDave May gmin[b] = PetscMin(gmin[b],PetscRealPart(_coor[bs*i+b])); 70a5f152d1SDave May gmax[b] = PetscMax(gmax[b],PetscRealPart(_coor[bs*i+b])); 710e2ec84fSDave May } 720e2ec84fSDave May } 730e2ec84fSDave May ierr = VecRestoreArrayRead(coorlocal,&_coor);CHKERRQ(ierr); 740e2ec84fSDave May 750e2ec84fSDave May for (b=0; b<bs; b++) { 7671844bb8SDave May if (npoints[b] > 1) { 770e2ec84fSDave May dx[b] = (max[b] - min[b])/((PetscReal)(npoints[b]-1)); 7871844bb8SDave May } else { 7971844bb8SDave May dx[b] = 0.0; 8071844bb8SDave May } 812e3d3761SDave May 822e3d3761SDave May _npoints[b] = npoints[b]; 830e2ec84fSDave May } 840e2ec84fSDave May 850e2ec84fSDave May /* determine number of points living in the bounding box */ 860e2ec84fSDave May n_estimate = 0; 872e3d3761SDave May for (k=0; k<_npoints[2]; k++) { 882e3d3761SDave May for (j=0; j<_npoints[1]; j++) { 892e3d3761SDave May for (i=0; i<_npoints[0]; i++) { 900e2ec84fSDave May PetscReal xp[] = {0.0,0.0,0.0}; 910e2ec84fSDave May PetscInt ijk[3]; 920e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 930e2ec84fSDave May 940e2ec84fSDave May ijk[0] = i; 950e2ec84fSDave May ijk[1] = j; 960e2ec84fSDave May ijk[2] = k; 970e2ec84fSDave May for (b=0; b<bs; b++) { 980e2ec84fSDave May xp[b] = min[b] + ijk[b] * dx[b]; 990e2ec84fSDave May } 1000e2ec84fSDave May for (b=0; b<bs; b++) { 1010e2ec84fSDave May if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; } 1020e2ec84fSDave May if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; } 1030e2ec84fSDave May } 1040e2ec84fSDave May if (point_inside) { n_estimate++; } 1050e2ec84fSDave May } 1060e2ec84fSDave May } 1070e2ec84fSDave May } 1080e2ec84fSDave May 1090e2ec84fSDave May /* create candidate list */ 110c28a3c15SDave May ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr); 1110e2ec84fSDave May ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr); 1120e2ec84fSDave May ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr); 1130e2ec84fSDave May ierr = VecSetFromOptions(pos);CHKERRQ(ierr); 1140e2ec84fSDave May ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr); 1150e2ec84fSDave May 1160e2ec84fSDave May n_estimate = 0; 1172e3d3761SDave May for (k=0; k<_npoints[2]; k++) { 1182e3d3761SDave May for (j=0; j<_npoints[1]; j++) { 1192e3d3761SDave May for (i=0; i<_npoints[0]; i++) { 1200e2ec84fSDave May PetscReal xp[] = {0.0,0.0,0.0}; 1210e2ec84fSDave May PetscInt ijk[3]; 1220e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 1230e2ec84fSDave May 1240e2ec84fSDave May ijk[0] = i; 1250e2ec84fSDave May ijk[1] = j; 1260e2ec84fSDave May ijk[2] = k; 1270e2ec84fSDave May for (b=0; b<bs; b++) { 1280e2ec84fSDave May xp[b] = min[b] + ijk[b] * dx[b]; 1290e2ec84fSDave May } 1300e2ec84fSDave May for (b=0; b<bs; b++) { 1310e2ec84fSDave May if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; } 1320e2ec84fSDave May if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; } 1330e2ec84fSDave May } 1340e2ec84fSDave May if (point_inside) { 1350e2ec84fSDave May for (b=0; b<bs; b++) { 1360e2ec84fSDave May _pos[bs*n_estimate+b] = xp[b]; 1370e2ec84fSDave May } 1380e2ec84fSDave May n_estimate++; 1390e2ec84fSDave May } 1400e2ec84fSDave May } 1410e2ec84fSDave May } 1420e2ec84fSDave May } 1430e2ec84fSDave May ierr = VecRestoreArray(pos,&_pos);CHKERRQ(ierr); 1440e2ec84fSDave May 1450e2ec84fSDave May /* locate points */ 1460e2ec84fSDave May ierr = DMLocatePoints(celldm,pos,DM_POINTLOCATION_NONE,&sfcell);CHKERRQ(ierr); 1470e2ec84fSDave May 1480e2ec84fSDave May ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr); 1490e2ec84fSDave May n_found = 0; 1500e2ec84fSDave May for (p=0; p<n_estimate; p++) { 1510e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 1520e2ec84fSDave May n_found++; 1530e2ec84fSDave May } 1540e2ec84fSDave May } 1550e2ec84fSDave May 1560e2ec84fSDave May /* adjust size */ 1570e2ec84fSDave May if (mode == ADD_VALUES) { 1580e2ec84fSDave May ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr); 1590e2ec84fSDave May n_new_est = n_curr + n_found; 1600e2ec84fSDave May ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 1610e2ec84fSDave May } 1620e2ec84fSDave May if (mode == INSERT_VALUES) { 1630e2ec84fSDave May n_curr = 0; 1640e2ec84fSDave May n_new_est = n_found; 1650e2ec84fSDave May ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr); 1660e2ec84fSDave May } 1670e2ec84fSDave May 1680e2ec84fSDave May /* initialize new coords, cell owners, pid */ 1690e2ec84fSDave May ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr); 1700e2ec84fSDave May ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 1710e2ec84fSDave May ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 1720e2ec84fSDave May n_found = 0; 1730e2ec84fSDave May for (p=0; p<n_estimate; p++) { 1740e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 1750e2ec84fSDave May for (b=0; b<bs; b++) { 1760ca99263SDave May swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]); 1770e2ec84fSDave May } 1780e2ec84fSDave May swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 1790e2ec84fSDave May n_found++; 1800e2ec84fSDave May } 1810e2ec84fSDave May } 1820e2ec84fSDave May ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 1830e2ec84fSDave May ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr); 1840e2ec84fSDave May ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr); 1850e2ec84fSDave May 1860e2ec84fSDave May ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr); 1870e2ec84fSDave May ierr = VecDestroy(&pos);CHKERRQ(ierr); 1880e2ec84fSDave May 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 1950e2ec84fSDave May 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); 2360e2ec84fSDave May ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(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; 2550e2ec84fSDave May ierr = MPI_Bcast(&my_npoints,1,MPIU_INT,0,comm);CHKERRQ(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 } 2620e2ec84fSDave May ierr = MPI_Bcast(my_coor,bs*my_npoints,MPIU_REAL,0,comm);CHKERRQ(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 3530e2ec84fSDave May PetscFunctionReturn(0); 3540e2ec84fSDave May } 3550e2ec84fSDave May 3560e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM,DM,DMSwarmPICLayoutType,PetscInt); 3570e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM,DM,DMSwarmPICLayoutType,PetscInt); 3580e2ec84fSDave May 3590e2ec84fSDave May /*@C 3600e2ec84fSDave May DMSwarmInsertPointsUsingCellDM - Insert point coordinates within each cell 3610e2ec84fSDave May 3620e2ec84fSDave May Not collective 3630e2ec84fSDave May 3640e2ec84fSDave May Input parameters: 3650e2ec84fSDave May + dm - the DMSwarm 3660e2ec84fSDave May . layout_type - method used to fill each cell with the cell DM 3670e2ec84fSDave May - fill_param - parameter controlling how many points per cell are added (the meaning of this parameter is dependent on the layout type) 3680e2ec84fSDave May 3690e2ec84fSDave May Level: beginner 3700e2ec84fSDave May 3710e2ec84fSDave May Notes: 372*ea3d7275SDave May * The insert method will reset any previous defined points within the DMSwarm. 373*ea3d7275SDave May * When using a DMDA both 2D and 3D are supported for all layout types provided you are using DMDA_ELEMENT_Q1. 374*ea3d7275SDave May * When using a DMPLEX the following case are supported 375*ea3d7275SDave May (i) DMSWARMPIC_LAYOUT_REGULAR: 2D (triangle), 376*ea3d7275SDave May (ii) DMSWARMPIC_LAYOUT_GAUSS: 2D and 3D provided the cell is a tri/tet or a quad/hex, 377*ea3d7275SDave May (iii) DMSWARMPIC_LAYOUT_SUBDIVISION: 2D and 3D for quad/hex and 2D tri. 3780e2ec84fSDave May 3790e2ec84fSDave May .seealso: DMSwarmPICLayoutType, DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 3800e2ec84fSDave May @*/ 3810e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm,DMSwarmPICLayoutType layout_type,PetscInt fill_param) 3820e2ec84fSDave May { 3830e2ec84fSDave May PetscErrorCode ierr; 3840e2ec84fSDave May DM celldm; 3850e2ec84fSDave May PetscBool isDA,isPLEX; 3860e2ec84fSDave May 3870e2ec84fSDave May PetscFunctionBegin; 3880e2ec84fSDave May DMSWARMPICVALID(dm); 3890e2ec84fSDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 3900e2ec84fSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 3910e2ec84fSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 3920e2ec84fSDave May if (isDA) { 3930e2ec84fSDave May ierr = private_DMSwarmInsertPointsUsingCellDM_DA(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 3940e2ec84fSDave May } else if (isPLEX) { 3950e2ec84fSDave May ierr = private_DMSwarmInsertPointsUsingCellDM_PLEX(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); 3960e2ec84fSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 3970e2ec84fSDave May 3980e2ec84fSDave May PetscFunctionReturn(0); 3990e2ec84fSDave May } 4000e2ec84fSDave May 401431382f2SDave 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. 419*ea3d7275SDave May Only supported for DMPLEX. If you are using a DMDA it is recommended to either use 420*ea3d7275SDave May DMSwarmInsertPointsUsingCellDM(), or extract and set the coordinates yourself using 421*ea3d7275SDave May PetscReal *coor; 422*ea3d7275SDave May DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 423*ea3d7275SDave May // user code to define the coordinates here 424*ea3d7275SDave May DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 425431382f2SDave May 426431382f2SDave May .seealso: DMSwarmSetCellDM(), DMSwarmInsertPointsUsingCellDM() 427431382f2SDave May @*/ 428431382f2SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinatesCellwise(DM dm,PetscInt npoints,PetscReal xi[]) 4290e2ec84fSDave May { 430431382f2SDave May PetscErrorCode ierr; 431431382f2SDave May DM celldm; 432431382f2SDave May PetscBool isDA,isPLEX; 433431382f2SDave May 4340e2ec84fSDave May PetscFunctionBegin; 435431382f2SDave May DMSWARMPICVALID(dm); 436431382f2SDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 437431382f2SDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 438431382f2SDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 439431382f2SDave May if (isDA) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMPLEX. Recommended you use DMSwarmInsertPointsUsingCellDM()"); 440431382f2SDave May else if (isPLEX) { 441431382f2SDave May ierr = private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm,celldm,npoints,xi);CHKERRQ(ierr); 442431382f2SDave May } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 443431382f2SDave May 4440e2ec84fSDave May PetscFunctionReturn(0); 4450e2ec84fSDave May } 446431382f2SDave May 4470e2ec84fSDave May 4480e2ec84fSDave May /* Field projection API */ 44994f7d2dcSDave May extern PetscErrorCode private_DMSwarmProjectFields_DA(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]); 45094f7d2dcSDave May extern PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]); 45194f7d2dcSDave May 45294f7d2dcSDave May /*@C 45394f7d2dcSDave May DMSwarmProjectFields - Project a set of swarm fields onto the cell DM 45494f7d2dcSDave May 45594f7d2dcSDave May Collective on Vec 45694f7d2dcSDave May 45794f7d2dcSDave May Input parameters: 45894f7d2dcSDave May + dm - the DMSwarm 45994f7d2dcSDave May . nfields - the number of swarm fields to project 46094f7d2dcSDave May . fieldnames - the textual names of the swarm fields to project 46194f7d2dcSDave May . fields - an array of Vec's of length nfields 46294f7d2dcSDave May - reuse - flag indicating whether the array and contents of fields should be re-used or internally allocated 46394f7d2dcSDave May 46494f7d2dcSDave May Currently, the only available projection method consists of 46594f7d2dcSDave May phi_i = \sum_{p=0}^{np} N_i(x_p) phi_p dJ / \sum_{p=0}^{np} N_i(x_p) dJ 46694f7d2dcSDave May where phi_p is the swarm field at point p, 46794f7d2dcSDave May N_i() is the cell DM basis function at vertex i, 46894f7d2dcSDave May dJ is the determinant of the cell Jacobian and 46994f7d2dcSDave May phi_i is the projected vertex value of the field phi. 47094f7d2dcSDave May 47194f7d2dcSDave May Level: beginner 47294f7d2dcSDave May 47394f7d2dcSDave May Notes: 47494f7d2dcSDave 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. 47694f7d2dcSDave May - Only swarm fields registered with data type = PETSC_REAL can be projected onto the cell DM. 47794f7d2dcSDave May - Only swarm fields of block size = 1 can currently be projected. 47894f7d2dcSDave May - The only projection methods currently only support the DA (2D) and PLEX (triangles 2D). 47994f7d2dcSDave May 48094f7d2dcSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 48194f7d2dcSDave May @*/ 48294f7d2dcSDave May PETSC_EXTERN PetscErrorCode DMSwarmProjectFields(DM dm,PetscInt nfields,const char *fieldnames[],Vec **fields,PetscBool reuse) 4830e2ec84fSDave May { 48494f7d2dcSDave May DM_Swarm *swarm = (DM_Swarm*)dm->data; 48594f7d2dcSDave May DataField *gfield; 48694f7d2dcSDave May DM celldm; 48794f7d2dcSDave May PetscBool isDA,isPLEX; 48894f7d2dcSDave May Vec *vecs; 48994f7d2dcSDave May PetscInt f,nvecs; 49094f7d2dcSDave May PetscInt project_type = 0; 49194f7d2dcSDave May PetscErrorCode ierr; 49294f7d2dcSDave May 4930e2ec84fSDave May PetscFunctionBegin; 49494f7d2dcSDave May DMSWARMPICVALID(dm); 49594f7d2dcSDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 49694f7d2dcSDave May ierr = PetscMalloc1(nfields,&gfield);CHKERRQ(ierr); 49794f7d2dcSDave May nvecs = 0; 49894f7d2dcSDave May for (f=0; f<nfields; f++) { 49994f7d2dcSDave May ierr = DataBucketGetDataFieldByName(swarm->db,fieldnames[f],&gfield[f]);CHKERRQ(ierr); 50094f7d2dcSDave May if (gfield[f]->petsc_type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields using a data type = PETSC_REAL"); 50194f7d2dcSDave May if (gfield[f]->bs != 1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields with block size = 1"); 50294f7d2dcSDave May nvecs += gfield[f]->bs; 50394f7d2dcSDave May } 50494f7d2dcSDave May if (!reuse) { 50594f7d2dcSDave May ierr = PetscMalloc1(nvecs,&vecs);CHKERRQ(ierr); 50694f7d2dcSDave May for (f=0; f<nvecs; f++) { 50794f7d2dcSDave May ierr = DMCreateGlobalVector(celldm,&vecs[f]);CHKERRQ(ierr); 50894f7d2dcSDave May ierr = PetscObjectSetName((PetscObject)vecs[f],gfield[f]->name);CHKERRQ(ierr); 50994f7d2dcSDave May } 51094f7d2dcSDave May } else { 51194f7d2dcSDave May vecs = *fields; 51294f7d2dcSDave May } 51394f7d2dcSDave May 51494f7d2dcSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); 51594f7d2dcSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); 51694f7d2dcSDave May if (isDA) { 51794f7d2dcSDave May ierr = private_DMSwarmProjectFields_DA(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); 51894f7d2dcSDave May } else if (isPLEX) { 51994f7d2dcSDave May ierr = private_DMSwarmProjectFields_PLEX(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); 52094f7d2dcSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); 52194f7d2dcSDave May 52294f7d2dcSDave May ierr = PetscFree(gfield);CHKERRQ(ierr); 52394f7d2dcSDave May if (!reuse) { 52494f7d2dcSDave May *fields = vecs; 52594f7d2dcSDave May } 52694f7d2dcSDave May 5270e2ec84fSDave May PetscFunctionReturn(0); 5280e2ec84fSDave May } 5290e2ec84fSDave May 5300e2ec84fSDave May /*@C 531b799feefSDave May DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM 5320e2ec84fSDave May 5330e2ec84fSDave May Not collective 5340e2ec84fSDave May 5350e2ec84fSDave May Input parameter: 5360e2ec84fSDave May . dm - the DMSwarm 5370e2ec84fSDave May 5380e2ec84fSDave May Output parameters: 5390e2ec84fSDave May + ncells - the number of cells in the cell DM (optional argument, pass NULL to ignore) 540b799feefSDave May - count - array of length ncells containing the number of points per cell 5410e2ec84fSDave May 5420e2ec84fSDave May Level: beginner 5430e2ec84fSDave May 5440e2ec84fSDave May Notes: 5450e2ec84fSDave May The array count is allocated internally and must be free'd by the user. 5460e2ec84fSDave May 5470e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType 5480e2ec84fSDave May @*/ 5490e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm,PetscInt *ncells,PetscInt **count) 5500e2ec84fSDave May { 551b799feefSDave May PetscErrorCode ierr; 552b799feefSDave May PetscBool isvalid; 553b799feefSDave May PetscInt nel; 554b799feefSDave May PetscInt *sum; 555b799feefSDave May 5560e2ec84fSDave May PetscFunctionBegin; 557b799feefSDave May ierr = DMSwarmSortGetIsValid(dm,&isvalid);CHKERRQ(ierr); 558b799feefSDave May nel = 0; 559b799feefSDave May if (isvalid) { 560b799feefSDave May PetscInt e; 561b799feefSDave May 562b799feefSDave May ierr = DMSwarmSortGetSizes(dm,&nel,NULL);CHKERRQ(ierr); 563b799feefSDave May 564b799feefSDave May ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 565b799feefSDave May for (e=0; e<nel; e++) { 566b799feefSDave May ierr = DMSwarmSortGetNumberOfPointsPerCell(dm,e,&sum[e]);CHKERRQ(ierr); 567b799feefSDave May } 568b799feefSDave May } else { 569b799feefSDave May DM celldm; 570b799feefSDave May PetscBool isda,isplex,isshell; 571b799feefSDave May PetscInt p,npoints; 572b799feefSDave May PetscInt *swarm_cellid; 573b799feefSDave May 574b799feefSDave May /* get the number of cells */ 575b799feefSDave May ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); 576b799feefSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isda);CHKERRQ(ierr); 577b799feefSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isplex);CHKERRQ(ierr); 578b799feefSDave May ierr = PetscObjectTypeCompare((PetscObject)celldm,DMSHELL,&isshell);CHKERRQ(ierr); 579b799feefSDave May if (isda) { 580b799feefSDave May PetscInt _nel,_npe; 581b799feefSDave May const PetscInt *_element; 582b799feefSDave May 583b799feefSDave May ierr = DMDAGetElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 584b799feefSDave May nel = _nel; 585b799feefSDave May ierr = DMDARestoreElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr); 586b799feefSDave May } else if (isplex) { 587b799feefSDave May PetscInt ps,pe; 588b799feefSDave May 589b799feefSDave May ierr = DMPlexGetHeightStratum(celldm,0,&ps,&pe);CHKERRQ(ierr); 590b799feefSDave May nel = pe - ps; 591b799feefSDave May } else if (isshell) { 592b799feefSDave May PetscErrorCode (*method_DMShellGetNumberOfCells)(DM,PetscInt*); 593b799feefSDave May 594b799feefSDave May ierr = PetscObjectQueryFunction((PetscObject)celldm,"DMGetNumberOfCells_C",&method_DMShellGetNumberOfCells);CHKERRQ(ierr); 595b799feefSDave May if (method_DMShellGetNumberOfCells) { 596b799feefSDave May ierr = method_DMShellGetNumberOfCells(celldm,&nel);CHKERRQ(ierr); 597b799feefSDave 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 );"); 598b799feefSDave 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"); 599b799feefSDave May 600b799feefSDave May ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); 601b799feefSDave May ierr = PetscMemzero(sum,sizeof(PetscInt)*nel);CHKERRQ(ierr); 602b799feefSDave May ierr = DMSwarmGetLocalSize(dm,&npoints);CHKERRQ(ierr); 603b799feefSDave May ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 604b799feefSDave May for (p=0; p<npoints; p++) { 605b799feefSDave May if (swarm_cellid[p] != DMLOCATEPOINT_POINT_NOT_FOUND) { 606b799feefSDave May sum[ swarm_cellid[p] ]++; 607b799feefSDave May } 608b799feefSDave May } 609b799feefSDave May ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr); 610b799feefSDave May } 611b799feefSDave May if (ncells) { *ncells = nel; } 612b799feefSDave May *count = sum; 6130e2ec84fSDave May PetscFunctionReturn(0); 6140e2ec84fSDave May } 615