Actual source code: transm.c

  1: #include <../src/mat/impls/shell/shell.h>

  3: static PetscErrorCode MatMult_Transpose(Mat N, Vec x, Vec y)
  4: {
  5:   Mat A;

  7:   PetscFunctionBegin;
  8:   PetscCall(MatShellGetContext(N, &A));
  9:   PetscCall(MatMultTranspose(A, x, y));
 10:   PetscFunctionReturn(PETSC_SUCCESS);
 11: }

 13: static PetscErrorCode MatMultTranspose_Transpose(Mat N, Vec x, Vec y)
 14: {
 15:   Mat A;

 17:   PetscFunctionBegin;
 18:   PetscCall(MatShellGetContext(N, &A));
 19:   PetscCall(MatMult(A, x, y));
 20:   PetscFunctionReturn(PETSC_SUCCESS);
 21: }

 23: static PetscErrorCode MatSolve_Transpose_LU(Mat N, Vec b, Vec x)
 24: {
 25:   Mat A;

 27:   PetscFunctionBegin;
 28:   PetscCall(MatShellGetContext(N, &A));
 29:   PetscCall(MatSolveTranspose(A, b, x));
 30:   PetscFunctionReturn(PETSC_SUCCESS);
 31: }

 33: static PetscErrorCode MatSolveAdd_Transpose_LU(Mat N, Vec b, Vec y, Vec x)
 34: {
 35:   Mat A;

 37:   PetscFunctionBegin;
 38:   PetscCall(MatShellGetContext(N, &A));
 39:   PetscCall(MatSolveTransposeAdd(A, b, y, x));
 40:   PetscFunctionReturn(PETSC_SUCCESS);
 41: }

 43: static PetscErrorCode MatSolveTranspose_Transpose_LU(Mat N, Vec b, Vec x)
 44: {
 45:   Mat A;

 47:   PetscFunctionBegin;
 48:   PetscCall(MatShellGetContext(N, &A));
 49:   PetscCall(MatSolve(A, b, x));
 50:   PetscFunctionReturn(PETSC_SUCCESS);
 51: }

 53: static PetscErrorCode MatSolveTransposeAdd_Transpose_LU(Mat N, Vec b, Vec y, Vec x)
 54: {
 55:   Mat A;

 57:   PetscFunctionBegin;
 58:   PetscCall(MatShellGetContext(N, &A));
 59:   PetscCall(MatSolveAdd(A, b, y, x));
 60:   PetscFunctionReturn(PETSC_SUCCESS);
 61: }

 63: static PetscErrorCode MatMatSolve_Transpose_LU(Mat N, Mat B, Mat X)
 64: {
 65:   Mat A;

 67:   PetscFunctionBegin;
 68:   PetscCall(MatShellGetContext(N, &A));
 69:   PetscCall(MatMatSolveTranspose(A, B, X));
 70:   PetscFunctionReturn(PETSC_SUCCESS);
 71: }

 73: static PetscErrorCode MatMatSolveTranspose_Transpose_LU(Mat N, Mat B, Mat X)
 74: {
 75:   Mat A;

 77:   PetscFunctionBegin;
 78:   PetscCall(MatShellGetContext(N, &A));
 79:   PetscCall(MatMatSolve(A, B, X));
 80:   PetscFunctionReturn(PETSC_SUCCESS);
 81: }

 83: static PetscErrorCode MatLUFactor_Transpose(Mat N, IS row, IS col, const MatFactorInfo *minfo)
 84: {
 85:   Mat A;

 87:   PetscFunctionBegin;
 88:   PetscCall(MatShellGetContext(N, &A));
 89:   PetscCall(MatLUFactor(A, col, row, minfo));
 90:   PetscCall(MatShellSetOperation(N, MATOP_SOLVE, (void (*)(void))MatSolve_Transpose_LU));
 91:   PetscCall(MatShellSetOperation(N, MATOP_SOLVE_ADD, (void (*)(void))MatSolveAdd_Transpose_LU));
 92:   PetscCall(MatShellSetOperation(N, MATOP_SOLVE_TRANSPOSE, (void (*)(void))MatSolveTranspose_Transpose_LU));
 93:   PetscCall(MatShellSetOperation(N, MATOP_SOLVE_TRANSPOSE_ADD, (void (*)(void))MatSolveTransposeAdd_Transpose_LU));
 94:   PetscCall(MatShellSetOperation(N, MATOP_MAT_SOLVE, (void (*)(void))MatMatSolve_Transpose_LU));
 95:   PetscCall(MatShellSetOperation(N, MATOP_MAT_SOLVE_TRANSPOSE, (void (*)(void))MatMatSolveTranspose_Transpose_LU));
 96:   PetscFunctionReturn(PETSC_SUCCESS);
 97: }

 99: static PetscErrorCode MatSolve_Transpose_Cholesky(Mat N, Vec b, Vec x)
