Date: 2026-03-01T05:24:51+00:00

Actual source code: ex79.c

      1: #include <petsc.h>

      3: #if PetscDefined(HAVE_HYPRE_DEVICE)
      4: #include <petsc/private/petschypre.h>
      5: #endif

      7: static char help[] = "Solves a linear system with a block of right-hand sides, apply a preconditioner to the same block.\n\n";

      9: PetscErrorCode MatApply(PC pc, Mat X, Mat Y)
     10: {
     11:   PetscFunctionBeginUser;
     12:   PetscCall(MatCopy(X, Y, SAME_NONZERO_PATTERN));
     13:   PetscFunctionReturn(PETSC_SUCCESS);
     14: }

     16: int main(int argc, char **args)
     17: {
     18:   Mat                A, X, B; /* computed solutions and RHS */
     19:   KSP                ksp;     /* linear solver context */
     20:   PC                 pc;      /* preconditioner context */
     21:   PetscInt           m = 10;
     22:   PetscBool          flg, transpose = PETSC_FALSE, hypre_mat_on_device = PETSC_FALSE;
     23:   PetscLogEvent      event;
     24:   PetscEventPerfInfo info;

     26:   PetscFunctionBeginUser;
     27:   PetscCall(PetscInitialize(&argc, &args, NULL, help));
     28:   PetscCall(PetscLogDefaultBegin());
     29:   PetscCall(PetscOptionsGetInt(NULL, NULL, "-m", &m, NULL));
     30:   PetscCall(MatCreateAIJ(PETSC_COMM_WORLD, m, m, PETSC_DECIDE, PETSC_DECIDE, m, NULL, m, NULL, &A));
     31:   PetscCall(MatSetRandom(A, NULL));
     32:   PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
     33:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-transpose", &transpose, NULL));
     34:   PetscCall(MatShift(A, 10.0));
     35:   PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, PETSC_DECIDE, PETSC_DECIDE, m, NULL, &B));
     36:   PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, PETSC_DECIDE, PETSC_DECIDE, m, NULL, &X));
     37:   PetscCall(MatSetRandom(B, NULL));
     38:   PetscCall(MatSetFromOptions(A));
     39:   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &flg, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
     40:   if (flg) {
     41:     PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
     42:     PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
     43:   } else {
     44:     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &flg, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
     45:     if (flg) {
     46:       PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
     47:       PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
     48:     }
     49:   }
     50:   PetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
     51:   PetscCall(KSPSetOperators(ksp, A, A));
     52:   PetscCall(KSPSetFromOptions(ksp));
     53:   PetscCall(KSPGetPC(ksp, &pc));
     54: #if defined(PETSC_HAVE_HYPRE_DEVICE)
     55:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCHYPRE, &flg));
     56:   if (flg) {
     57:     HYPRE_MemoryLocation hmem;
     58:     PetscCallExternal(HYPRE_GetMemoryLocation, &hmem);
     59:     if (hmem == HYPRE_MEMORY_DEVICE) hypre_mat_on_device = PETSC_TRUE;
     60:   }
     61: #endif
     62:   if (!hypre_mat_on_device) {
     63:     PetscCall(PCShellSetMatApply(pc, MatApply));
     64:     PetscCall(PCShellSetMatApplyTranspose(pc, MatApply));
     65:   }
     66:   PetscCall(KSPMatSolve(ksp, B, X));
     67:   PetscCall(PCMatApply(pc, B, X));
     68:   if (transpose) {
     69:     PetscCall(KSPMatSolveTranspose(ksp, B, X));
     70:     PetscCall(PCMatApply(pc, B, X));
     71:     PetscCall(KSPMatSolve(ksp, B, X));
     72:   }
     73:   PetscCall(MatDestroy(&X));
     74:   PetscCall(MatDestroy(&B));
     75:   PetscCall(MatDestroy(&A));
     76:   PetscCall(KSPDestroy(&ksp));
     77:   PetscCall(PetscLogEventRegister("PCApply", PC_CLASSID, &event)); // there is no PCApplyTranspose event
     78:   PetscCall(PetscLogEventGetPerfInfo(PETSC_DETERMINE, event, &info));
     79:   PetscCheck(!PetscDefined(USE_LOG) || m <= 1 || !info.count, PetscObjectComm((PetscObject)ksp), PETSC_ERR_PLIB, "PCApply() called %d times", info.count);
     80:   PetscCall(PetscLogEventRegister("PCMatApply", PC_CLASSID, &event)); // there is no PCMatApplyTranspose event
     81:   PetscCall(PetscLogEventGetPerfInfo(PETSC_DETERMINE, event, &info));
     82:   PetscCheck(!PetscDefined(USE_LOG) || m <= 1 || info.count, PetscObjectComm((PetscObject)ksp), PETSC_ERR_PLIB, "PCMatApply() never called");
     83:   PetscCall(PetscFinalize());
     84:   return 0;
     85: }

     87: /*TEST
     88:    # KSPHPDDM does either pseudo-blocking or "true" blocking, all tests should succeed with other -ksp_hpddm_type
     89:    testset:
     90:       nsize: 1
     91:       args: -pc_type {{mat none shell gasm}shared output}
     92:       test:
     93:          suffix: 1
     94:          output_file: output/empty.out
     95:          args: -ksp_type preonly
     96:       test:
     97:          suffix: 1_hpddm
     98:          output_file: output/empty.out
     99:          requires: hpddm
    100:          args: -ksp_type hpddm -ksp_hpddm_type preonly

    102:    testset:
    103:       nsize: 1
    104:       args: -pc_type ksp -transpose
    105:       test:
    106:          suffix: 2
    107:          output_file: output/empty.out
    108:          args: -ksp_ksp_type preonly -ksp_type preonly
    109:       test:
    110:          suffix: 2_hpddm
    111:          output_file: output/empty.out
    112:          requires: hpddm
    113:          args: -ksp_ksp_type hpddm -ksp_type hpddm -ksp_hpddm_type preonly -ksp_ksp_hpddm_type preonly

    115:    testset:
    116:       nsize: 1
    117:       requires: h2opus
    118:       args: -pc_type h2opus -pc_h2opus_init_mat_h2opus_leafsize 10
    119:       test:
    120:          suffix: 3
    121:          output_file: output/empty.out
    122:          args: -ksp_type preonly
    123:       test:
    124:          suffix: 3_hpddm
    125:          output_file: output/empty.out
    126:          requires: hpddm
    127:          args: -ksp_type hpddm -ksp_hpddm_type preonly

    129:    testset:
    130:       nsize: 1
    131:       requires: spai
    132:       args: -pc_type spai
    133:       test:
    134:          suffix: 4
    135:          output_file: output/empty.out
    136:          args: -ksp_type preonly
    137:       test:
    138:          suffix: 4_hpddm
    139:          output_file: output/empty.out
    140:          requires: hpddm
    141:          args: -ksp_type hpddm -ksp_hpddm_type preonly
    142:    # special code path in PCMatApply() for PCBJACOBI when a block is shared by multiple processes
    143:    testset:
    144:       nsize: 2
    145:       args: -pc_type bjacobi -pc_bjacobi_blocks 1 -sub_pc_type none
    146:       test:
    147:          suffix: 5
    148:          output_file: output/empty.out
    149:          args: -ksp_type preonly -sub_ksp_type preonly
    150:       test:
    151:          suffix: 5_hpddm
    152:          output_file: output/empty.out
    153:          requires: hpddm
    154:          args: -ksp_type hpddm -ksp_hpddm_type preonly -sub_ksp_type hpddm
    155:    # special code path in PCMatApply() for PCGASM when a block is shared by multiple processes
    156:    testset:
    157:       nsize: 2
    158:       args: -pc_type gasm -pc_gasm_total_subdomains 1 -sub_pc_type none
    159:       test:
    160:          suffix: 6
    161:          output_file: output/empty.out
    162:          args: -ksp_type preonly -sub_ksp_type preonly
    163:       test:
    164:          suffix: 6_hpddm
    165:          output_file: output/empty.out
    166:          requires: hpddm
    167:          args: -ksp_type hpddm -ksp_hpddm_type preonly -sub_ksp_type hpddm

    169:    testset:
    170:       nsize: 1
    171:       requires: suitesparse
    172:       args: -pc_type qr
    173:       test:
    174:          suffix: 7
    175:          output_file: output/empty.out
    176:          args: -ksp_type preonly
    177:       test:
    178:          suffix: 7_hpddm
    179:          output_file: output/empty.out
    180:          requires: hpddm
    181:          args: -ksp_type hpddm -ksp_hpddm_type preonly

    183:    testset:
    184:       nsize: 1
    185:       requires: hpddm cuda
    186:       args: -mat_type aijcusparse -ksp_type hpddm
    187:       test:
    188:          suffix: 8_hpddm
    189:          output_file: output/empty.out
    190:       test:
    191:          suffix: 8_hpddm_transpose
    192:          output_file: output/empty.out
    193:          args: -pc_type icc -transpose

    195:    testset:
    196:       nsize: 1
    197:       args: -pc_type {{bjacobi lu ilu cholesky icc none shell}shared output} -transpose
    198:       test:
    199:          suffix: 1_transpose
    200:          output_file: output/empty.out
    201:          args: -ksp_type preonly
    202:       test:
    203:          suffix: 1_hpddm_transpose
    204:          output_file: output/empty.out
    205:          requires: hpddm
    206:          args: -ksp_type hpddm -ksp_hpddm_type preonly

    208:    testset:
    209:       nsize: 2
    210:       args: -pc_type asm -transpose
    211:       test:
    212:          suffix: 2_transpose
    213:          output_file: output/empty.out
    214:          args: -ksp_type preonly
    215:       test:
    216:          suffix: 2_hpddm_transpose
    217:          output_file: output/empty.out
    218:          requires: hpddm
    219:          args: -ksp_type hpddm -ksp_hpddm_type preonly

    221:    testset:
    222:       requires: hypre !complex
    223:       args: -pc_type hypre -pc_hypre_boomeramg_relax_type_all l1scaled-Jacobi -pc_hypre_boomeramg_no_CF
    224:       test:
    225:          suffix: 9
    226:          output_file: output/empty.out
    227:          args: -ksp_type preonly
    228:       test:
    229:          suffix: 9_hpddm
    230:          output_file: output/empty.out
    231:          requires: hpddm !hip
    232:          args: -ksp_type hpddm -ksp_max_it 15 -ksp_error_if_not_converged
    233:       test:
    234:          suffix: 9_cuda
    235:          output_file: output/empty.out
    236:          requires: cuda
    237:          args: -mat_type aijcusparse -ksp_type preonly

    239: TEST*/