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