100: {
101:   Mat A;

103:   PetscFunctionBegin;
104:   PetscCall(MatShellGetContext(N, &A));
105:   PetscCall(MatSolveTranspose(A, b, x));
106:   PetscFunctionReturn(PETSC_SUCCESS);
107: }

109: static PetscErrorCode MatSolveAdd_Transpose_Cholesky(Mat N, Vec b, Vec y, Vec x)
110: {
111:   Mat A;

113:   PetscFunctionBegin;
114:   PetscCall(MatShellGetContext(N, &A));
115:   PetscCall(MatSolveTransposeAdd(A, b, y, x));
116:   PetscFunctionReturn(PETSC_SUCCESS);
117: }

119: static PetscErrorCode MatSolveTranspose_Transpose_Cholesky(Mat N, Vec b, Vec x)
120: {
121:   Mat A;

123:   PetscFunctionBegin;
124:   PetscCall(MatShellGetContext(N, &A));
125:   PetscCall(MatSolve(A, b, x));
126:   PetscFunctionReturn(PETSC_SUCCESS);
127: }

129: static PetscErrorCode MatSolveTransposeAdd_Transpose_Cholesky(Mat N, Vec b, Vec y, Vec x)
130: {
131:   Mat A;

133:   PetscFunctionBegin;
134:   PetscCall(MatShellGetContext(N, &A));
135:   PetscCall(MatSolveAdd(A, b, y, x));
136:   PetscFunctionReturn(PETSC_SUCCESS);
137: }

139: static PetscErrorCode MatMatSolve_Transpose_Cholesky(Mat N, Mat B, Mat X)
140: {
141:   Mat A;

143:   PetscFunctionBegin;
144:   PetscCall(MatShellGetContext(N, &A));
145:   PetscCall(MatMatSolveTranspose(A, B, X));
146:   PetscFunctionReturn(PETSC_SUCCESS);
147: }

149: static PetscErrorCode MatMatSolveTranspose_Transpose_Cholesky(Mat N, Mat B, Mat X)
150: {
151:   Mat A;

153:   PetscFunctionBegin;
154:   PetscCall(MatShellGetContext(N, &A));
155:   PetscCall(MatMatSolve(A, B, X));
156:   PetscFunctionReturn(PETSC_SUCCESS);
157: }

159: static PetscErrorCode MatCholeskyFactor_Transpose(Mat N, IS perm, const MatFactorInfo *minfo)
160: {
161:   Mat A;

163:   PetscFunctionBegin;
164:   PetscCall(MatShellGetContext(N, &A));
165:   PetscCall(MatCholeskyFactor(A, perm, minfo));
166:   PetscCall(MatShellSetOperation(N, MATOP_SOLVE, (void (*)(void))MatSolve_Transpose_Cholesky));
167:   PetscCall(MatShellSetOperation(N, MATOP_SOLVE_ADD, (void (*)(void))MatSolveAdd_Transpose_Cholesky));
168:   PetscCall(MatShellSetOperation(N, MATOP_SOLVE_TRANSPOSE, (void (*)(void))MatSolveTranspose_Transpose_Cholesky));
169:   PetscCall(MatShellSetOperation(N, MATOP_SOLVE_TRANSPOSE_ADD, (void (*)(void))MatSolveTransposeAdd_Transpose_Cholesky));
170:   PetscCall(MatShellSetOperation(N, MATOP_MAT_SOLVE, (void (*)(void))MatMatSolve_Transpose_Cholesky));
171:   PetscCall(MatShellSetOperation(N, MATOP_MAT_SOLVE_TRANSPOSE, (void (*)(void))MatMatSolveTranspose_Transpose_Cholesky));
172:   PetscFunctionReturn(PETSC_SUCCESS);
173: }

