1 #include <petsctao.h> /*I "petsctao.h" I*/ 2 #include <../src/tao/matrix/submatfree.h> 3 4 /*@C 5 MatCreateSubMatrixFree - Creates a reduced matrix by masking a 6 full matrix. 7 8 Collective 9 10 Input Parameters: 11 + mat - matrix of arbitrary type 12 . Rows - the rows that will be in the submatrix 13 - Cols - the columns that will be in the submatrix 14 15 Output Parameter: 16 . J - New matrix 17 18 Level: developer 19 20 Note: 21 The caller is responsible for destroying the input objects after matrix J has been destroyed. 22 23 .seealso: `MatCreate()` 24 @*/ 25 PetscErrorCode MatCreateSubMatrixFree(Mat mat, IS Rows, IS Cols, Mat *J) 26 { 27 MPI_Comm comm = PetscObjectComm((PetscObject)mat); 28 MatSubMatFreeCtx ctx; 29 PetscInt mloc, nloc, m, n; 30 31 PetscFunctionBegin; 32 PetscCall(PetscNew(&ctx)); 33 ctx->A = mat; 34 PetscCall(MatGetSize(mat, &m, &n)); 35 PetscCall(MatGetLocalSize(mat, &mloc, &nloc)); 36 PetscCall(MatCreateVecs(mat, NULL, &ctx->VC)); 37 ctx->VR = ctx->VC; 38 PetscCall(PetscObjectReference((PetscObject)mat)); 39 40 ctx->Rows = Rows; 41 ctx->Cols = Cols; 42 PetscCall(PetscObjectReference((PetscObject)Rows)); 43 PetscCall(PetscObjectReference((PetscObject)Cols)); 44 PetscCall(MatCreateShell(comm, mloc, nloc, m, n, ctx, J)); 45 PetscCall(MatShellSetManageScalingShifts(*J)); 46 PetscCall(MatShellSetOperation(*J, MATOP_MULT, (void (*)(void))MatMult_SMF)); 47 PetscCall(MatShellSetOperation(*J, MATOP_DESTROY, (void (*)(void))MatDestroy_SMF)); 48 PetscCall(MatShellSetOperation(*J, MATOP_VIEW, (void (*)(void))MatView_SMF)); 49 PetscCall(MatShellSetOperation(*J, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_SMF)); 50 PetscCall(MatShellSetOperation(*J, MATOP_DIAGONAL_SET, (void (*)(void))MatDiagonalSet_SMF)); 51 PetscCall(MatShellSetOperation(*J, MATOP_SHIFT, (void (*)(void))MatShift_SMF)); 52 PetscCall(MatShellSetOperation(*J, MATOP_EQUAL, (void (*)(void))MatEqual_SMF)); 53 PetscCall(MatShellSetOperation(*J, MATOP_SCALE, (void (*)(void))MatScale_SMF)); 54 PetscCall(MatShellSetOperation(*J, MATOP_TRANSPOSE, (void (*)(void))MatTranspose_SMF)); 55 PetscCall(MatShellSetOperation(*J, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_SMF)); 56 PetscCall(MatShellSetOperation(*J, MATOP_CREATE_SUBMATRICES, (void (*)(void))MatCreateSubMatrices_SMF)); 57 PetscCall(MatShellSetOperation(*J, MATOP_NORM, (void (*)(void))MatNorm_SMF)); 58 PetscCall(MatShellSetOperation(*J, MATOP_DUPLICATE, (void (*)(void))MatDuplicate_SMF)); 59 PetscCall(MatShellSetOperation(*J, MATOP_CREATE_SUBMATRIX, (void (*)(void))MatCreateSubMatrix_SMF)); 60 PetscCall(MatShellSetOperation(*J, MATOP_GET_ROW_MAX, (void (*)(void))MatDuplicate_SMF)); 61 62 PetscFunctionReturn(PETSC_SUCCESS); 63 } 64 65 PetscErrorCode MatSMFResetRowColumn(Mat mat, IS Rows, IS Cols) 66 { 67 MatSubMatFreeCtx ctx; 68 69 PetscFunctionBegin; 70 PetscCall(MatShellGetContext(mat, &ctx)); 71 PetscCall(ISDestroy(&ctx->Rows)); 72 PetscCall(ISDestroy(&ctx->Cols)); 73 PetscCall(PetscObjectReference((PetscObject)Rows)); 74 PetscCall(PetscObjectReference((PetscObject)Cols)); 75 ctx->Cols = Cols; 76 ctx->Rows = Rows; 77 PetscFunctionReturn(PETSC_SUCCESS); 78 } 79 80 PetscErrorCode MatMult_SMF(Mat mat, Vec a, Vec y) 81 { 82 MatSubMatFreeCtx ctx; 83 84 PetscFunctionBegin; 85 PetscCall(MatShellGetContext(mat, &ctx)); 86 PetscCall(VecCopy(a, ctx->VR)); 87 PetscCall(VecISSet(ctx->VR, ctx->Cols, 0.0)); 88 PetscCall(MatMult(ctx->A, ctx->VR, y)); 89 PetscCall(VecISSet(y, ctx->Rows, 0.0)); 90 PetscFunctionReturn(PETSC_SUCCESS); 91 } 92 93 PetscErrorCode MatMultTranspose_SMF(Mat mat, Vec a, Vec y) 94 { 95 MatSubMatFreeCtx ctx; 96 97 PetscFunctionBegin; 98 PetscCall(MatShellGetContext(mat, &ctx)); 99 PetscCall(VecCopy(a, ctx->VC)); 100 PetscCall(VecISSet(ctx->VC, ctx->Rows, 0.0)); 101 PetscCall(MatMultTranspose(ctx->A, ctx->VC, y)); 102 PetscCall(VecISSet(y, ctx->Cols, 0.0)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 PetscErrorCode MatDiagonalSet_SMF(Mat M, Vec D, InsertMode is) 107 { 108 MatSubMatFreeCtx ctx; 109 110 PetscFunctionBegin; 111 PetscCall(MatShellGetContext(M, &ctx)); 112 PetscCall(MatDiagonalSet(ctx->A, D, is)); 113 PetscFunctionReturn(PETSC_SUCCESS); 114 } 115 116 PetscErrorCode MatDestroy_SMF(Mat mat) 117 { 118 MatSubMatFreeCtx ctx; 119 120 PetscFunctionBegin; 121 PetscCall(MatShellGetContext(mat, &ctx)); 122 PetscCall(MatDestroy(&ctx->A)); 123 PetscCall(ISDestroy(&ctx->Rows)); 124 PetscCall(ISDestroy(&ctx->Cols)); 125 PetscCall(VecDestroy(&ctx->VC)); 126 PetscCall(PetscFree(ctx)); 127 PetscFunctionReturn(PETSC_SUCCESS); 128 } 129 130 PetscErrorCode MatView_SMF(Mat mat, PetscViewer viewer) 131 { 132 MatSubMatFreeCtx ctx; 133 134 PetscFunctionBegin; 135 PetscCall(MatShellGetContext(mat, &ctx)); 136 PetscCall(MatView(ctx->A, viewer)); 137 PetscFunctionReturn(PETSC_SUCCESS); 138 } 139 140 PetscErrorCode MatShift_SMF(Mat Y, PetscReal a) 141 { 142 MatSubMatFreeCtx ctx; 143 144 PetscFunctionBegin; 145 PetscCall(MatShellGetContext(Y, &ctx)); 146 PetscCall(MatShift(ctx->A, a)); 147 PetscFunctionReturn(PETSC_SUCCESS); 148 } 149 150 PetscErrorCode MatDuplicate_SMF(Mat mat, MatDuplicateOption op, Mat *M) 151 { 152 MatSubMatFreeCtx ctx; 153 154 PetscFunctionBegin; 155 PetscCall(MatShellGetContext(mat, &ctx)); 156 PetscCall(MatCreateSubMatrixFree(ctx->A, ctx->Rows, ctx->Cols, M)); 157 PetscFunctionReturn(PETSC_SUCCESS); 158 } 159 160 PetscErrorCode MatEqual_SMF(Mat A, Mat B, PetscBool *flg) 161 { 162 MatSubMatFreeCtx ctx1, ctx2; 163 PetscBool flg1, flg2, flg3; 164 165 PetscFunctionBegin; 166 PetscCall(MatShellGetContext(A, &ctx1)); 167 PetscCall(MatShellGetContext(B, &ctx2)); 168 PetscCall(ISEqual(ctx1->Rows, ctx2->Rows, &flg2)); 169 PetscCall(ISEqual(ctx1->Cols, ctx2->Cols, &flg3)); 170 if (flg2 == PETSC_FALSE || flg3 == PETSC_FALSE) { 171 *flg = PETSC_FALSE; 172 } else { 173 PetscCall(MatEqual(ctx1->A, ctx2->A, &flg1)); 174 if (flg1 == PETSC_FALSE) { 175 *flg = PETSC_FALSE; 176 } else { 177 *flg = PETSC_TRUE; 178 } 179 } 180 PetscFunctionReturn(PETSC_SUCCESS); 181 } 182 183 PetscErrorCode MatScale_SMF(Mat mat, PetscReal a) 184 { 185 MatSubMatFreeCtx ctx; 186 187 PetscFunctionBegin; 188 PetscCall(MatShellGetContext(mat, &ctx)); 189 PetscCall(MatScale(ctx->A, a)); 190 PetscFunctionReturn(PETSC_SUCCESS); 191 } 192 193 PetscErrorCode MatTranspose_SMF(Mat mat, Mat *B) 194 { 195 PetscFunctionBegin; 196 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support for transpose for MatCreateSubMatrixFree() matrix"); 197 PetscFunctionReturn(PETSC_SUCCESS); 198 } 199 200 PetscErrorCode MatGetDiagonal_SMF(Mat mat, Vec v) 201 { 202 MatSubMatFreeCtx ctx; 203 204 PetscFunctionBegin; 205 PetscCall(MatShellGetContext(mat, &ctx)); 206 PetscCall(MatGetDiagonal(ctx->A, v)); 207 PetscFunctionReturn(PETSC_SUCCESS); 208 } 209 210 PetscErrorCode MatGetRowMax_SMF(Mat M, Vec D) 211 { 212 MatSubMatFreeCtx ctx; 213 214 PetscFunctionBegin; 215 PetscCall(MatShellGetContext(M, &ctx)); 216 PetscCall(MatGetRowMax(ctx->A, D, NULL)); 217 PetscFunctionReturn(PETSC_SUCCESS); 218 } 219 220 PetscErrorCode MatCreateSubMatrices_SMF(Mat A, PetscInt n, IS *irow, IS *icol, MatReuse scall, Mat **B) 221 { 222 PetscInt i; 223 224 PetscFunctionBegin; 225 if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n + 1, B)); 226 227 for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SMF(A, irow[i], icol[i], scall, &(*B)[i])); 228 PetscFunctionReturn(PETSC_SUCCESS); 229 } 230 231 PetscErrorCode MatCreateSubMatrix_SMF(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 232 { 233 MatSubMatFreeCtx ctx; 234 235 PetscFunctionBegin; 236 PetscCall(MatShellGetContext(mat, &ctx)); 237 if (newmat) PetscCall(MatDestroy(&*newmat)); 238 PetscCall(MatCreateSubMatrixFree(ctx->A, isrow, iscol, newmat)); 239 PetscFunctionReturn(PETSC_SUCCESS); 240 } 241 242 PetscErrorCode MatGetRow_SMF(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt **cols, const PetscScalar **vals) 243 { 244 MatSubMatFreeCtx ctx; 245 246 PetscFunctionBegin; 247 PetscCall(MatShellGetContext(mat, &ctx)); 248 PetscCall(MatGetRow(ctx->A, row, ncols, cols, vals)); 249 PetscFunctionReturn(PETSC_SUCCESS); 250 } 251 252 PetscErrorCode MatRestoreRow_SMF(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt **cols, const PetscScalar **vals) 253 { 254 MatSubMatFreeCtx ctx; 255 256 PetscFunctionBegin; 257 PetscCall(MatShellGetContext(mat, &ctx)); 258 PetscCall(MatRestoreRow(ctx->A, row, ncols, cols, vals)); 259 PetscFunctionReturn(PETSC_SUCCESS); 260 } 261 262 PetscErrorCode MatGetColumnVector_SMF(Mat mat, Vec Y, PetscInt col) 263 { 264 MatSubMatFreeCtx ctx; 265 266 PetscFunctionBegin; 267 PetscCall(MatShellGetContext(mat, &ctx)); 268 PetscCall(MatGetColumnVector(ctx->A, Y, col)); 269 PetscFunctionReturn(PETSC_SUCCESS); 270 } 271 272 PetscErrorCode MatNorm_SMF(Mat mat, NormType type, PetscReal *norm) 273 { 274 MatSubMatFreeCtx ctx; 275 276 PetscFunctionBegin; 277 PetscCall(MatShellGetContext(mat, &ctx)); 278 if (type == NORM_FROBENIUS) { 279 *norm = 1.0; 280 } else if (type == NORM_1 || type == NORM_INFINITY) { 281 *norm = 1.0; 282 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm"); 283 PetscFunctionReturn(PETSC_SUCCESS); 284 } 285