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

Actual source code: fmg.c

      1: /*
      2:      Full multigrid using either additive or multiplicative V or W cycle
      3: */
      4: #include <petsc/private/pcmgimpl.h>

      6: PetscErrorCode PCMGFCycle_Private(PC pc, PC_MG_Levels **mglevels, PetscBool transpose, PetscBool matapp)
      7: {
      8:   PetscInt i, l = mglevels[0]->levels;

     10:   PetscFunctionBegin;
     11:   if (!transpose) {
     12:     /* restrict the RHS through all levels to coarsest. */
     13:     for (i = l - 1; i > 0; i--) {
     14:       if (mglevels[i]->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels[i]->eventinterprestrict, 0, 0, 0, 0));
     15:       if (matapp) PetscCall(MatMatRestrict(mglevels[i]->restrct, mglevels[i]->B, &mglevels[i - 1]->B));
     16:       else PetscCall(MatRestrict(mglevels[i]->restrct, mglevels[i]->b, mglevels[i - 1]->b));
     17:       if (mglevels[i]->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels[i]->eventinterprestrict, 0, 0, 0, 0));
     18:     }

     20:     /* work our way up through the levels */
     21:     if (matapp) {
     22:       if (!mglevels[0]->X) {
     23:         PetscCall(MatDuplicate(mglevels[0]->B, MAT_DO_NOT_COPY_VALUES, &mglevels[0]->X));
     24:       } else {
     25:         PetscCall(MatZeroEntries(mglevels[0]->X));
     26:       }
     27:     } else {
     28:       PetscCall(VecZeroEntries(mglevels[0]->x));
     29:     }
     30:     for (i = 0; i < l - 1; i++) {
     31:       PetscCall(PCMGMCycle_Private(pc, &mglevels[i], transpose, matapp, NULL));
     32:       if (mglevels[i + 1]->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels[i + 1]->eventinterprestrict, 0, 0, 0, 0));
     33:       if (matapp) PetscCall(MatMatInterpolate(mglevels[i + 1]->interpolate, mglevels[i]->X, &mglevels[i + 1]->X));
     34:       else PetscCall(MatInterpolate(mglevels[i + 1]->interpolate, mglevels[i]->x, mglevels[i + 1]->x));
     35:       if (mglevels[i + 1]->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels[i + 1]->eventinterprestrict, 0, 0, 0, 0));
     36:     }
     37:     PetscCall(PCMGMCycle_Private(pc, &mglevels[l - 1], transpose, matapp, NULL));
     38:   } else {
     39:     PetscCall(PCMGMCycle_Private(pc, &mglevels[l - 1], transpose, matapp, NULL));
     40:     for (i = l - 2; i >= 0; i--) {
     41:       if (mglevels[i + 1]->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels[i + 1]->eventinterprestrict, 0, 0, 0, 0));
     42:       if (matapp) PetscCall(MatMatRestrict(mglevels[i + 1]->interpolate, mglevels[i + 1]->X, &mglevels[i]->X));
     43:       else PetscCall(MatRestrict(mglevels[i + 1]->interpolate, mglevels[i + 1]->x, mglevels[i]->x));
     44:       if (mglevels[i + 1]->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels[i + 1]->eventinterprestrict, 0, 0, 0, 0));
     45:       PetscCall(PCMGMCycle_Private(pc, &mglevels[i], transpose, matapp, NULL));
     46:     }
     47:     for (i = 1; i < l; i++) {
     48:       if (mglevels[i]->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels[i]->eventinterprestrict, 0, 0, 0, 0));
     49:       if (matapp) PetscCall(MatMatInterpolate(mglevels[i]->restrct, mglevels[i - 1]->B, &mglevels[i]->B));
     50:       else PetscCall(MatInterpolate(mglevels[i]->restrct, mglevels[i - 1]->b, mglevels[i]->b));
     51:       if (mglevels[i]->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels[i]->eventinterprestrict, 0, 0, 0, 0));
     52:     }
     53:   }
     54:   PetscFunctionReturn(PETSC_SUCCESS);
     55: }

     57: PetscErrorCode PCMGKCycle_Private(PC pc, PC_MG_Levels **mglevels, PetscBool transpose, PetscBool matapp)
     58: {
     59:   PetscInt i, l = mglevels[0]->levels;

     61:   PetscFunctionBegin;
     62:   /* restrict the RHS through all levels to coarsest. */
     63:   for (i = l - 1; i > 0; i--) {
     64:     if (mglevels[i]->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels[i]->eventinterprestrict, 0, 0, 0, 0));
     65:     if (matapp) PetscCall(MatMatRestrict(mglevels[i]->restrct, mglevels[i]->B, &mglevels[i - 1]->B));
     66:     else PetscCall(MatRestrict(mglevels[i]->restrct, mglevels[i]->b, mglevels[i - 1]->b));
     67:     if (mglevels[i]->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels[i]->eventinterprestrict, 0, 0, 0, 0));
     68:   }

     70:   /* work our way up through the levels */
     71:   if (matapp) {
     72:     if (!mglevels[0]->X) {
     73:       PetscCall(MatDuplicate(mglevels[0]->B, MAT_DO_NOT_COPY_VALUES, &mglevels[0]->X));
     74:     } else {
     75:       PetscCall(MatZeroEntries(mglevels[0]->X));
     76:     }
     77:   } else {
     78:     PetscCall(VecZeroEntries(mglevels[0]->x));
     79:   }
     80:   for (i = 0; i < l - 1; i++) {
     81:     if (mglevels[i]->eventsmoothsolve) PetscCall(PetscLogEventBegin(mglevels[i]->eventsmoothsolve, 0, 0, 0, 0));
     82:     if (matapp) {
     83:       PetscCall(KSPMatSolve(mglevels[i]->smoothd, mglevels[i]->B, mglevels[i]->X));
     84:       PetscCall(KSPCheckSolve(mglevels[i]->smoothd, pc, NULL));
     85:     } else {
     86:       PetscCall(KSPSolve(mglevels[i]->smoothd, mglevels[i]->b, mglevels[i]->x));
     87:       PetscCall(KSPCheckSolve(mglevels[i]->smoothd, pc, mglevels[i]->x));
     88:     }
     89:     if (mglevels[i]->eventsmoothsolve) PetscCall(PetscLogEventEnd(mglevels[i]->eventsmoothsolve, 0, 0, 0, 0));
     90:     if (mglevels[i + 1]->eventinterprestrict) PetscCall(PetscLogEventBegin(mglevels[i + 1]->eventinterprestrict, 0, 0, 0, 0));
     91:     if (matapp) PetscCall(MatMatInterpolate(mglevels[i + 1]->interpolate, mglevels[i]->X, &mglevels[i + 1]->X));
     92:     else PetscCall(MatInterpolate(mglevels[i + 1]->interpolate, mglevels[i]->x, mglevels[i + 1]->x));
     93:     if (mglevels[i + 1]->eventinterprestrict) PetscCall(PetscLogEventEnd(mglevels[i + 1]->eventinterprestrict, 0, 0, 0, 0));
     94:   }
     95:   if (mglevels[l - 1]->eventsmoothsolve) PetscCall(PetscLogEventBegin(mglevels[l - 1]->eventsmoothsolve, 0, 0, 0, 0));
     96:   if (matapp) {
     97:     PetscCall(KSPMatSolve(mglevels[l - 1]->smoothd, mglevels[l - 1]->B, mglevels[l - 1]->X));
     98:     PetscCall(KSPCheckSolve(mglevels[l - 1]->smoothd, pc, NULL));
     99:   } else {
    100:     PetscCall(KSPSolve(mglevels[l - 1]->smoothd, mglevels[l - 1]->b, mglevels[l - 1]->x));
    101:     PetscCall(KSPCheckSolve(mglevels[l - 1]->smoothd, pc, mglevels[l - 1]->x));
    102:   }
    103:   if (mglevels[l - 1]->eventsmoothsolve) PetscCall(PetscLogEventEnd(mglevels[l - 1]->eventsmoothsolve, 0, 0, 0, 0));
    104:   PetscFunctionReturn(PETSC_SUCCESS);
    105: }