#define PETSCDM_DLL #include /*I "petscdmswarm.h" I*/ #include #include #include #include "data_bucket.h" /* Error chceking macto to ensure the swarm type is correct and that a cell DM has been set */ #define DMSWARMPICVALID(dm) \ { \ DM_Swarm *_swarm = (DM_Swarm*)(dm)->data; \ 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)"); \ else \ 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)"); \ } /* Coordinate insertition/addition API */ /*@C DMSwarmSetPointsUniformCoordinates - Set point coordinates in a DMSwarm on a regular (ijk) grid Collective on DM Input parameters: + dm - the DMSwarm . min - minimum coordinate values in the x, y, z directions (array of length dim) . max - maximum coordinate values in the x, y, z directions (array of length dim) . npoints - number of points in each spatial direction (array of length dim) - mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES) Level: beginner Notes: When using mode = INSERT_VALUES, this method will reset the number of particles in the DMSwarm to be npoints[0]*npoints[1] (2D) or npoints[0]*npoints[1]*npoints[2] (3D). When using mode = ADD_VALUES, new points will be appended to any already existing in the DMSwarm .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType @*/ PETSC_EXTERN PetscErrorCode DMSwarmSetPointsUniformCoordinates(DM dm,PetscReal min[],PetscReal max[],PetscInt npoints[],InsertMode mode) { PetscErrorCode ierr; PetscReal gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL}; PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; PetscInt i,j,k,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found; Vec coorlocal; const PetscScalar *_coor; DM celldm; PetscReal dx[3]; PetscInt _npoints[] = { 0, 0, 1 }; Vec pos; PetscScalar *_pos; PetscReal *swarm_coor; PetscInt *swarm_cellid; PetscSF sfcell = NULL; const PetscSFNode *LA_sfcell; PetscFunctionBegin; DMSWARMPICVALID(dm); ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr); ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr); ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr); N = N / bs; ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr); for (i=0; i 1) { dx[b] = (max[b] - min[b])/((PetscReal)(npoints[b]-1)); } else { dx[b] = 0.0; } _npoints[b] = npoints[b]; } /* determine number of points living in the bounding box */ n_estimate = 0; for (k=0; k<_npoints[2]; k++) { for (j=0; j<_npoints[1]; j++) { for (i=0; i<_npoints[0]; i++) { PetscReal xp[] = {0.0,0.0,0.0}; PetscInt ijk[3]; PetscBool point_inside = PETSC_TRUE; ijk[0] = i; ijk[1] = j; ijk[2] = k; for (b=0; b gmax[b]) { point_inside = PETSC_FALSE; } } if (point_inside) { n_estimate++; } } } } /* create candidate list */ ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr); ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr); ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr); ierr = VecSetFromOptions(pos);CHKERRQ(ierr); ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr); n_estimate = 0; for (k=0; k<_npoints[2]; k++) { for (j=0; j<_npoints[1]; j++) { for (i=0; i<_npoints[0]; i++) { PetscReal xp[] = {0.0,0.0,0.0}; PetscInt ijk[3]; PetscBool point_inside = PETSC_TRUE; ijk[0] = i; ijk[1] = j; ijk[2] = k; for (b=0; b gmax[b]) { point_inside = PETSC_FALSE; } } if (point_inside) { for (b=0; b 0) { /* allocate space */ ierr = PetscMalloc1(bs*my_npoints,&my_coor);CHKERRQ(ierr); } else { my_coor = coor; } ierr = MPI_Bcast(my_coor,bs*my_npoints,MPIU_REAL,0,comm);CHKERRQ(ierr); } else { my_npoints = npoints; my_coor = coor; } /* determine the number of points living in the bounding box */ n_estimate = 0; for (i=0; i gmax[b]) { point_inside = PETSC_FALSE; } } if (point_inside) { n_estimate++; } } /* create candidate list */ ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr); ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr); ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr); ierr = VecSetFromOptions(pos);CHKERRQ(ierr); ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr); n_estimate = 0; for (i=0; i gmax[b]) { point_inside = PETSC_FALSE; } } if (point_inside) { for (b=0; b 0) { ierr = PetscFree(my_coor);CHKERRQ(ierr); } } ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr); ierr = VecDestroy(&pos);CHKERRQ(ierr); PetscFunctionReturn(0); } extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM,DM,DMSwarmPICLayoutType,PetscInt); extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM,DM,DMSwarmPICLayoutType,PetscInt); /*@C DMSwarmInsertPointsUsingCellDM - Insert point coordinates within each cell Not collective Input parameters: + dm - the DMSwarm . layout_type - method used to fill each cell with the cell DM - fill_param - parameter controlling how many points per cell are added (the meaning of this parameter is dependent on the layout type) Level: beginner Notes: The insert method will reset any previous defined points within the DMSwarm .seealso: DMSwarmPICLayoutType, DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType @*/ PETSC_EXTERN PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm,DMSwarmPICLayoutType layout_type,PetscInt fill_param) { PetscErrorCode ierr; DM celldm; PetscBool isDA,isPLEX; PetscFunctionBegin; DMSWARMPICVALID(dm); ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); if (isDA) { ierr = private_DMSwarmInsertPointsUsingCellDM_DA(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); } else if (isPLEX) { ierr = private_DMSwarmInsertPointsUsingCellDM_PLEX(dm,celldm,layout_type,fill_param);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); PetscFunctionReturn(0); } /* PETSC_EXTERN PetscErrorCode DMSwarmAddPointCoordinatesCellWise(DM dm,PetscInt cell,PetscInt npoints,PetscReal xi[],PetscBool proximity_initialization) { PetscFunctionBegin; PetscFunctionReturn(0); } */ /* Field projection API */ extern PetscErrorCode private_DMSwarmProjectFields_DA(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]); extern PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]); /*@C DMSwarmProjectFields - Project a set of swarm fields onto the cell DM Collective on Vec Input parameters: + dm - the DMSwarm . nfields - the number of swarm fields to project . fieldnames - the textual names of the swarm fields to project . fields - an array of Vec's of length nfields - reuse - flag indicating whether the array and contents of fields should be re-used or internally allocated Currently, the only available projection method consists of phi_i = \sum_{p=0}^{np} N_i(x_p) phi_p dJ / \sum_{p=0}^{np} N_i(x_p) dJ where phi_p is the swarm field at point p, N_i() is the cell DM basis function at vertex i, dJ is the determinant of the cell Jacobian and phi_i is the projected vertex value of the field phi. Level: beginner Notes: - If reuse = PETSC_FALSE, this function will allocate the array of Vec's, and each individual Vec. The user is responsible for destroying both the array and the individual Vec objects. - Only swarm fields registered with data type = PETSC_REAL can be projected onto the cell DM. - Only swarm fields of block size = 1 can currently be projected. - The only projection methods currently only support the DA (2D) and PLEX (triangles 2D). .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType @*/ PETSC_EXTERN PetscErrorCode DMSwarmProjectFields(DM dm,PetscInt nfields,const char *fieldnames[],Vec **fields,PetscBool reuse) { DM_Swarm *swarm = (DM_Swarm*)dm->data; DataField *gfield; DM celldm; PetscBool isDA,isPLEX; Vec *vecs; PetscInt f,nvecs; PetscInt project_type = 0; PetscErrorCode ierr; PetscFunctionBegin; DMSWARMPICVALID(dm); ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr); ierr = PetscMalloc1(nfields,&gfield);CHKERRQ(ierr); nvecs = 0; for (f=0; fdb,fieldnames[f],&gfield[f]);CHKERRQ(ierr); 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"); if (gfield[f]->bs != 1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields with block size = 1"); nvecs += gfield[f]->bs; } if (!reuse) { ierr = PetscMalloc1(nvecs,&vecs);CHKERRQ(ierr); for (f=0; fname);CHKERRQ(ierr); } } else { vecs = *fields; } ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr); if (isDA) { ierr = private_DMSwarmProjectFields_DA(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); } else if (isPLEX) { ierr = private_DMSwarmProjectFields_PLEX(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX"); ierr = PetscFree(gfield);CHKERRQ(ierr); if (!reuse) { *fields = vecs; } PetscFunctionReturn(0); } /*@C DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM Not collective Input parameter: . dm - the DMSwarm Output parameters: + ncells - the number of cells in the cell DM (optional argument, pass NULL to ignore) - count - array of length ncells containing the number of points per cell Level: beginner Notes: The array count is allocated internally and must be free'd by the user. .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType @*/ PETSC_EXTERN PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm,PetscInt *ncells,PetscInt **count) { PetscErrorCode ierr; PetscBool isvalid; PetscInt nel; PetscInt *sum; PetscFunctionBegin; ierr = DMSwarmSortGetIsValid(dm,&isvalid);CHKERRQ(ierr); nel = 0; if (isvalid) { PetscInt e; ierr = DMSwarmSortGetSizes(dm,&nel,NULL);CHKERRQ(ierr); ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr); for (e=0; e