示例

C Interface:
#include "mg.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "mpi.h"
int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);
    MPI_Comm comm = MPI_COMM_WORLD;
    int rankSize;
    MPI_Comm_size(comm, &rankSize);
    int pId;
    MPI_Comm_rank(comm, &pId);
    // Init proc size
    int px = 1;
    int py = 1;
    int pz = 1;
    // Init matrix size
    int gx = 400;
    int gy = 200;
    int gz = 50;
    int lx = gx / px;
    int ly = gy / py;
    int lz = gz;
    int xbeg = (pId % px) * lx;
    int xend = xbeg + lx;
    int ybeg = (pId / px) * ly;
    int yend = ybeg + ly;
    int zbeg = 0;
    int zend = lz;
    int totLen = (lx + 2) * (ly + 2) * (lz + 2);
    // Init matrix A
    KmlMgMatrixH A = NULL;
    float *aValue = (float *)malloc(19 * totLen * sizeof(float));
    {
        KmlMgMatrixStore store;
        store.comm = comm;
        store.globalx = gx;
        store.globaly = gy;
        store.globalz = gz;
        store.procx = px;
        store.procy = py;
        store.procz = pz;
        store.xbeg = xbeg;
        store.xend = xend;
        store.ybeg = ybeg;
        store.yend = yend;
        store.zbeg = zbeg;
        store.zend = zend;
        store.xhalo = 1;
        store.yhalo = 1;
        store.zhalo = 1;
        store.crossPolar = 1;
        store.type = KML_MG_MATRIX_STORE_SPARSE_HALO;
        store.sparse.values = NULL;
        store.sparse.type = KML_MG_SPARSE_AOS;
        store.sparse.stencil = KML_MG_STENCIL_3D19;
        KmlMgMatrixOptions options;
        options.fieldMask = KML_MG_MATRIX_OPTIONS_INDEX_TYPE | KML_MG_MATRIX_OPTIONS_VALUE_TYPE;
        options.indexType = KML_MG_INDEX_INT32;
        options.valueType = KML_MG_VALUE_FP32;
        if (A != NULL) {
            KmlMgMatrixDestroy(A);
        }
        if (KmlMgMatrixCreate(&A, &store, &options) != KML_MG_OK) {
            printf("Create A error!\n");
        };
        // Set A values, order is Y-X-Z
        for (int i = 1; i < lx + 1; i++) {
            for (int j = 1; j < ly + 1; j++) {
                for (int k = 1; k < lz + 1; k++) {
                    for (int l = 0; l < 19; l++) {
                        aValue[j * (lx + 2) * (lz + 2) * 19 + i * (lz + 2) * 19 + k * 19 + l] = 0.5;
                    }
                    aValue[j * (lx + 2) * (lz + 2) * 19 + i * (lz + 2) * 19 + k * 19 + 9] *= 100;
                }
            }
        }
        if (KmlMgMatrixSetValues(A, (void *)aValue) != KML_MG_OK) {
            printf("SetValues of A error!\n");
        };
    }
    // Init B & X
    KmlMgMatrixH B = NULL;
    float *bValue = (float *)malloc(totLen * sizeof(float));
    KmlMgMatrixH X = NULL;
    float *xValue = (float *)malloc(totLen * sizeof(float));
    {
        KmlMgMatrixStore store;
        store.comm = comm;
        store.globalx = gx;
        store.globaly = gy;
        store.globalz = gz;
        store.procx = px;
        store.procy = py;
        store.procz = pz;
        store.xbeg = xbeg;
        store.xend = xend;
        store.ybeg = ybeg;
        store.yend = yend;
        store.zbeg = zbeg;
        store.zend = zend;
        store.xhalo = 1;
        store.yhalo = 1;
        store.zhalo = 1;
        store.crossPolar = 1;
        store.type = KML_MG_MATRIX_STORE_DENSE_COL_MAJOR_HALO;
        store.dense.values = NULL;
        store.dense.numDim = 1;
        store.dense.is2D = 0;
        store.dense.needCorner = 1;
        KmlMgMatrixOptions options;
        options.fieldMask = KML_MG_MATRIX_OPTIONS_INDEX_TYPE | KML_MG_MATRIX_OPTIONS_VALUE_TYPE;
        options.indexType = KML_MG_INDEX_INT32;
        options.valueType = KML_MG_VALUE_FP32;
        // Create B
        if (KmlMgMatrixCreate(&B, &store, &options) != KML_MG_OK) {
            printf("Create B error!\n");
        };
        // Set B values
        for (int i = 0; i < totLen; i++) {
            bValue[i] = 1.1;
        }
        if (KmlMgMatrixSetValues(B, (void *)bValue) != KML_MG_OK) {
            printf("SetValues of B error!\n");
        };
        // Create X
        if (KmlMgMatrixCreate(&X, &store, &options) != KML_MG_OK) {
            printf("Create X error!\n");
        };
        // Set X values
        for (int i = 0; i < totLen; i++) {
            xValue[i] = 0.0;
        }
        if (KmlMgMatrixSetValues(X, (void *)xValue) != KML_MG_OK) {
            printf("SetValues of X error!\n");
        };
    }
    // Init solver
    KmlMgSolverH solver = NULL;
    KmlMgPreconditionerOptions preOpt;  // need malloc and free
    {
        KmlMgSolverOptions solOpt;
        solOpt.fieldMask = KML_MG_SOLVER_OPTIONS_INDEX_TYPE | KML_MG_SOLVER_OPTIONS_KSP_VALUE_TYPE |
                           KML_MG_SOLVER_OPTIONS_PC_VALUE_TYPE | KML_MG_SOLVER_OPTIONS_PC_CALC_TYPE |
                           KML_MG_SOLVER_OPTIONS_KSP;
        solOpt.indexType = KML_MG_INDEX_INT32;
        solOpt.kspValueType = KML_MG_VALUE_FP32;
        solOpt.pcValueType = KML_MG_VALUE_FP32;
        solOpt.pcCalcType = KML_MG_VALUE_FP32;
        solOpt.ksp = KML_MG_SOLVER_GCR;
        if (solver != NULL) {
            KmlMgSolverDestroy(solver);
        }
        if (KmlMgSolverCreate(&solver, comm, &solOpt) != KML_MG_OK) {
            printf("solver Create error!\n");
        };
        preOpt.fieldMask = KML_MG_PRECONDITIONER_OPTIONS_INDEX_TYPE | KML_MG_PRECONDITIONER_OPTIONS_KSP_VALUE_TYPE |
                           KML_MG_PRECONDITIONER_OPTIONS_VALUE_TYPE | KML_MG_PRECONDITIONER_OPTIONS_CALC_TYPE |
                           KML_MG_PRECONDITIONER_OPTIONS_NUM_LEVEL | KML_MG_PRECONDITIONER_OPTIONS_SHIFT_LEVEL |
                           KML_MG_PRECONDITIONER_OPTIONS_CYCLE_TYPE | KML_MG_PRECONDITIONER_OPTIONS_SWEEP |
                           KML_MG_PRECONDITIONER_OPTIONS_XPSS | KML_MG_PRECONDITIONER_OPTIONS_SMOOTHER |
                           KML_MG_PRECONDITIONER_OPTIONS_WEIGHT | KML_MG_PRECONDITIONER_OPTIONS_COARSEN |
                           KML_MG_PRECONDITIONER_OPTIONS_RESTRICT | KML_MG_PRECONDITIONER_OPTIONS_PROLONG |
                           KML_MG_PRECONDITIONER_OPTIONS_ALPHA | KML_MG_PRECONDITIONER_OPTIONS_CONTROL;
        preOpt.indexType = KML_MG_INDEX_INT32;
        preOpt.kspValueType = KML_MG_VALUE_FP32;
        preOpt.valueType = KML_MG_VALUE_FP32;
        preOpt.calcType = KML_MG_VALUE_FP32;
        preOpt.numLevels = 4;
        preOpt.shiftLevelId = 1;
        preOpt.cycle = KML_MG_CYCLE_V;
        int *gridSweep = (int *)malloc(2 * sizeof(int));
        gridSweep[0] = 1;
        gridSweep[1] = 0;
        preOpt.gridSweep = gridSweep;
        int *xpss = (int *)malloc(4 * sizeof(int));
        xpss[0] = 1;
        xpss[1] = 1;
        xpss[2] = 1;
        xpss[3] = 1;
        preOpt.xpss = xpss;
        KmlMgSmootherType *smoother = (KmlMgSmootherType *)malloc(4 * sizeof(KmlMgSmootherType));
        smoother[0] = KML_MG_SMOOTHER_PLANE_ILU;
        smoother[1] = KML_MG_SMOOTHER_LINE_GS;
        smoother[2] = KML_MG_SMOOTHER_LINE_GS;
        smoother[3] = KML_MG_SMOOTHER_LINE_GS;
        preOpt.smoother = smoother;
        float *weight = (float *)malloc(4 * sizeof(float));
        weight[0] = 1.0;
        weight[1] = 1.0;
        weight[2] = 1.0;
        weight[3] = 1.0;
        preOpt.weight = weight;
        KmlMgCoarsenType *coarsen = (KmlMgCoarsenType *)malloc(4 * sizeof(KmlMgCoarsenType));
        coarsen[0] = KML_MG_COARSEN_SEMI_XY;
        coarsen[1] = KML_MG_COARSEN_SEMI_XY;
        coarsen[2] = KML_MG_COARSEN_SEMI_XY;
        coarsen[3] = KML_MG_COARSEN_SEMI_XY;
        preOpt.coarsen = coarsen;
        KmlMgRestInteType *rest = (KmlMgRestInteType *)malloc(4 * sizeof(KmlMgRestInteType));
        rest[0] = KML_MG_REST_INTE_CELL_2D16;
        rest[1] = KML_MG_REST_INTE_CELL_2D4;
        rest[2] = KML_MG_REST_INTE_CELL_2D4;
        rest[3] = KML_MG_REST_INTE_CELL_2D4;
        preOpt.rest = rest;
        KmlMgRestInteType *interp = (KmlMgRestInteType *)malloc(4 * sizeof(KmlMgRestInteType));
        interp[0] = KML_MG_REST_INTE_CELL_2D16;
        interp[1] = KML_MG_REST_INTE_CELL_2D16;
        interp[2] = KML_MG_REST_INTE_CELL_2D16;
        interp[3] = KML_MG_REST_INTE_CELL_2D16;
        preOpt.interp = interp;
        float *alpha = (float *)malloc(4 * sizeof(float));
        alpha[0] = 1.0;
        alpha[1] = 1.0;
        alpha[2] = 1.0;
        alpha[3] = 1.0;
        preOpt.alpha = alpha;
        int *control = (int *)malloc(4 * sizeof(int));
        control[0] = 0;
        control[1] = 1;
        control[2] = 1;
        control[3] = 1;
        preOpt.control = control;
        if (KmlMgSolverSetPreconditioner(solver, &preOpt) != KML_MG_OK) {
            printf("solver SetPreconditioner error!\n");
        }
        printf("SetPreconditioner done!\n");
        if (KmlMgSolverSetPreconditionerMatrix(solver, A) != KML_MG_OK) {
            printf("solver SetPreconditionerMatrix error!\n");
        }
        printf("SetPreconditionerMatrix done!\n");
        if (KmlMgSolverPrepare(solver, A) != KML_MG_OK) {
            printf("solver Prepare error!\n");
        }
        printf("Prepare done!\n");
    }
    // Apply
    {
        KmlMgApplyOptions opt;
        opt.fieldMask = KML_MG_APPLY_OPTIONS_USE_ZERO_GUESS | KML_MG_APPLY_OPTIONS_TOLERANCE_TYPE |
                        KML_MG_APPLY_OPTIONS_TOLERANCE | KML_MG_APPLY_OPTIONS_MAX_ITERATION |
                        KML_MG_APPLY_OPTIONS_RESTART_STEP;
        opt.useZeroGuess = 1;
        opt.toleranceType = KML_MG_TOLERANCE_ABS;
        opt.tolerance = 1e-6;
        opt.maxIteration = 200;
        opt.restartStep = 10;
        KmlMgStatus sta = KmlMgSolverApply(solver, B, X, &opt);
        if (sta != KML_MG_OK) {
            printf("solver Apply error!\n");
        }
        const char * str = KmlMgStatusStr(sta);
        printf("%s\n", str);
        printf("Apply done\n");
    }
    KmlMgMatrixInfo info;
    info.fieldMask = KML_MG_MATRIX_INFO_STORE;
    KmlMgMatrixQuery(X, &info);
    // Clear
    {
        if (A != NULL) {
            KmlMgMatrixDestroy(A);
        }
        if (aValue != NULL) {
            free((void *)aValue);
        }
        if (B != NULL) {
            KmlMgMatrixDestroy(B);
        }
        if (bValue != NULL) {
            free((void *)bValue);
        }
        if (X != NULL) {
            KmlMgMatrixDestroy(X);
        }
        if (xValue != NULL) {
            free((void *)xValue);
        }
        if (preOpt.gridSweep != NULL) {
            free((void *)preOpt.gridSweep);
        }
        if (preOpt.xpss != NULL) {
            free((void *)preOpt.xpss);
        }
        if (preOpt.smoother != NULL) {
            free((void *)preOpt.smoother);
        }
        if (preOpt.weight != NULL) {
            free((void *)preOpt.weight);
        }
        if (preOpt.coarsen != NULL) {
            free((void *)preOpt.coarsen);
        }
        if (preOpt.rest != NULL) {
            free((void *)preOpt.rest);
        }
        if (preOpt.interp != NULL) {
            free((void *)preOpt.interp);
        }
        if (preOpt.alpha != NULL) {
            free((void *)preOpt.alpha);
        }
        if (preOpt.control != NULL) {
            free((void *)preOpt.control);
        }
    }
    MPI_Finalize();
    return 0;
}