xref: /petsc/src/binding/petsc4py/demo/legacy/petsc-examples/ksp/ex23.py (revision 55a74a43bb44613d95e937906bec3b8c3581b432)
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