175: static PetscErrorCode MatLUFactorNumeric_Transpose(Mat F, Mat N, const MatFactorInfo *info)
176: {
177:   Mat A, FA;

179:   PetscFunctionBegin;
180:   PetscCall(MatShellGetContext(N, &A));
181:   PetscCall(MatShellGetContext(F, &FA));
182:   PetscCall(MatLUFactorNumeric(FA, A, info));
183:   PetscCall(MatShellSetOperation(F, MATOP_SOLVE, (void (*)(void))MatSolve_Transpose_LU));
184:   PetscCall(MatShellSetOperation(F, MATOP_SOLVE_ADD, (void (*)(void))MatSolveAdd_Transpose_LU));
185:   PetscCall(MatShellSetOperation(F, MATOP_SOLVE_TRANSPOSE, (void (*)(void))MatSolveTranspose_Transpose_LU));
186:   PetscCall(MatShellSetOperation(F, MATOP_SOLVE_TRANSPOSE_ADD, (void (*)(void))MatSolveTransposeAdd_Transpose_LU));
187:   PetscCall(MatShellSetOperation(F, MATOP_MAT_SOLVE, (void (*)(void))MatMatSolve_Transpose_LU));
188:   PetscCall(MatShellSetOperation(F, MATOP_MAT_SOLVE_TRANSPOSE, (void (*)(void))MatMatSolveTranspose_Transpose_LU));
189:   PetscFunctionReturn(PETSC_SUCCESS);
190: }

192: static PetscErrorCode MatLUFactorSymbolic_Transpose(Mat F, Mat N, IS row, IS col, const MatFactorInfo *info)
193: {
194:   Mat A, FA;

196:   PetscFunctionBegin;
197:   PetscCall(MatShellGetContext(N, &A));
198:   PetscCall(MatShellGetContext(F, &FA));
199:   PetscCall(MatLUFactorSymbolic(FA, A, row, col, info));
200:   PetscCall(MatShellSetOperation(F, MATOP_LUFACTOR_NUMERIC, (void (*)(void))MatLUFactorNumeric_Transpose));
201:   PetscFunctionReturn(PETSC_SUCCESS);
202: }

204: static PetscErrorCode MatCholeskyFactorNumeric_Transpose(Mat F, Mat N, const MatFactorInfo *info)
205: {
206:   Mat A, FA;

208:   PetscFunctionBegin;
209:   PetscCall(MatShellGetContext(N, &A));
210:   PetscCall(MatShellGetContext(F, &FA));
211:   PetscCall(MatCholeskyFactorNumeric(FA, A, info));
212:   PetscCall(MatShellSetOperation(F, MATOP_SOLVE, (void (*)(void))MatSolve_Transpose_Cholesky));
213:   PetscCall(MatShellSetOperation(F, MATOP_SOLVE_ADD, (void (*)(void))MatSolveAdd_Transpose_Cholesky));
214:   PetscCall(MatShellSetOperation(F, MATOP_SOLVE_TRANSPOSE, (void (*)(void))MatSolveTranspose_Transpose_Cholesky));
215:   PetscCall(MatShellSetOperation(F, MATOP_SOLVE_TRANSPOSE_ADD, (void (*)(void))MatSolveTransposeAdd_Transpose_Cholesky));
216:   PetscCall(MatShellSetOperation(F, MATOP_MAT_SOLVE, (void (*)(void))MatMatSolve_Transpose_Cholesky));
217:   PetscCall(MatShellSetOperation(F, MATOP_MAT_SOLVE_TRANSPOSE, (void (*)(void))MatMatSolveTranspose_Transpose_Cholesky));
218:   PetscFunctionReturn(PETSC_SUCCESS);
219: }

