1*55a74a43SLisandro Dalcin 2*55a74a43SLisandro Dalcin''' 3*55a74a43SLisandro DalcinEx23 from PETSc example files implemented for PETSc4py. 4*55a74a43SLisandro Dalcinhttps://petsc.org/release/src/ksp/ksp/tutorials/ex23.c.html 5*55a74a43SLisandro DalcinBy: Miguel Arriaga 6*55a74a43SLisandro Dalcin 7*55a74a43SLisandro DalcinSolves a tridiagonal linear system. 8*55a74a43SLisandro Dalcin 9*55a74a43SLisandro DalcinVec x, b, u; approx solution, RHS, exact solution 10*55a74a43SLisandro DalcinMat A; linear system matrix 11*55a74a43SLisandro DalcinKSP ksp; linear solver context 12*55a74a43SLisandro DalcinPC pc; preconditioner context 13*55a74a43SLisandro DalcinPetscReal norm; norm of solution error 14*55a74a43SLisandro Dalcin 15*55a74a43SLisandro Dalcin''' 16*55a74a43SLisandro Dalcinimport sys 17*55a74a43SLisandro Dalcinimport petsc4py 18*55a74a43SLisandro Dalcinpetsc4py.init(sys.argv) 19*55a74a43SLisandro Dalcinfrom petsc4py import PETSc 20*55a74a43SLisandro Dalcin 21*55a74a43SLisandro Dalcinimport numpy as np 22*55a74a43SLisandro Dalcin 23*55a74a43SLisandro Dalcincomm = PETSc.COMM_WORLD 24*55a74a43SLisandro Dalcinsize = comm.getSize() 25*55a74a43SLisandro Dalcinrank = comm.getRank() 26*55a74a43SLisandro Dalcinn = 12 # Size of problem 27*55a74a43SLisandro Dalcintol = 1E-11 # Tolerance of Result. tol=1000.*PETSC_MACHINE_EPSILON; 28*55a74a43SLisandro Dalcin 29*55a74a43SLisandro Dalcin''' 30*55a74a43SLisandro Dalcin- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 31*55a74a43SLisandro Dalcin Compute the matrix and right-hand-side vector that define 32*55a74a43SLisandro Dalcin the linear system, Ax = b. 33*55a74a43SLisandro Dalcin- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 34*55a74a43SLisandro Dalcin 35*55a74a43SLisandro DalcinCreate vectors. Note that we form 1 vector from scratch and 36*55a74a43SLisandro Dalcinthen duplicate as needed. For this simple case let PETSc decide how 37*55a74a43SLisandro Dalcinmany elements of the vector are stored on each processor. The second 38*55a74a43SLisandro Dalcinargument to VecSetSizes() below causes PETSc to decide. 39*55a74a43SLisandro Dalcin''' 40*55a74a43SLisandro Dalcin 41*55a74a43SLisandro Dalcinx = PETSc.Vec().create(comm=comm) 42*55a74a43SLisandro Dalcinx.setSizes(n) 43*55a74a43SLisandro Dalcinx.setFromOptions() 44*55a74a43SLisandro Dalcin 45*55a74a43SLisandro Dalcinb = x.duplicate() 46*55a74a43SLisandro Dalcinu = x.duplicate() 47*55a74a43SLisandro Dalcin 48*55a74a43SLisandro Dalcin''' 49*55a74a43SLisandro DalcinIdentify the starting and ending mesh points on each 50*55a74a43SLisandro Dalcinprocessor for the interior part of the mesh. We let PETSc decide 51*55a74a43SLisandro Dalcinabove. 52*55a74a43SLisandro Dalcin''' 53*55a74a43SLisandro Dalcin 54*55a74a43SLisandro Dalcinrstart,rend = x.getOwnershipRange() 55*55a74a43SLisandro Dalcinnlocal = x.getLocalSize() 56*55a74a43SLisandro Dalcin 57*55a74a43SLisandro Dalcin''' 58*55a74a43SLisandro DalcinCreate matrix. When using MatCreate(), the matrix format can 59*55a74a43SLisandro Dalcinbe specified at runtime. 60*55a74a43SLisandro Dalcin 61*55a74a43SLisandro DalcinPerformance tuning note: For problems of substantial size, 62*55a74a43SLisandro Dalcinpreallocation of matrix memory is crucial for attaining good 63*55a74a43SLisandro Dalcinperformance. See the matrix chapter of the users manual for details. 64*55a74a43SLisandro Dalcin 65*55a74a43SLisandro DalcinWe pass in nlocal as the "local" size of the matrix to force it 66*55a74a43SLisandro Dalcinto have the same parallel layout as the vector created above. 67*55a74a43SLisandro Dalcin''' 68*55a74a43SLisandro Dalcin 69*55a74a43SLisandro DalcinA = PETSc.Mat().create(comm=comm) 70*55a74a43SLisandro DalcinA.setSizes(n,nlocal) 71*55a74a43SLisandro DalcinA.setFromOptions() 72*55a74a43SLisandro DalcinA.setUp() 73*55a74a43SLisandro Dalcin 74*55a74a43SLisandro Dalcin''' 75*55a74a43SLisandro DalcinAssemble matrix. 76*55a74a43SLisandro Dalcin 77*55a74a43SLisandro DalcinThe linear system is distributed across the processors by 78*55a74a43SLisandro Dalcinchunks of contiguous rows, which correspond to contiguous 79*55a74a43SLisandro Dalcinsections of the mesh on which the problem is discretized. 80*55a74a43SLisandro DalcinFor matrix assembly, each processor contributes entries for 81*55a74a43SLisandro Dalcinthe part that it owns locally. 82*55a74a43SLisandro Dalcin''' 83*55a74a43SLisandro Dalcin 84*55a74a43SLisandro Dalcincol = np.zeros(3,dtype=PETSc.IntType) 85*55a74a43SLisandro Dalcinvalue = np.zeros(3,dtype=PETSc.ScalarType) 86*55a74a43SLisandro Dalcin 87*55a74a43SLisandro Dalcinif not rstart: 88*55a74a43SLisandro Dalcin rstart = 1 89*55a74a43SLisandro Dalcin i = 0; col[0] = 0; col[1] = 1; value[0] = 2.0; value[1] = -1.0 90*55a74a43SLisandro Dalcin A.setValues(i,col[0:2],value[0:2]) 91*55a74a43SLisandro Dalcin 92*55a74a43SLisandro Dalcinif rend == n: 93*55a74a43SLisandro Dalcin rend = n-1 94*55a74a43SLisandro Dalcin i = n-1; col[0] = n-2; col[1] = n-1; value[0] = -1.0; value[1] = 2.0 95*55a74a43SLisandro Dalcin A.setValues(i,col[0:2],value[0:2]) 96*55a74a43SLisandro Dalcin 97*55a74a43SLisandro Dalcin 98*55a74a43SLisandro Dalcin''' Set entries corresponding to the mesh interior ''' 99*55a74a43SLisandro Dalcinvalue[0] = -1.0; value[1] = 2.0; value[2] = -1.0 100*55a74a43SLisandro Dalcinfor i in range(rstart,rend): 101*55a74a43SLisandro Dalcin col[0] = i-1; col[1] = i; col[2] = i+1 102*55a74a43SLisandro Dalcin A.setValues(i,col,value) 103*55a74a43SLisandro Dalcin 104*55a74a43SLisandro Dalcin 105*55a74a43SLisandro Dalcin''' Assemble the matrix ''' 106*55a74a43SLisandro DalcinA.assemblyBegin(A.AssemblyType.FINAL) 107*55a74a43SLisandro DalcinA.assemblyEnd(A.AssemblyType.FINAL) 108*55a74a43SLisandro Dalcin 109*55a74a43SLisandro Dalcin''' Set exact solution; then compute right-hand-side vector. ''' 110*55a74a43SLisandro Dalcinu.set(1.0) 111*55a74a43SLisandro Dalcinb = A(u) 112*55a74a43SLisandro Dalcin 113*55a74a43SLisandro Dalcin''' 114*55a74a43SLisandro Dalcin- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 115*55a74a43SLisandro Dalcin Create the linear solver and set various options 116*55a74a43SLisandro Dalcin- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ''' 117*55a74a43SLisandro Dalcin''' 118*55a74a43SLisandro DalcinCreate linear solver context 119*55a74a43SLisandro Dalcin''' 120*55a74a43SLisandro Dalcinksp = PETSc.KSP().create() 121*55a74a43SLisandro Dalcin 122*55a74a43SLisandro Dalcin''' 123*55a74a43SLisandro DalcinSet operators. Here the matrix that defines the linear system 124*55a74a43SLisandro Dalcinalso serves as the preconditioning matrix. 125*55a74a43SLisandro Dalcin''' 126*55a74a43SLisandro Dalcinksp.setOperators(A,A) 127*55a74a43SLisandro Dalcin 128*55a74a43SLisandro Dalcin''' 129*55a74a43SLisandro DalcinSet linear solver defaults for this problem (optional). 130*55a74a43SLisandro Dalcin - By extracting the KSP and PC contexts from the KSP context, 131*55a74a43SLisandro Dalcin we can then directly call any KSP and PC routines to set 132*55a74a43SLisandro Dalcin various options. 133*55a74a43SLisandro Dalcin - The following four statements are optional; all of these 134*55a74a43SLisandro Dalcin parameters could alternatively be specified at runtime via 135*55a74a43SLisandro Dalcin KSPSetFromOptions(); 136*55a74a43SLisandro Dalcin''' 137*55a74a43SLisandro Dalcinpc = ksp.getPC() 138*55a74a43SLisandro Dalcinpc.setType('jacobi') 139*55a74a43SLisandro Dalcinksp.setTolerances(rtol=1.e-7) 140*55a74a43SLisandro Dalcin 141*55a74a43SLisandro Dalcin''' 142*55a74a43SLisandro DalcinSet runtime options, e.g., 143*55a74a43SLisandro Dalcin-ksp_type <type> -pc_type <type> -ksp_monitor -ksp_rtol <rtol> 144*55a74a43SLisandro DalcinThese options will override those specified above as long as 145*55a74a43SLisandro DalcinKSPSetFromOptions() is called _after_ any other customization 146*55a74a43SLisandro Dalcinroutines. 147*55a74a43SLisandro Dalcin''' 148*55a74a43SLisandro Dalcinksp.setFromOptions() 149*55a74a43SLisandro Dalcin 150*55a74a43SLisandro Dalcin''' 151*55a74a43SLisandro Dalcin- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 152*55a74a43SLisandro Dalcin Solve the linear system 153*55a74a43SLisandro Dalcin- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ''' 154*55a74a43SLisandro Dalcin 155*55a74a43SLisandro Dalcin''' Solve linear system ''' 156*55a74a43SLisandro Dalcinksp.solve(b,x) 157*55a74a43SLisandro Dalcin 158*55a74a43SLisandro Dalcin''' 159*55a74a43SLisandro DalcinView solver info; we could instead use the option -ksp_view to 160*55a74a43SLisandro Dalcinprint this info to the screen at the conclusion of KSPSolve(). 161*55a74a43SLisandro Dalcin''' 162*55a74a43SLisandro Dalcin# ksp.view() 163*55a74a43SLisandro Dalcin 164*55a74a43SLisandro Dalcin''' 165*55a74a43SLisandro Dalcin- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 166*55a74a43SLisandro Dalcin Check solution and clean up 167*55a74a43SLisandro Dalcin- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ''' 168*55a74a43SLisandro Dalcin 169*55a74a43SLisandro Dalcin''' Check the error ''' 170*55a74a43SLisandro Dalcinx = x - u # x.axpy(-1.0,u) 171*55a74a43SLisandro Dalcinnorm = x.norm(PETSc.NormType.NORM_2) 172*55a74a43SLisandro Dalcinits = ksp.getIterationNumber() 173*55a74a43SLisandro Dalcinif norm > tol: 174*55a74a43SLisandro Dalcin PETSc.Sys.Print("Norm of error {}, Iterations {}\n".format(norm,its),comm=comm) 175*55a74a43SLisandro Dalcinelse: 176*55a74a43SLisandro Dalcin if size==1: 177*55a74a43SLisandro Dalcin PETSc.Sys.Print("- Serial OK",comm=comm) 178*55a74a43SLisandro Dalcin else: 179*55a74a43SLisandro Dalcin PETSc.Sys.Print("- Parallel OK",comm=comm) 180