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