221: static PetscErrorCode MatCholeskyFactorSymbolic_Transpose(Mat F, Mat N, IS perm, const MatFactorInfo *info)
222: {
223:   Mat A, FA;

225:   PetscFunctionBegin;
226:   PetscCall(MatShellGetContext(N, &A));
227:   PetscCall(MatShellGetContext(F, &FA));
228:   PetscCall(MatCholeskyFactorSymbolic(FA, A, perm, info));
229:   PetscCall(MatShellSetOperation(F, MATOP_CHOLESKY_FACTOR_NUMERIC, (void (*)(void))MatCholeskyFactorNumeric_Transpose));
230:   PetscFunctionReturn(PETSC_SUCCESS);
231: }

233: static PetscErrorCode MatGetFactor_Transpose(Mat N, MatSolverType type, MatFactorType ftype, Mat *F)
234: {
235:   Mat A, FA;

237:   PetscFunctionBegin;
238:   PetscCall(MatShellGetContext(N, &A));
239:   PetscCall(MatGetFactor(A, type, ftype, &FA));
240:   PetscCall(MatCreateTranspose(FA, F));
241:   if (ftype == MAT_FACTOR_LU) PetscCall(MatShellSetOperation(*F, MATOP_LUFACTOR_SYMBOLIC, (void (*)(void))MatLUFactorSymbolic_Transpose));
242:   else if (ftype == MAT_FACTOR_CHOLESKY) {
243:     PetscCall(MatShellSetOperation(*F, MATOP_CHOLESKY_FACTOR_SYMBOLIC, (void (*)(void))MatCholeskyFactorSymbolic_Transpose));
244:     PetscCall(MatPropagateSymmetryOptions(A, FA));
245:   } else SETERRQ(PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "Support for factor type %s not implemented in MATTRANSPOSEVIRTUAL", MatFactorTypes[ftype]);
246:   (*F)->factortype = ftype;
247:   PetscCall(MatDestroy(&FA));
248:   PetscFunctionReturn(PETSC_SUCCESS);
249: }

251: static PetscErrorCode MatDestroy_Transpose(Mat N)
252: {
253:   Mat A;

255:   PetscFunctionBegin;
256:   PetscCall(MatShellGetContext(N, &A));
257:   PetscCall(MatDestroy(&A));
258:   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatTransposeGetMat_C", NULL));
259:   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatProductSetFromOptions_anytype_C", NULL));
260:   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatShellSetContext_C", NULL));
261:   PetscCall(PetscObjectComposeFunction((PetscObject)N, "MatFactorGetSolverType_C", NULL));
262:   PetscFunctionReturn(PETSC_SUCCESS);
263: }

265: static PetscErrorCode MatGetInfo_Transpose(Mat N, MatInfoType flag, MatInfo *info)
266: {
267:   Mat A;

269:   PetscFunctionBegin;
270:   PetscCall(MatShellGetContext(N, &A));
271:   PetscCall(MatGetInfo(A, flag, info));
272:   PetscFunctionReturn(PETSC_SUCCESS);
273: }

275: static PetscErrorCode MatFactorGetSolverType_Transpose(Mat N, MatSolverType *type)
276: {
277:   Mat A;

279:   PetscFunctionBegin;
280:   PetscCall(MatShellGetContext(N, &A));
281:   PetscCall(MatFactorGetSolverType(A, type));
282:   PetscFunctionReturn(PETSC_SUCCESS);
283: }

