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