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