285: static PetscErrorCode MatDuplicate_Transpose(Mat N, MatDuplicateOption op, Mat *m)
286: {
287:   Mat A, C;

289:   PetscFunctionBegin;
290:   PetscCall(MatShellGetContext(N, &A));
291:   PetscCall(MatDuplicate(A, op, &C));
292:   PetscCall(MatCreateTranspose(C, m));
293:   if (op == MAT_COPY_VALUES) PetscCall(MatCopy(N, *m, SAME_NONZERO_PATTERN));
294:   PetscCall(MatDestroy(&C));
295:   PetscFunctionReturn(PETSC_SUCCESS);
296: }

298: static PetscErrorCode MatHasOperation_Transpose(Mat mat, MatOperation op, PetscBool *has)
299: {
300:   Mat A;

302:   PetscFunctionBegin;
303:   PetscCall(MatShellGetContext(mat, &A));
304:   *has = PETSC_FALSE;
305:   if (op == MATOP_MULT || op == MATOP_MULT_ADD) {
306:     PetscCall(MatHasOperation(A, MATOP_MULT_TRANSPOSE, has));
307:   } else if (op == MATOP_MULT_TRANSPOSE || op == MATOP_MULT_TRANSPOSE_ADD) {
308:     PetscCall(MatHasOperation(A, MATOP_MULT, has));
309:   } else if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
310:   PetscFunctionReturn(PETSC_SUCCESS);
311: }

313: static PetscErrorCode MatProductSetFromOptions_Transpose(Mat D)
314: {
315:   Mat            A, B, C, Ain, Bin, Cin;
316:   PetscBool      Aistrans, Bistrans, Cistrans;
317:   PetscInt       Atrans, Btrans, Ctrans;
318:   MatProductType ptype;

320:   PetscFunctionBegin;
321:   MatCheckProduct(D, 1);
322:   A = D->product->A;
323:   B = D->product->B;
324:   C = D->product->C;
325:   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATTRANSPOSEVIRTUAL, &Aistrans));
326:   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATTRANSPOSEVIRTUAL, &Bistrans));
327:   PetscCall(PetscObjectTypeCompare((PetscObject)C, MATTRANSPOSEVIRTUAL, &Cistrans));
328:   PetscCheck(Aistrans || Bistrans || Cistrans, PetscObjectComm((PetscObject)D), PETSC_ERR_PLIB, "This should not happen");
329:   Atrans = 0;
330:   Ain    = A;
331:   while (Aistrans) {
332:     Atrans++;
333:     PetscCall(MatTransposeGetMat(Ain, &Ain));
334:     PetscCall(PetscObjectTypeCompare((PetscObject)Ain, MATTRANSPOSEVIRTUAL, &Aistrans));
335:   }
336:   Btrans = 0;
337:   Bin    = B;
338:   while (Bistrans) {
339:     Btrans++;
340:     PetscCall(MatTransposeGetMat(Bin, &Bin));
341:     PetscCall(PetscObjectTypeCompare((PetscObject)Bin, MATTRANSPOSEVIRTUAL, &Bistrans));
342:   }
343:   Ctrans = 0;
344:   Cin    = C;
345:   while (Cistrans) {
346:     Ctrans++;
347:     PetscCall(MatTransposeGetMat(Cin, &Cin));
348:     PetscCall(PetscObjectTypeCompare((PetscObject)Cin, MATTRANSPOSEVIRTUAL, &Cistrans));
349:   }
350:   Atrans = Atrans % 2;
351:   Btrans = Btrans % 2;
352:   Ctrans = Ctrans % 2;
353:   ptype  = D->product->type; /* same product type by default */
354:   if (Ain->symmetric == PETSC_BOOL3_TRUE) Atrans = 0;
355:   if (Bin->symmetric == PETSC_BOOL3_TRUE) Btrans = 0;
356:   if (Cin && Cin->symmetric == PETSC_BOOL3_TRUE) Ctrans = 0;

