1 #define PETSCMAT_DLL 2 3 /* 4 This provides a matrix that applies a VecScatter to a vector. 5 */ 6 7 #include "private/matimpl.h" /*I "petscmat.h" I*/ 8 #include "private/vecimpl.h" 9 10 typedef struct { 11 VecScatter scatter; 12 } Mat_Scatter; 13 14 #undef __FUNCT__ 15 #define __FUNCT__ "MatScatterGetVecScatter" 16 /*@ 17 MatScatterGetVecScatter - Returns the user-provided scatter set with MatScatterSetVecScatter() 18 19 Not Collective, but not cannot use scatter if not used collectively on Mat 20 21 Input Parameter: 22 . mat - the matrix, should have been created with MatCreateScatter() or have type MATSCATTER 23 24 Output Parameter: 25 . scatter - the scatter context 26 27 Level: intermediate 28 29 .keywords: matrix, scatter, get 30 31 .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MATSCATTER 32 @*/ 33 PetscErrorCode PETSCMAT_DLLEXPORT MatScatterGetVecScatter(Mat mat,VecScatter *scatter) 34 { 35 Mat_Scatter *mscatter; 36 37 PetscFunctionBegin; 38 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 39 PetscValidPointer(scatter,2); 40 mscatter = (Mat_Scatter*)mat->data; 41 *scatter = mscatter->scatter; 42 PetscFunctionReturn(0); 43 } 44 45 #undef __FUNCT__ 46 #define __FUNCT__ "MatDestroy_Scatter" 47 PetscErrorCode MatDestroy_Scatter(Mat mat) 48 { 49 PetscErrorCode ierr; 50 Mat_Scatter *scatter = (Mat_Scatter*)mat->data; 51 52 PetscFunctionBegin; 53 if (scatter->scatter) {ierr = VecScatterDestroy(scatter->scatter);CHKERRQ(ierr);} 54 ierr = PetscFree(scatter);CHKERRQ(ierr); 55 PetscFunctionReturn(0); 56 } 57 58 #undef __FUNCT__ 59 #define __FUNCT__ "MatMult_Scatter" 60 PetscErrorCode MatMult_Scatter(Mat A,Vec x,Vec y) 61 { 62 Mat_Scatter *scatter = (Mat_Scatter*)A->data; 63 PetscErrorCode ierr; 64 65 PetscFunctionBegin; 66 if (!scatter->scatter) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()"); 67 ierr = VecZeroEntries(y);CHKERRQ(ierr); 68 ierr = VecScatterBegin(scatter->scatter,x,y,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 69 ierr = VecScatterEnd(scatter->scatter,x,y,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 70 PetscFunctionReturn(0); 71 } 72 73 #undef __FUNCT__ 74 #define __FUNCT__ "MatMultAdd_Scatter" 75 PetscErrorCode MatMultAdd_Scatter(Mat A,Vec x,Vec y,Vec z) 76 { 77 Mat_Scatter *scatter = (Mat_Scatter*)A->data; 78 PetscErrorCode ierr; 79 80 PetscFunctionBegin; 81 if (!scatter->scatter) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()"); 82 if (z != y) {ierr = VecCopy(y,z);CHKERRQ(ierr);} 83 ierr = VecScatterBegin(scatter->scatter,x,z,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 84 ierr = VecScatterEnd(scatter->scatter,x,z,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 85 PetscFunctionReturn(0); 86 } 87 88 #undef __FUNCT__ 89 #define __FUNCT__ "MatMultTranspose_Scatter" 90 PetscErrorCode MatMultTranspose_Scatter(Mat A,Vec x,Vec y) 91 { 92 Mat_Scatter *scatter = (Mat_Scatter*)A->data; 93 PetscErrorCode ierr; 94 95 PetscFunctionBegin; 96 if (!scatter->scatter) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()"); 97 ierr = VecZeroEntries(y);CHKERRQ(ierr); 98 ierr = VecScatterBegin(scatter->scatter,x,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 99 ierr = VecScatterEnd(scatter->scatter,x,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 100 PetscFunctionReturn(0); 101 } 102 103 #undef __FUNCT__ 104 #define __FUNCT__ "MatMultTransposeAdd_Scatter" 105 PetscErrorCode MatMultTransposeAdd_Scatter(Mat A,Vec x,Vec y,Vec z) 106 { 107 Mat_Scatter *scatter = (Mat_Scatter*)A->data; 108 PetscErrorCode ierr; 109 110 PetscFunctionBegin; 111 if (!scatter->scatter) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Need to first call MatScatterSetScatter()"); 112 if (z != y) {ierr = VecCopy(y,z);CHKERRQ(ierr);} 113 ierr = VecScatterBegin(scatter->scatter,x,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 114 ierr = VecScatterEnd(scatter->scatter,x,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 115 PetscFunctionReturn(0); 116 } 117 118 static struct _MatOps MatOps_Values = {0, 119 0, 120 0, 121 MatMult_Scatter, 122 /* 4*/ MatMultAdd_Scatter, 123 MatMultTranspose_Scatter, 124 MatMultTransposeAdd_Scatter, 125 0, 126 0, 127 0, 128 /*10*/ 0, 129 0, 130 0, 131 0, 132 0, 133 /*15*/ 0, 134 0, 135 0, 136 0, 137 0, 138 /*20*/ 0, 139 0, 140 0, 141 0, 142 0, 143 /*25*/ 0, 144 0, 145 0, 146 0, 147 0, 148 /*30*/ 0, 149 0, 150 0, 151 0, 152 0, 153 /*35*/ 0, 154 0, 155 0, 156 0, 157 0, 158 /*40*/ 0, 159 0, 160 0, 161 0, 162 0, 163 /*45*/ 0, 164 0, 165 0, 166 0, 167 0, 168 /*50*/ 0, 169 0, 170 0, 171 0, 172 0, 173 /*55*/ 0, 174 0, 175 0, 176 0, 177 0, 178 /*60*/ 0, 179 MatDestroy_Scatter, 180 0, 181 0, 182 0, 183 /*65*/ 0, 184 0, 185 0, 186 0, 187 0, 188 /*70*/ 0, 189 0, 190 0, 191 0, 192 0, 193 /*75*/ 0, 194 0, 195 0, 196 0, 197 0, 198 /*80*/ 0, 199 0, 200 0, 201 0, 202 0, 203 /*85*/ 0, 204 0, 205 0, 206 0, 207 0, 208 /*90*/ 0, 209 0, 210 0, 211 0, 212 0, 213 /*95*/ 0, 214 0, 215 0, 216 0}; 217 218 /*MC 219 MATSCATTER - MATSCATTER = "scatter" - A matrix type that simply applies a VecScatterBegin/End() 220 221 Level: advanced 222 223 .seealso: MatCreateScatter(), MatScatterSetVecScatter(), MatScatterGetVecScatter() 224 225 M*/ 226 227 EXTERN_C_BEGIN 228 #undef __FUNCT__ 229 #define __FUNCT__ "MatCreate_Scatter" 230 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_Scatter(Mat A) 231 { 232 Mat_Scatter *b; 233 PetscErrorCode ierr; 234 235 PetscFunctionBegin; 236 ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 237 ierr = PetscNewLog(A,Mat_Scatter,&b);CHKERRQ(ierr); 238 239 A->data = (void*)b; 240 241 ierr = PetscMapSetBlockSize(A->rmap,1);CHKERRQ(ierr); 242 ierr = PetscMapSetBlockSize(A->cmap,1);CHKERRQ(ierr); 243 ierr = PetscMapSetUp(A->rmap);CHKERRQ(ierr); 244 ierr = PetscMapSetUp(A->cmap);CHKERRQ(ierr); 245 246 A->assembled = PETSC_TRUE; 247 A->preallocated = PETSC_FALSE; 248 249 ierr = PetscObjectChangeTypeName((PetscObject)A,MATSCATTER);CHKERRQ(ierr); 250 PetscFunctionReturn(0); 251 } 252 EXTERN_C_END 253 254 #undef __FUNCT__ 255 #define __FUNCT__ "MatCreateScatter" 256 /*@C 257 MatCreateScatter - Creates a new matrix based on a VecScatter 258 259 Collective on MPI_Comm 260 261 Input Parameters: 262 + comm - MPI communicator 263 - scatter - a VecScatterContext 264 265 Output Parameter: 266 . A - the matrix 267 268 Level: intermediate 269 270 PETSc requires that matrices and vectors being used for certain 271 operations are partitioned accordingly. For example, when 272 creating a scatter matrix, A, that supports parallel matrix-vector 273 products using MatMult(A,x,y) the user should set the number 274 of local matrix rows to be the number of local elements of the 275 corresponding result vector, y. Note that this is information is 276 required for use of the matrix interface routines, even though 277 the scatter matrix may not actually be physically partitioned. 278 For example, 279 280 .keywords: matrix, scatter, create 281 282 .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER 283 @*/ 284 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A) 285 { 286 PetscErrorCode ierr; 287 288 PetscFunctionBegin; 289 ierr = MatCreate(comm,A);CHKERRQ(ierr); 290 ierr = MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 291 ierr = MatSetType(*A,MATSCATTER);CHKERRQ(ierr); 292 ierr = MatScatterSetVecScatter(*A,scatter);CHKERRQ(ierr); 293 PetscFunctionReturn(0); 294 } 295 296 #undef __FUNCT__ 297 #define __FUNCT__ "MatScatterSetVecScatter" 298 /*@ 299 MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator 300 301 Collective on Mat 302 303 Input Parameters: 304 + mat - the scatter matrix 305 - scatter - the scatter context create with VecScatterCreate() 306 307 Level: advanced 308 309 310 .seealso: MatCreateScatter(), MATSCATTER 311 @*/ 312 PetscErrorCode PETSCMAT_DLLEXPORT MatScatterSetVecScatter(Mat mat,VecScatter scatter) 313 { 314 Mat_Scatter *mscatter = (Mat_Scatter*)mat->data; 315 PetscErrorCode ierr; 316 317 PetscFunctionBegin; 318 PetscValidHeaderSpecific(mat,MAT_COOKIE,1); 319 PetscValidHeaderSpecific(scatter,VEC_SCATTER_COOKIE,2); 320 PetscCheckSameComm((PetscObject)scatter,1,(PetscObject)mat,2); 321 if (mat->rmap->n != scatter->to_n) SETERRQ2(PETSC_ERR_ARG_SIZ,"Number of local rows in matrix %D not equal local scatter size %D",mat->rmap->n,scatter->to_n); 322 if (mat->cmap->n != scatter->from_n) SETERRQ2(PETSC_ERR_ARG_SIZ,"Number of local columns in matrix %D not equal local scatter size %D",mat->cmap->n,scatter->from_n); 323 324 ierr = PetscObjectReference((PetscObject)scatter);CHKERRQ(ierr); 325 if (mscatter->scatter) {ierr = VecScatterDestroy(mscatter->scatter);CHKERRQ(ierr);} 326 mscatter->scatter = scatter; 327 PetscFunctionReturn(0); 328 } 329 330 331