1 2 static char help[] = "Tests LU, Cholesky factorization and MatMatSolve() for a ScaLAPACK dense matrix.\n\n"; 3 4 #include <petscmat.h> 5 6 int main(int argc,char **argv) 7 { 8 Mat A,F,B,X,C,Aher,G; 9 Vec b,x,c,d,e; 10 PetscInt m=5,n,p,i,j,nrows,ncols; 11 PetscScalar *v,*barray,rval; 12 PetscReal norm,tol=1.e5*PETSC_MACHINE_EPSILON; 13 PetscMPIInt size,rank; 14 PetscRandom rand; 15 const PetscInt *rows,*cols; 16 IS isrows,iscols; 17 PetscBool mats_view=PETSC_FALSE; 18 19 PetscFunctionBeginUser; 20 PetscCall(PetscInitialize(&argc,&argv,(char*) 0,help)); 21 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 22 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size)); 23 24 PetscCall(PetscRandomCreate(PETSC_COMM_WORLD,&rand)); 25 PetscCall(PetscRandomSetFromOptions(rand)); 26 27 /* Get local dimensions of matrices */ 28 PetscCall(PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL)); 29 n = m; 30 PetscCall(PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL)); 31 p = m/2; 32 PetscCall(PetscOptionsGetInt(NULL,NULL,"-p",&p,NULL)); 33 PetscCall(PetscOptionsHasName(NULL,NULL,"-mats_view",&mats_view)); 34 35 /* Create matrix A */ 36 PetscCall(PetscPrintf(PETSC_COMM_WORLD," Create ScaLAPACK matrix A\n")); 37 PetscCall(MatCreate(PETSC_COMM_WORLD,&A)); 38 PetscCall(MatSetSizes(A,m,n,PETSC_DECIDE,PETSC_DECIDE)); 39 PetscCall(MatSetType(A,MATSCALAPACK)); 40 PetscCall(MatSetFromOptions(A)); 41 PetscCall(MatSetUp(A)); 42 /* Set local matrix entries */ 43 PetscCall(MatGetOwnershipIS(A,&isrows,&iscols)); 44 PetscCall(ISGetLocalSize(isrows,&nrows)); 45 PetscCall(ISGetIndices(isrows,&rows)); 46 PetscCall(ISGetLocalSize(iscols,&ncols)); 47 PetscCall(ISGetIndices(iscols,&cols)); 48 PetscCall(PetscMalloc1(nrows*ncols,&v)); 49 for (i=0;i<nrows;i++) { 50 for (j=0;j<ncols;j++) { 51 PetscCall(PetscRandomGetValue(rand,&rval)); 52 v[i*ncols+j] = rval; 53 } 54 } 55 PetscCall(MatSetValues(A,nrows,rows,ncols,cols,v,INSERT_VALUES)); 56 PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 57 PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 58 PetscCall(ISRestoreIndices(isrows,&rows)); 59 PetscCall(ISRestoreIndices(iscols,&cols)); 60 PetscCall(ISDestroy(&isrows)); 61 PetscCall(ISDestroy(&iscols)); 62 PetscCall(PetscFree(v)); 63 if (mats_view) { 64 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "A: nrows %" PetscInt_FMT ", m %" PetscInt_FMT "; ncols %" PetscInt_FMT ", n %" PetscInt_FMT "\n",nrows,m,ncols,n)); 65 PetscCall(MatView(A,PETSC_VIEWER_STDOUT_WORLD)); 66 } 67 68 /* Create rhs matrix B */ 69 PetscCall(PetscPrintf(PETSC_COMM_WORLD," Create rhs matrix B\n")); 70 PetscCall(MatCreate(PETSC_COMM_WORLD,&B)); 71 PetscCall(MatSetSizes(B,m,p,PETSC_DECIDE,PETSC_DECIDE)); 72 PetscCall(MatSetType(B,MATSCALAPACK)); 73 PetscCall(MatSetFromOptions(B)); 74 PetscCall(MatSetUp(B)); 75 PetscCall(MatGetOwnershipIS(B,&isrows,&iscols)); 76 PetscCall(ISGetLocalSize(isrows,&nrows)); 77 PetscCall(ISGetIndices(isrows,&rows)); 78 PetscCall(ISGetLocalSize(iscols,&ncols)); 79 PetscCall(ISGetIndices(iscols,&cols)); 80 PetscCall(PetscMalloc1(nrows*ncols,&v)); 81 for (i=0;i<nrows;i++) { 82 for (j=0;j<ncols;j++) { 83 PetscCall(PetscRandomGetValue(rand,&rval)); 84 v[i*ncols+j] = rval; 85 } 86 } 87 PetscCall(MatSetValues(B,nrows,rows,ncols,cols,v,INSERT_VALUES)); 88 PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 89 PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 90 PetscCall(ISRestoreIndices(isrows,&rows)); 91 PetscCall(ISRestoreIndices(iscols,&cols)); 92 PetscCall(ISDestroy(&isrows)); 93 PetscCall(ISDestroy(&iscols)); 94 PetscCall(PetscFree(v)); 95 if (mats_view) { 96 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "B: nrows %" PetscInt_FMT ", m %" PetscInt_FMT "; ncols %" PetscInt_FMT ", p %" PetscInt_FMT "\n",nrows,m,ncols,p)); 97 PetscCall(MatView(B,PETSC_VIEWER_STDOUT_WORLD)); 98 } 99 100 /* Create rhs vector b and solution x (same size as b) */ 101 PetscCall(VecCreate(PETSC_COMM_WORLD,&b)); 102 PetscCall(VecSetSizes(b,m,PETSC_DECIDE)); 103 PetscCall(VecSetFromOptions(b)); 104 PetscCall(VecGetArray(b,&barray)); 105 for (j=0;j<m;j++) { 106 PetscCall(PetscRandomGetValue(rand,&rval)); 107 barray[j] = rval; 108 } 109 PetscCall(VecRestoreArray(b,&barray)); 110 PetscCall(VecAssemblyBegin(b)); 111 PetscCall(VecAssemblyEnd(b)); 112 if (mats_view) { 113 PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[%d] b: m %" PetscInt_FMT "\n",rank,m)); 114 PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT)); 115 PetscCall(VecView(b,PETSC_VIEWER_STDOUT_WORLD)); 116 } 117 PetscCall(VecDuplicate(b,&x)); 118 119 /* Create matrix X - same size as B */ 120 PetscCall(PetscPrintf(PETSC_COMM_WORLD," Create solution matrix X\n")); 121 PetscCall(MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&X)); 122 123 /* Cholesky factorization */ 124 /*------------------------*/ 125 PetscCall(PetscPrintf(PETSC_COMM_WORLD," Create ScaLAPACK matrix Aher\n")); 126 PetscCall(MatHermitianTranspose(A,MAT_INITIAL_MATRIX,&Aher)); 127 PetscCall(MatAXPY(Aher,1.0,A,SAME_NONZERO_PATTERN)); /* Aher = A + A^T */ 128 PetscCall(MatShift(Aher,100.0)); /* add 100.0 to diagonals of Aher to make it spd */ 129 if (mats_view) { 130 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Aher:\n")); 131 PetscCall(MatView(Aher,PETSC_VIEWER_STDOUT_WORLD)); 132 } 133 134 /* Cholesky factorization */ 135 /*------------------------*/ 136 PetscCall(PetscPrintf(PETSC_COMM_WORLD," Test Cholesky Solver \n")); 137 /* In-place Cholesky */ 138 /* Create matrix factor G, with a copy of Aher */ 139 PetscCall(MatDuplicate(Aher,MAT_COPY_VALUES,&G)); 140 141 /* G = L * L^T */ 142 PetscCall(MatCholeskyFactor(G,0,0)); 143 if (mats_view) { 144 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Cholesky Factor G:\n")); 145 PetscCall(MatView(G,PETSC_VIEWER_STDOUT_WORLD)); 146 } 147 148 /* Solve L * L^T x = b and L * L^T * X = B */ 149 PetscCall(MatSolve(G,b,x)); 150 PetscCall(MatMatSolve(G,B,X)); 151 PetscCall(MatDestroy(&G)); 152 153 /* Out-place Cholesky */ 154 PetscCall(MatGetFactor(Aher,MATSOLVERSCALAPACK,MAT_FACTOR_CHOLESKY,&G)); 155 PetscCall(MatCholeskyFactorSymbolic(G,Aher,0,NULL)); 156 PetscCall(MatCholeskyFactorNumeric(G,Aher,NULL)); 157 if (mats_view) PetscCall(MatView(G,PETSC_VIEWER_STDOUT_WORLD)); 158 PetscCall(MatSolve(G,b,x)); 159 PetscCall(MatMatSolve(G,B,X)); 160 PetscCall(MatDestroy(&G)); 161 162 /* Check norm(Aher*x - b) */ 163 PetscCall(VecCreate(PETSC_COMM_WORLD,&c)); 164 PetscCall(VecSetSizes(c,m,PETSC_DECIDE)); 165 PetscCall(VecSetFromOptions(c)); 166 PetscCall(MatMult(Aher,x,c)); 167 PetscCall(VecAXPY(c,-1.0,b)); 168 PetscCall(VecNorm(c,NORM_1,&norm)); 169 if (norm > tol) { 170 PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Warning: ||Aher*x - b||=%g for Cholesky\n",(double)norm)); 171 } 172 173 /* Check norm(Aher*X - B) */ 174 PetscCall(MatMatMult(Aher,X,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&C)); 175 PetscCall(MatAXPY(C,-1.0,B,SAME_NONZERO_PATTERN)); 176 PetscCall(MatNorm(C,NORM_1,&norm)); 177 if (norm > tol) { 178 PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Warning: ||Aher*X - B||=%g for Cholesky\n",(double)norm)); 179 } 180 181 /* LU factorization */ 182 /*------------------*/ 183 PetscCall(PetscPrintf(PETSC_COMM_WORLD," Test LU Solver \n")); 184 /* In-place LU */ 185 /* Create matrix factor F, with a copy of A */ 186 PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&F)); 187 /* Create vector d to test MatSolveAdd() */ 188 PetscCall(VecDuplicate(x,&d)); 189 PetscCall(VecCopy(x,d)); 190 191 /* PF=LU factorization */ 192 PetscCall(MatLUFactor(F,0,0,NULL)); 193 194 /* Solve LUX = PB */ 195 PetscCall(MatSolveAdd(F,b,d,x)); 196 PetscCall(MatMatSolve(F,B,X)); 197 PetscCall(MatDestroy(&F)); 198 199 /* Check norm(A*X - B) */ 200 PetscCall(VecCreate(PETSC_COMM_WORLD,&e)); 201 PetscCall(VecSetSizes(e,m,PETSC_DECIDE)); 202 PetscCall(VecSetFromOptions(e)); 203 PetscCall(MatMult(A,x,c)); 204 PetscCall(MatMult(A,d,e)); 205 PetscCall(VecAXPY(c,-1.0,e)); 206 PetscCall(VecAXPY(c,-1.0,b)); 207 PetscCall(VecNorm(c,NORM_1,&norm)); 208 if (norm > tol) { 209 PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Warning: ||A*x - b||=%g for LU\n",(double)norm)); 210 } 211 /* Reuse product C; replace Aher with A */ 212 PetscCall(MatProductReplaceMats(A,NULL,NULL,C)); 213 PetscCall(MatMatMult(A,X,MAT_REUSE_MATRIX,PETSC_DEFAULT,&C)); 214 PetscCall(MatAXPY(C,-1.0,B,SAME_NONZERO_PATTERN)); 215 PetscCall(MatNorm(C,NORM_1,&norm)); 216 if (norm > tol) { 217 PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Warning: ||A*X - B||=%g for LU\n",(double)norm)); 218 } 219 220 /* Out-place LU */ 221 PetscCall(MatGetFactor(A,MATSOLVERSCALAPACK,MAT_FACTOR_LU,&F)); 222 PetscCall(MatLUFactorSymbolic(F,A,0,0,NULL)); 223 PetscCall(MatLUFactorNumeric(F,A,NULL)); 224 if (mats_view) PetscCall(MatView(F,PETSC_VIEWER_STDOUT_WORLD)); 225 PetscCall(MatSolve(F,b,x)); 226 PetscCall(MatMatSolve(F,B,X)); 227 PetscCall(MatDestroy(&F)); 228 229 /* Free space */ 230 PetscCall(MatDestroy(&A)); 231 PetscCall(MatDestroy(&Aher)); 232 PetscCall(MatDestroy(&B)); 233 PetscCall(MatDestroy(&C)); 234 PetscCall(MatDestroy(&X)); 235 PetscCall(VecDestroy(&b)); 236 PetscCall(VecDestroy(&c)); 237 PetscCall(VecDestroy(&d)); 238 PetscCall(VecDestroy(&e)); 239 PetscCall(VecDestroy(&x)); 240 PetscCall(PetscRandomDestroy(&rand)); 241 PetscCall(PetscFinalize()); 242 return 0; 243 } 244 245 /*TEST 246 247 build: 248 requires: scalapack 249 250 test: 251 nsize: 2 252 output_file: output/ex245.out 253 254 test: 255 suffix: 2 256 nsize: 6 257 output_file: output/ex245.out 258 259 TEST*/ 260