358:   if (Atrans || Btrans || Ctrans) {
359:     ptype = MATPRODUCT_UNSPECIFIED;
360:     switch (D->product->type) {
361:     case MATPRODUCT_AB:
362:       if (Atrans && Btrans) { /* At * Bt we do not have support for this */
363:         /* TODO custom implementation ? */
364:       } else if (Atrans) { /* At * B */
365:         ptype = MATPRODUCT_AtB;
366:       } else { /* A * Bt */
367:         ptype = MATPRODUCT_ABt;
368:       }
369:       break;
370:     case MATPRODUCT_AtB:
371:       if (Atrans && Btrans) { /* A * Bt */
372:         ptype = MATPRODUCT_ABt;
373:       } else if (Atrans) { /* A * B */
374:         ptype = MATPRODUCT_AB;
375:       } else { /* At * Bt we do not have support for this */
376:         /* TODO custom implementation ? */
377:       }
378:       break;
379:     case MATPRODUCT_ABt:
380:       if (Atrans && Btrans) { /* At * B */
381:         ptype = MATPRODUCT_AtB;
382:       } else if (Atrans) { /* At * Bt we do not have support for this */
383:         /* TODO custom implementation ? */
384:       } else { /* A * B */
385:         ptype = MATPRODUCT_AB;
386:       }
387:       break;
388:     case MATPRODUCT_PtAP:
389:       if (Atrans) { /* PtAtP */
390:         /* TODO custom implementation ? */
391:       } else { /* RARt */
392:         ptype = MATPRODUCT_RARt;
393:       }
394:       break;
395:     case MATPRODUCT_RARt:
396:       if (Atrans) { /* RAtRt */
397:         /* TODO custom implementation ? */
398:       } else { /* PtAP */
399:         ptype = MATPRODUCT_PtAP;
400:       }
401:       break;
402:     case MATPRODUCT_ABC:
403:       /* TODO custom implementation ? */
404:       break;
405:     default:
406:       SETERRQ(PetscObjectComm((PetscObject)D), PETSC_ERR_SUP, "ProductType %s is not supported", MatProductTypes[D->product->type]);
407:     }
408:   }
409:   PetscCall(MatProductReplaceMats(Ain, Bin, Cin, D));
410:   PetscCall(MatProductSetType(D, ptype));
411:   PetscCall(MatProductSetFromOptions(D));
412:   PetscFunctionReturn(PETSC_SUCCESS);
413: }

415: static PetscErrorCode MatGetDiagonal_Transpose(Mat N, Vec v)
416: {
417:   Mat A;

419:   PetscFunctionBegin;
420:   PetscCall(MatShellGetContext(N, &A));
421:   PetscCall(MatGetDiagonal(A, v));
422:   PetscFunctionReturn(PETSC_SUCCESS);
423: }

425: static PetscErrorCode MatCopy_Transpose(Mat A, Mat B, MatStructure str)
426: {
427:   Mat a, b;

429:   PetscFunctionBegin;
430:   PetscCall(MatShellGetContext(A, &a));
431:   PetscCall(MatShellGetContext(B, &b));
432:   PetscCall(MatCopy(a, b, str));
433:   PetscFunctionReturn(PETSC_SUCCESS);
434: }

