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