xref: /petsc/src/mat/tests/ex268.c (revision 1dd4f53ad195540140f7acf39402592096589281)
1*1dd4f53aSPierre Jolivet static char help[] = "Tests MATFACTORHTOOL\n\n";
2*1dd4f53aSPierre Jolivet 
3*1dd4f53aSPierre Jolivet #include <petscmat.h>
4*1dd4f53aSPierre Jolivet 
5*1dd4f53aSPierre Jolivet static PetscErrorCode GenEntries(PetscInt sdim, PetscInt M, PetscInt N, const PetscInt *J, const PetscInt *K, PetscScalar *ptr, void *ctx)
6*1dd4f53aSPierre Jolivet {
7*1dd4f53aSPierre Jolivet   PetscInt  d, j, k;
8*1dd4f53aSPierre Jolivet   PetscReal diff = 0.0, *coords = (PetscReal *)(ctx);
9*1dd4f53aSPierre Jolivet 
10*1dd4f53aSPierre Jolivet   PetscFunctionBeginUser;
11*1dd4f53aSPierre Jolivet   for (j = 0; j < M; j++) {
12*1dd4f53aSPierre Jolivet     for (k = 0; k < N; k++) {
13*1dd4f53aSPierre Jolivet       diff = 0.0;
14*1dd4f53aSPierre Jolivet       for (d = 0; d < sdim; d++) diff += (coords[J[j] * sdim + d] - coords[K[k] * sdim + d]) * (coords[J[j] * sdim + d] - coords[K[k] * sdim + d]);
15*1dd4f53aSPierre Jolivet       ptr[j + M * k] = 1.0 / (1.0e-1 + PetscSqrtReal(diff));
16*1dd4f53aSPierre Jolivet     }
17*1dd4f53aSPierre Jolivet   }
18*1dd4f53aSPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
19*1dd4f53aSPierre Jolivet }
20*1dd4f53aSPierre Jolivet 
21*1dd4f53aSPierre Jolivet int main(int argc, char **argv)
22*1dd4f53aSPierre Jolivet {
23*1dd4f53aSPierre Jolivet   Mat               A, Ad, F, Fd, X, Xd, B;
24*1dd4f53aSPierre Jolivet   Vec               x, xd, b;
25*1dd4f53aSPierre Jolivet   PetscInt          m = 100, dim = 3, M, K = 10, begin, n = 0;
26*1dd4f53aSPierre Jolivet   PetscMPIInt       size;
27*1dd4f53aSPierre Jolivet   PetscReal        *coords, *gcoords, norm, epsilon;
28*1dd4f53aSPierre Jolivet   MatHtoolKernelFn *kernel = GenEntries;
29*1dd4f53aSPierre Jolivet   PetscBool         flg, sym = PETSC_FALSE;
30*1dd4f53aSPierre Jolivet   PetscRandom       rdm;
31*1dd4f53aSPierre Jolivet   MatSolverType     type;
32*1dd4f53aSPierre Jolivet 
33*1dd4f53aSPierre Jolivet   PetscFunctionBeginUser;
34*1dd4f53aSPierre Jolivet   PetscCall(PetscInitialize(&argc, &argv, (char *)NULL, help));
35*1dd4f53aSPierre Jolivet   PetscCall(PetscOptionsGetInt(NULL, NULL, "-m_local", &m, NULL));
36*1dd4f53aSPierre Jolivet   PetscCall(PetscOptionsGetInt(NULL, NULL, "-n_local", &n, NULL));
37*1dd4f53aSPierre Jolivet   PetscCall(PetscOptionsGetInt(NULL, NULL, "-dim", &dim, NULL));
38*1dd4f53aSPierre Jolivet   PetscCall(PetscOptionsGetInt(NULL, NULL, "-K", &K, NULL));
39*1dd4f53aSPierre Jolivet   PetscCall(PetscOptionsGetBool(NULL, NULL, "-symmetric", &sym, NULL));
40*1dd4f53aSPierre Jolivet   PetscCall(PetscOptionsGetReal(NULL, NULL, "-mat_htool_epsilon", &epsilon, NULL));
41*1dd4f53aSPierre Jolivet   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
42*1dd4f53aSPierre Jolivet   M = size * m;
43*1dd4f53aSPierre Jolivet   PetscCall(PetscOptionsGetInt(NULL, NULL, "-M", &M, NULL));
44*1dd4f53aSPierre Jolivet   PetscCall(PetscMalloc1(m * dim, &coords));
45*1dd4f53aSPierre Jolivet   PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rdm));
46*1dd4f53aSPierre Jolivet   PetscCall(PetscRandomGetValuesReal(rdm, m * dim, coords));
47*1dd4f53aSPierre Jolivet   PetscCall(PetscCalloc1(M * dim, &gcoords));
48*1dd4f53aSPierre Jolivet   PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, PETSC_DECIDE, M, K, NULL, &B));
49*1dd4f53aSPierre Jolivet   PetscCall(MatSetRandom(B, rdm));
50*1dd4f53aSPierre Jolivet   PetscCall(MatGetOwnershipRange(B, &begin, NULL));
51*1dd4f53aSPierre Jolivet   PetscCall(PetscArraycpy(gcoords + begin * dim, coords, m * dim));
52*1dd4f53aSPierre Jolivet   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, gcoords, M * dim, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD));
53*1dd4f53aSPierre Jolivet   PetscCall(MatCreateHtoolFromKernel(PETSC_COMM_WORLD, m, m, M, M, dim, coords, coords, kernel, gcoords, &A));
54*1dd4f53aSPierre Jolivet   PetscCall(MatSetOption(A, MAT_SYMMETRIC, sym));
55*1dd4f53aSPierre Jolivet   PetscCall(MatSetFromOptions(A));
56*1dd4f53aSPierre Jolivet   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
57*1dd4f53aSPierre Jolivet   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
58*1dd4f53aSPierre Jolivet   PetscCall(MatConvert(A, MATDENSE, MAT_INITIAL_MATRIX, &Ad));
59*1dd4f53aSPierre Jolivet   PetscCall(MatMultEqual(A, Ad, 10, &flg));
60*1dd4f53aSPierre Jolivet   PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Ax != Adx");
61*1dd4f53aSPierre Jolivet   PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, PETSC_DECIDE, M, K, NULL, &X));
62*1dd4f53aSPierre Jolivet   PetscCall(MatCreateDense(PETSC_COMM_WORLD, m, PETSC_DECIDE, M, K, NULL, &Xd));
63*1dd4f53aSPierre Jolivet   PetscCall(MatViewFromOptions(A, NULL, "-A"));
64*1dd4f53aSPierre Jolivet   PetscCall(MatViewFromOptions(Ad, NULL, "-Ad"));
65*1dd4f53aSPierre Jolivet   PetscCall(MatViewFromOptions(B, NULL, "-B"));
66*1dd4f53aSPierre Jolivet   for (PetscInt i = 0; i < 2; ++i) {
67*1dd4f53aSPierre Jolivet     PetscCall(MatGetFactor(A, MATSOLVERHTOOL, i == 0 ? MAT_FACTOR_LU : MAT_FACTOR_CHOLESKY, &F));
68*1dd4f53aSPierre Jolivet     PetscCall(MatGetFactor(Ad, MATSOLVERPETSC, i == 0 ? MAT_FACTOR_LU : MAT_FACTOR_CHOLESKY, &Fd));
69*1dd4f53aSPierre Jolivet     PetscCall(MatFactorGetSolverType(F, &type));
70*1dd4f53aSPierre Jolivet     PetscCall(PetscStrncmp(type, MATSOLVERHTOOL, 5, &flg));
71*1dd4f53aSPierre Jolivet     PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "MATSOLVERHTOOL != htool");
72*1dd4f53aSPierre Jolivet     if (i == 0) {
73*1dd4f53aSPierre Jolivet       PetscCall(MatLUFactorSymbolic(F, A, NULL, NULL, NULL));
74*1dd4f53aSPierre Jolivet       PetscCall(MatLUFactorNumeric(F, A, NULL));
75*1dd4f53aSPierre Jolivet       PetscCall(MatLUFactorSymbolic(Fd, Ad, NULL, NULL, NULL));
76*1dd4f53aSPierre Jolivet       PetscCall(MatLUFactorNumeric(Fd, Ad, NULL));
77*1dd4f53aSPierre Jolivet     } else {
78*1dd4f53aSPierre Jolivet       PetscCall(MatCholeskyFactorSymbolic(F, A, NULL, NULL));
79*1dd4f53aSPierre Jolivet       PetscCall(MatCholeskyFactorNumeric(F, A, NULL));
80*1dd4f53aSPierre Jolivet       PetscCall(MatCholeskyFactorSymbolic(Fd, Ad, NULL, NULL));
81*1dd4f53aSPierre Jolivet       PetscCall(MatCholeskyFactorNumeric(Fd, Ad, NULL));
82*1dd4f53aSPierre Jolivet     }
83*1dd4f53aSPierre Jolivet     PetscCall(MatMatSolve(F, B, X));
84*1dd4f53aSPierre Jolivet     PetscCall(MatMatSolve(Fd, B, Xd));
85*1dd4f53aSPierre Jolivet     PetscCall(MatViewFromOptions(X, NULL, "-X"));
86*1dd4f53aSPierre Jolivet     PetscCall(MatViewFromOptions(Xd, NULL, "-Xd"));
87*1dd4f53aSPierre Jolivet     PetscCall(MatAXPY(Xd, -1.0, X, SAME_NONZERO_PATTERN));
88*1dd4f53aSPierre Jolivet     PetscCall(MatNorm(Xd, NORM_INFINITY, &norm));
89*1dd4f53aSPierre Jolivet     PetscCall(MatViewFromOptions(Xd, NULL, "-MatMatSolve"));
90*1dd4f53aSPierre Jolivet     if (norm > 0.01) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error: norm of residual for MatMatSolve %g\n", (double)norm));
91*1dd4f53aSPierre Jolivet     if (!PetscDefined(USE_COMPLEX) || i == 0) {
92*1dd4f53aSPierre Jolivet       PetscCall(MatMatSolveTranspose(F, B, X));
93*1dd4f53aSPierre Jolivet       PetscCall(MatMatSolveTranspose(Fd, B, Xd));
94*1dd4f53aSPierre Jolivet       PetscCall(MatAXPY(Xd, -1.0, X, SAME_NONZERO_PATTERN));
95*1dd4f53aSPierre Jolivet       PetscCall(MatNorm(Xd, NORM_INFINITY, &norm));
96*1dd4f53aSPierre Jolivet       PetscCall(MatViewFromOptions(Xd, NULL, "-MatMatSolveTranspose"));
97*1dd4f53aSPierre Jolivet       if (norm > 0.01) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error: norm of residual for MatMatSolveTranspose %g\n", (double)norm));
98*1dd4f53aSPierre Jolivet     }
99*1dd4f53aSPierre Jolivet     PetscCall(MatDenseGetColumnVecRead(B, 0, &b));
100*1dd4f53aSPierre Jolivet     PetscCall(MatDenseGetColumnVecWrite(X, 0, &x));
101*1dd4f53aSPierre Jolivet     PetscCall(MatDenseGetColumnVecWrite(Xd, 0, &xd));
102*1dd4f53aSPierre Jolivet     PetscCall(MatSolve(F, b, x));
103*1dd4f53aSPierre Jolivet     PetscCall(MatSolve(Fd, b, xd));
104*1dd4f53aSPierre Jolivet     PetscCall(VecAXPY(xd, -1.0, x));
105*1dd4f53aSPierre Jolivet     PetscCall(VecNorm(xd, NORM_INFINITY, &norm));
106*1dd4f53aSPierre Jolivet     PetscCall(MatViewFromOptions(Xd, NULL, "-MatSolve"));
107*1dd4f53aSPierre Jolivet     if (norm > 0.01) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error: norm of residual for MatSolve %g\n", (double)norm));
108*1dd4f53aSPierre Jolivet     if (!PetscDefined(USE_COMPLEX) || i == 0) {
109*1dd4f53aSPierre Jolivet       PetscCall(MatSolveTranspose(F, b, x));
110*1dd4f53aSPierre Jolivet       PetscCall(MatSolveTranspose(Fd, b, xd));
111*1dd4f53aSPierre Jolivet       PetscCall(VecAXPY(xd, -1.0, x));
112*1dd4f53aSPierre Jolivet       PetscCall(VecNorm(xd, NORM_INFINITY, &norm));
113*1dd4f53aSPierre Jolivet       PetscCall(MatViewFromOptions(Xd, NULL, "-MatSolveTranspose"));
114*1dd4f53aSPierre Jolivet       if (norm > 0.01) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error: norm of residual for MatSolveTranspose %g\n", (double)norm));
115*1dd4f53aSPierre Jolivet     }
116*1dd4f53aSPierre Jolivet     PetscCall(MatDenseRestoreColumnVecWrite(Xd, 0, &xd));
117*1dd4f53aSPierre Jolivet     PetscCall(MatDenseRestoreColumnVecWrite(X, 0, &x));
118*1dd4f53aSPierre Jolivet     PetscCall(MatDenseRestoreColumnVecRead(B, 0, &b));
119*1dd4f53aSPierre Jolivet     PetscCall(MatDestroy(&Fd));
120*1dd4f53aSPierre Jolivet     PetscCall(MatDestroy(&F));
121*1dd4f53aSPierre Jolivet   }
122*1dd4f53aSPierre Jolivet   PetscCall(MatDestroy(&Xd));
123*1dd4f53aSPierre Jolivet   PetscCall(MatDestroy(&X));
124*1dd4f53aSPierre Jolivet   PetscCall(PetscRandomDestroy(&rdm));
125*1dd4f53aSPierre Jolivet   PetscCall(MatDestroy(&Ad));
126*1dd4f53aSPierre Jolivet   PetscCall(MatDestroy(&A));
127*1dd4f53aSPierre Jolivet   PetscCall(MatDestroy(&B));
128*1dd4f53aSPierre Jolivet   PetscCall(PetscFree(gcoords));
129*1dd4f53aSPierre Jolivet   PetscCall(PetscFree(coords));
130*1dd4f53aSPierre Jolivet   PetscCall(PetscFinalize());
131*1dd4f53aSPierre Jolivet   return 0;
132*1dd4f53aSPierre Jolivet }
133*1dd4f53aSPierre Jolivet 
134*1dd4f53aSPierre Jolivet /*TEST
135*1dd4f53aSPierre Jolivet 
136*1dd4f53aSPierre Jolivet    build:
137*1dd4f53aSPierre Jolivet       requires: htool
138*1dd4f53aSPierre Jolivet 
139*1dd4f53aSPierre Jolivet    test:
140*1dd4f53aSPierre Jolivet       requires: htool
141*1dd4f53aSPierre Jolivet       suffix: 1
142*1dd4f53aSPierre Jolivet       nsize: 1
143*1dd4f53aSPierre Jolivet       args: -mat_htool_epsilon 1.0e-11
144*1dd4f53aSPierre Jolivet       output_file: output/empty.out
145*1dd4f53aSPierre Jolivet 
146*1dd4f53aSPierre Jolivet TEST*/
147