436: static PetscErrorCode MatConvert_Transpose(Mat N, MatType newtype, MatReuse reuse, Mat *newmat)
437: {
438:   Mat         A;
439:   PetscScalar vscale = 1.0, vshift = 0.0;
440:   PetscBool   flg;

442:   PetscFunctionBegin;
443:   PetscCall(MatShellGetContext(N, &A));
444:   PetscCall(MatHasOperation(A, MATOP_TRANSPOSE, &flg));
445:   if (flg || N->ops->getrow) { /* if this condition is false, MatConvert_Shell() will be called in MatConvert_Basic(), so the following checks are not needed */
446:     PetscCheck(!((Mat_Shell *)N->data)->zrows && !((Mat_Shell *)N->data)->zcols, PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "Cannot call MatConvert() if MatZeroRows() or MatZeroRowsColumns() has been called on the input Mat");
447:     PetscCheck(!((Mat_Shell *)N->data)->axpy, PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "Cannot call MatConvert() if MatAXPY() has been called on the input Mat");
448:     PetscCheck(!((Mat_Shell *)N->data)->left && !((Mat_Shell *)N->data)->right, PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "Cannot call MatConvert() if MatDiagonalScale() has been called on the input Mat");
449:     PetscCheck(!((Mat_Shell *)N->data)->dshift, PetscObjectComm((PetscObject)N), PETSC_ERR_SUP, "Cannot call MatConvert() if MatDiagonalSet() has been called on the input Mat");
450:     vscale = ((Mat_Shell *)N->data)->vscale;
451:     vshift = ((Mat_Shell *)N->data)->vshift;
452:   }
453:   if (flg) {
454:     Mat B;

456:     PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &B));
457:     if (reuse != MAT_INPLACE_MATRIX) {
458:       PetscCall(MatConvert(B, newtype, reuse, newmat));
459:       PetscCall(MatDestroy(&B));
460:     } else {
461:       PetscCall(MatConvert(B, newtype, MAT_INPLACE_MATRIX, &B));
462:       PetscCall(MatHeaderReplace(N, &B));
463:     }
464:   } else { /* use basic converter as fallback */
465:     flg = (PetscBool)(N->ops->getrow != NULL);
466:     PetscCall(MatConvert_Basic(N, newtype, reuse, newmat));
467:   }
468:   if (flg) {
469:     PetscCall(MatScale(*newmat, vscale));
470:     PetscCall(MatShift(*newmat, vshift));
471:   }
472:   PetscFunctionReturn(PETSC_SUCCESS);
473: }

475: static PetscErrorCode MatTransposeGetMat_Transpose(Mat N, Mat *M)
476: {
477:   PetscFunctionBegin;
478:   PetscCall(MatShellGetContext(N, M));
479:   PetscFunctionReturn(PETSC_SUCCESS);
480: }

482: /*@
483:   MatTransposeGetMat - Gets the `Mat` object stored inside a `MATTRANSPOSEVIRTUAL`

485:   Logically Collective

487:   Input Parameter:
488: . A - the `MATTRANSPOSEVIRTUAL` matrix

490:   Output Parameter:
491: . M - the matrix object stored inside `A`

493:   Level: intermediate

495: .seealso: [](ch_matrices), `Mat`, `MATTRANSPOSEVIRTUAL`, `MatCreateTranspose()`
496: @*/
497: PetscErrorCode MatTransposeGetMat(Mat A, Mat *M)
498: {
499:   PetscFunctionBegin;
502:   PetscAssertPointer(M, 2);
503:   PetscUseMethod(A, "MatTransposeGetMat_C", (Mat, Mat *), (A, M));
504:   PetscFunctionReturn(PETSC_SUCCESS);
505: }

507: /*MC
508:    MATTRANSPOSEVIRTUAL - "transpose" - A matrix type that represents a virtual transpose of a matrix

510:   Level: advanced

512:   Developer Notes:
513:   This is implemented on top of `MATSHELL` to get support for scaling and shifting without requiring duplicate code

515:   Users can not call `MatShellSetOperation()` operations on this class, there is some error checking for that incorrect usage

517: .seealso: [](ch_matrices), `Mat`, `MATHERMITIANTRANSPOSEVIRTUAL`, `Mat`, `MatCreateHermitianTranspose()`, `MatCreateTranspose()`,
518:           `MATNORMALHERMITIAN`, `MATNORMAL`
519: M*/

