1 2 /* 3 This provides a matrix that applies a VecScatter to a vector. 4 */ 5 6 #include <petsc-private/matimpl.h> /*I "petscmat.h" I*/ 7 #include <petsc-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 ierr = VecScatterDestroy(&scatter->scatter);CHKERRQ(ierr); 53 ierr = PetscFree(mat->data);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(PetscObjectComm((PetscObject)A),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(PetscObjectComm((PetscObject)A),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(PetscObjectComm((PetscObject)A),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(PetscObjectComm((PetscObject)A),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 #undef __FUNCT__ 226 #define __FUNCT__ "MatCreate_Scatter" 227 PETSC_EXTERN PetscErrorCode MatCreate_Scatter(Mat A) 228 { 229 Mat_Scatter *b; 230 PetscErrorCode ierr; 231 232 PetscFunctionBegin; 233 ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 234 ierr = PetscNewLog(A,Mat_Scatter,&b);CHKERRQ(ierr); 235 236 A->data = (void*)b; 237 238 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 239 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 240 241 A->assembled = PETSC_TRUE; 242 A->preallocated = PETSC_FALSE; 243 244 ierr = PetscObjectChangeTypeName((PetscObject)A,MATSCATTER);CHKERRQ(ierr); 245 PetscFunctionReturn(0); 246 } 247 248 #undef __FUNCT__ 249 #define __FUNCT__ "MatCreateScatter" 250 /*@C 251 MatCreateScatter - Creates a new matrix based on a VecScatter 252 253 Collective on MPI_Comm 254 255 Input Parameters: 256 + comm - MPI communicator 257 - scatter - a VecScatterContext 258 259 Output Parameter: 260 . A - the matrix 261 262 Level: intermediate 263 264 PETSc requires that matrices and vectors being used for certain 265 operations are partitioned accordingly. For example, when 266 creating a scatter matrix, A, that supports parallel matrix-vector 267 products using MatMult(A,x,y) the user should set the number 268 of local matrix rows to be the number of local elements of the 269 corresponding result vector, y. Note that this is information is 270 required for use of the matrix interface routines, even though 271 the scatter matrix may not actually be physically partitioned. 272 273 .keywords: matrix, scatter, create 274 275 .seealso: MatScatterSetVecScatter(), MatScatterGetVecScatter(), MATSCATTER 276 @*/ 277 PetscErrorCode MatCreateScatter(MPI_Comm comm,VecScatter scatter,Mat *A) 278 { 279 PetscErrorCode ierr; 280 281 PetscFunctionBegin; 282 ierr = MatCreate(comm,A);CHKERRQ(ierr); 283 ierr = MatSetSizes(*A,scatter->to_n,scatter->from_n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 284 ierr = MatSetType(*A,MATSCATTER);CHKERRQ(ierr); 285 ierr = MatScatterSetVecScatter(*A,scatter);CHKERRQ(ierr); 286 ierr = MatSetUp(*A);CHKERRQ(ierr); 287 PetscFunctionReturn(0); 288 } 289 290 #undef __FUNCT__ 291 #define __FUNCT__ "MatScatterSetVecScatter" 292 /*@ 293 MatScatterSetVecScatter - sets that scatter that the matrix is to apply as its linear operator 294 295 Collective on Mat 296 297 Input Parameters: 298 + mat - the scatter matrix 299 - scatter - the scatter context create with VecScatterCreate() 300 301 Level: advanced 302 303 304 .seealso: MatCreateScatter(), MATSCATTER 305 @*/ 306 PetscErrorCode MatScatterSetVecScatter(Mat mat,VecScatter scatter) 307 { 308 Mat_Scatter *mscatter = (Mat_Scatter*)mat->data; 309 PetscErrorCode ierr; 310 311 PetscFunctionBegin; 312 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 313 PetscValidHeaderSpecific(scatter,VEC_SCATTER_CLASSID,2); 314 PetscCheckSameComm((PetscObject)scatter,1,(PetscObject)mat,2); 315 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); 316 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); 317 318 ierr = PetscObjectReference((PetscObject)scatter);CHKERRQ(ierr); 319 ierr = VecScatterDestroy(&mscatter->scatter);CHKERRQ(ierr); 320 321 mscatter->scatter = scatter; 322 PetscFunctionReturn(0); 323 } 324 325 326