Date: 2025-03-28T21:10:54+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;
     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:   if (transpose) {
     35:     PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &B));
     36:     PetscCall(MatAXPY(A, 1.0, B, DIFFERENT_NONZERO_PATTERN));
     37:     PetscCall(MatDestroy(&B));
     38:   }
     39:   PetscCall(MatShift(A, 10.0));
     40:   PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, PETSC_DECIDE, PETSC_DECIDE, m, NULL, &B));
     41:   PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, PETSC_DECIDE, PETSC_DECIDE, m, NULL, &X));
     42:   PetscCall(MatSetRandom(B, NULL));
     43:   PetscCall(MatSetFromOptions(A));
     44:   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &flg, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
     45:   if (flg) {
     46:     PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
     47:     PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
     48:   } else {
     49:     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &flg, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
     50:     if (flg) {
     51:       PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
     52:       PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
     53:     }
     54:   }
     55:   PetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
     56:   PetscCall(KSPSetOperators(ksp, A, A));
     57:   PetscCall(KSPSetFromOptions(ksp));
     58:   PetscCall(KSPGetPC(ksp, &pc));
     59:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCHYPRE, &flg));
     60:   if (flg && PetscDefined(HAVE_HYPRE_DEVICE)) {
     61: #if defined(HYPRE_USING_HIP)
     62:     PetscCall(MatConvert(A, MATAIJHIPSPARSE, MAT_INPLACE_MATRIX, &A));
     63:     PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
     64:     PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
     65: #elif defined(HYPRE_USING_CUDA)
     66:     PetscCall(MatConvert(A, MATAIJCUSPARSE, MAT_INPLACE_MATRIX, &A));
     67:     PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
     68:     PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
     69: #endif
     70:   } else PetscCall(PCShellSetMatApply(pc, MatApply));
     71:   PetscCall(KSPMatSolve(ksp, B, X));
     72:   PetscCall(PCMatApply(pc, B, X));
     73:   if (transpose) {
     74:     PetscCall(KSPMatSolveTranspose(ksp, B, X));
     75:     PetscCall(PCMatApply(pc, B, X));
     76:     PetscCall(KSPMatSolve(ksp, B, X));
     77:   }
     78:   PetscCall(MatDestroy(&X));
     79:   PetscCall(MatDestroy(&B));
     80:   PetscCall(MatDestroy(&A));
     81:   PetscCall(KSPDestroy(&ksp));
     82:   PetscCall(PetscLogEventRegister("PCApply", PC_CLASSID, &event));
     83:   PetscCall(PetscLogEventGetPerfInfo(PETSC_DETERMINE, event, &info));
     84:   PetscCheck(!PetscDefined(USE_LOG) || m <= 1 || !info.count, PetscObjectComm((PetscObject)ksp), PETSC_ERR_PLIB, "PCApply() called %d times", info.count);
     85:   PetscCall(PetscLogEventRegister("PCMatApply", PC_CLASSID, &event));
     86:   PetscCall(PetscLogEventGetPerfInfo(PETSC_DETERMINE, event, &info));
     87:   PetscCheck(!PetscDefined(USE_LOG) || m <= 1 || info.count, PetscObjectComm((PetscObject)ksp), PETSC_ERR_PLIB, "PCMatApply() never called");
     88:   PetscCall(PetscFinalize());
     89:   return 0;
     90: }

     92: /*TEST
     93:    # KSPHPDDM does either pseudo-blocking or "true" blocking, all tests should succeed with other -ksp_hpddm_type
     94:    testset:
     95:       nsize: 1
     96:       args: -pc_type {{bjacobi lu ilu mat cholesky icc none shell asm gasm}shared output}
     97:       test:
     98:          suffix: 1
     99:          output_file: output/ex77_preonly.out
    100:          args: -ksp_type preonly
    101:       test:
    102:          suffix: 1_hpddm
    103:          output_file: output/ex77_preonly.out
    104:          requires: hpddm
    105:          args: -ksp_type hpddm -ksp_hpddm_type preonly

    107:    testset:
    108:       nsize: 1
    109:       args: -pc_type ksp
    110:       test:
    111:          suffix: 2
    112:          output_file: output/ex77_preonly.out
    113:          args: -ksp_ksp_type preonly -ksp_type preonly
    114:       test:
    115:          suffix: 2_hpddm
    116:          output_file: output/ex77_preonly.out
    117:          requires: hpddm
    118:          args: -ksp_ksp_type hpddm -ksp_type hpddm -ksp_hpddm_type preonly -ksp_ksp_hpddm_type preonly

    120:    testset:
    121:       nsize: 1
    122:       requires: h2opus
    123:       args: -pc_type h2opus -pc_h2opus_init_mat_h2opus_leafsize 10
    124:       test:
    125:          suffix: 3
    126:          output_file: output/ex77_preonly.out
    127:          args: -ksp_type preonly
    128:       test:
    129:          suffix: 3_hpddm
    130:          output_file: output/ex77_preonly.out
    131:          requires: hpddm
    132:          args: -ksp_type hpddm -ksp_hpddm_type preonly

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

    174:    testset:
    175:       nsize: 1
    176:       requires: suitesparse
    177:       args: -pc_type qr
    178:       test:
    179:          suffix: 7
    180:          output_file: output/ex77_preonly.out
    181:          args: -ksp_type preonly
    182:       test:
    183:          suffix: 7_hpddm
    184:          output_file: output/ex77_preonly.out
    185:          requires: hpddm
    186:          args: -ksp_type hpddm -ksp_hpddm_type preonly

    188:    testset:
    189:       nsize: 1
    190:       requires: hpddm cuda
    191:       args: -mat_type aijcusparse -ksp_type hpddm
    192:       test:
    193:          suffix: 8_hpddm
    194:          output_file: output/ex77_preonly.out
    195:       test:
    196:          suffix: 8_hpddm_transpose
    197:          output_file: output/ex77_preonly.out
    198:          args: -pc_type icc -transpose

    200:    testset:
    201:       nsize: 1
    202:       args: -pc_type {{cholesky icc none}shared output} -transpose
    203:       test:
    204:          suffix: 1_transpose
    205:          output_file: output/ex77_preonly.out
    206:          args: -ksp_type preonly
    207:       test:
    208:          suffix: 1_hpddm_transpose
    209:          output_file: output/ex77_preonly.out
    210:          requires: hpddm
    211:          args: -ksp_type hpddm -ksp_hpddm_type preonly

    213:    testset:
    214:       requires: hypre !complex
    215:       args: -pc_type hypre -pc_hypre_boomeramg_relax_type_all l1scaled-Jacobi -pc_hypre_boomeramg_no_CF
    216:       test:
    217:          suffix: 9
    218:          output_file: output/ex77_preonly.out
    219:          args: -ksp_type preonly
    220:       test:
    221:          suffix: 9_hpddm
    222:          output_file: output/ex77_preonly.out
    223:          requires: hpddm !hip
    224:          args: -ksp_type hpddm -ksp_max_it 15 -ksp_error_if_not_converged

    226: TEST*/