521: /*@
522:   MatCreateTranspose - Creates a new matrix `MATTRANSPOSEVIRTUAL` object that behaves like A'

524:   Collective

526:   Input Parameter:
527: . A - the (possibly rectangular) matrix

529:   Output Parameter:
530: . N - the matrix that represents A'

532:   Level: intermediate

534:   Note:
535:   The transpose A' is NOT actually formed! Rather the new matrix
536:   object performs the matrix-vector product by using the `MatMultTranspose()` on
537:   the original matrix

539: .seealso: [](ch_matrices), `Mat`, `MATTRANSPOSEVIRTUAL`, `MatCreateNormal()`, `MatMult()`, `MatMultTranspose()`, `MatCreate()`,
540:           `MATNORMALHERMITIAN`
541: @*/
542: PetscErrorCode MatCreateTranspose(Mat A, Mat *N)
543: {
544:   VecType vtype;

546:   PetscFunctionBegin;
547:   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), N));
548:   PetscCall(PetscLayoutReference(A->rmap, &((*N)->cmap)));
549:   PetscCall(PetscLayoutReference(A->cmap, &((*N)->rmap)));
550:   PetscCall(MatSetType(*N, MATSHELL));
551:   PetscCall(MatShellSetContext(*N, A));
552:   PetscCall(PetscObjectReference((PetscObject)A));

554:   PetscCall(MatSetBlockSizes(*N, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs)));
555:   PetscCall(MatGetVecType(A, &vtype));
556:   PetscCall(MatSetVecType(*N, vtype));
557: #if defined(PETSC_HAVE_DEVICE)
558:   PetscCall(MatBindToCPU(*N, A->boundtocpu));
559: #endif
560:   PetscCall(MatSetUp(*N));

562:   PetscCall(MatShellSetOperation(*N, MATOP_DESTROY, (void (*)(void))MatDestroy_Transpose));
563:   PetscCall(MatShellSetOperation(*N, MATOP_MULT, (void (*)(void))MatMult_Transpose));
564:   PetscCall(MatShellSetOperation(*N, MATOP_MULT_TRANSPOSE, (void (*)(void))MatMultTranspose_Transpose));
565:   PetscCall(MatShellSetOperation(*N, MATOP_LUFACTOR, (void (*)(void))MatLUFactor_Transpose));
566:   PetscCall(MatShellSetOperation(*N, MATOP_CHOLESKYFACTOR, (void (*)(void))MatCholeskyFactor_Transpose));
567:   PetscCall(MatShellSetOperation(*N, MATOP_GET_FACTOR, (void (*)(void))MatGetFactor_Transpose));
568:   PetscCall(MatShellSetOperation(*N, MATOP_GETINFO, (void (*)(void))MatGetInfo_Transpose));
569:   PetscCall(MatShellSetOperation(*N, MATOP_DUPLICATE, (void (*)(void))MatDuplicate_Transpose));
570:   PetscCall(MatShellSetOperation(*N, MATOP_HAS_OPERATION, (void (*)(void))MatHasOperation_Transpose));
571:   PetscCall(MatShellSetOperation(*N, MATOP_GET_DIAGONAL, (void (*)(void))MatGetDiagonal_Transpose));
572:   PetscCall(MatShellSetOperation(*N, MATOP_COPY, (void (*)(void))MatCopy_Transpose));
573:   PetscCall(MatShellSetOperation(*N, MATOP_CONVERT, (void (*)(void))MatConvert_Transpose));

575:   PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatTransposeGetMat_C", MatTransposeGetMat_Transpose));
576:   PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatProductSetFromOptions_anytype_C", MatProductSetFromOptions_Transpose));
577:   PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatFactorGetSolverType_C", MatFactorGetSolverType_Transpose));
578:   PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatShellSetContext_C", MatShellSetContext_Immutable));
579:   PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatShellSetContextDestroy_C", MatShellSetContextDestroy_Immutable));
580:   PetscCall(PetscObjectComposeFunction((PetscObject)*N, "MatShellSetManageScalingShifts_C", MatShellSetManageScalingShifts_Immutable));
581:   PetscCall(PetscObjectChangeTypeName((PetscObject)*N, MATTRANSPOSEVIRTUAL));
582:   PetscFunctionReturn(PETSC_SUCCESS);
583: }