xref: /petsc/src/binding/petsc4py/demo/hpddm/hpddm.py (revision 6c5693054f5123506dab0f5da2d352ed973d0e50)
1dc97da86SPierre Jolivet# This script demonstrates solving a symmetric positive definite linear system using PETSc and HPDDM preconditioner
2dc97da86SPierre Jolivet# It must be run with exactly 4 MPI processes
3dc97da86SPierre Jolivet# Example run:
4*a8cf87e0SJunchao Zhang#   mpiexec -n 4 python3 hpddm.py -pc_hpddm_levels_1_sub_pc_type lu -pc_hpddm_levels_1_eps_nev 20 -pc_hpddm_levels_1_eps_threshold_absolute 0.1 -ksp_monitor
5dc97da86SPierre Jolivet# For more options, see ${PETSC_DIR}/src/ksp/ksp/tutorials/ex76.c
6dc97da86SPierre Jolivet
7dc97da86SPierre Jolivetimport sys
8dc97da86SPierre Jolivetimport petsc4py
9dc97da86SPierre Jolivet# Initialize PETSc with command-line arguments
10dc97da86SPierre Jolivetpetsc4py.init(sys.argv)
11dc97da86SPierre Jolivetfrom petsc4py import PETSc
12dc97da86SPierre Jolivet
13dc97da86SPierre Jolivet# Get the rank of the current process
14dc97da86SPierre Jolivetrank = PETSc.COMM_WORLD.getRank()
15dc97da86SPierre Jolivet# Ensure that the script is run with exactly 4 processes
16dc97da86SPierre Jolivetif PETSc.COMM_WORLD.getSize() != 4:
17dc97da86SPierre Jolivet  if rank == 0:
18dc97da86SPierre Jolivet    print("This example requires 4 processes")
19dc97da86SPierre Jolivet  quit()
20dc97da86SPierre Jolivet
21dc97da86SPierre Jolivet# Load directory for input data
22dc97da86SPierre Jolivetload_dir = PETSc.Options().getString("load_dir", "${DATAFILESPATH}/matrices/hpddm/GENEO")
23dc97da86SPierre Jolivet
24dc97da86SPierre Jolivet# Load an index set (IS) from binary file
25dc97da86SPierre Jolivetsizes = PETSc.IS().load(PETSc.Viewer().createBinary(f"{load_dir}/sizes_{rank}_4.dat", "r", comm = PETSc.COMM_SELF))
26dc97da86SPierre Jolivet# Get indices from the loaded IS
27dc97da86SPierre Jolivetidx   = sizes.getIndices()
28dc97da86SPierre Jolivet
29dc97da86SPierre Jolivet# Create a PETSc matrix object
30dc97da86SPierre JolivetA = PETSc.Mat().create()
31dc97da86SPierre Jolivet# Set the local and global sizes of the matrix
32dc97da86SPierre JolivetA.setSizes([[idx[0], idx[2]], [idx[1], idx[3]]])
33dc97da86SPierre Jolivet# Configure matrix using runtime options
34dc97da86SPierre JolivetA.setFromOptions()
35dc97da86SPierre Jolivet# Load matrix A from binary file
36dc97da86SPierre JolivetA = A.load(PETSc.Viewer().createBinary(f"{load_dir}/A.dat", "r", comm = PETSc.COMM_WORLD))
37dc97da86SPierre Jolivet
38dc97da86SPierre Jolivet# Load an index set (IS) from binary file
39dc97da86SPierre Jolivetaux_IS  = PETSc.IS().load(PETSc.Viewer().createBinary(f"{load_dir}/is_{rank}_4.dat", "r", comm = PETSc.COMM_SELF))
40dc97da86SPierre Jolivet# Set the block size of the index set
416d61d5b2SPierre Jolivetaux_IS.setBlockSize(A.getBlockSize())
42dc97da86SPierre Jolivet# Load the Neumann matrix of the current process
43dc97da86SPierre Jolivetaux_Mat = PETSc.Mat().load(PETSc.Viewer().createBinary(f"{load_dir}/Neumann_{rank}_4.dat", "r", comm = PETSc.COMM_SELF))
44dc97da86SPierre Jolivet
45dc97da86SPierre Jolivet# Create and configure the linear solver (KSP) and preconditioner (PC)
46dc97da86SPierre Jolivetksp = PETSc.KSP(PETSc.COMM_WORLD).create()
47dc97da86SPierre Jolivetpc = ksp.getPC()
48dc97da86SPierre Jolivet# Use HPDDM as the preconditioner
49dc97da86SPierre Jolivetpc.setType(PETSc.PC.Type.HPDDM)
50bd6c8f9dSPierre Jolivet# Set the index set (local-to-global numbering) and auxiliary matrix
51dc97da86SPierre Jolivetpc.setHPDDMAuxiliaryMat(aux_IS, aux_Mat)
52dc97da86SPierre Jolivet# Inform HPDDM that the auxiliary matrix is the local Neumann matrix
53dc97da86SPierre Jolivetpc.setHPDDMHasNeumannMat(True)
54dc97da86SPierre Jolivet# Apply any command-line options (which may override options from the source file)
55dc97da86SPierre Jolivetksp.setFromOptions()
56dc97da86SPierre Jolivet# Set the system matrix (Amat = Pmat)
57dc97da86SPierre Jolivetksp.setOperators(A)
58dc97da86SPierre Jolivet
59dc97da86SPierre Jolivet# Create RHS (b) and solution (x) vectors, set random values to b, and solve the system
60dc97da86SPierre Jolivetb, x = A.createVecs()
61dc97da86SPierre Jolivetb.setRandom()
62dc97da86SPierre Jolivetksp.solve(b, x)
63dc97da86SPierre Jolivet
64dc97da86SPierre Jolivet# Output grid and operator complexities on rank 0
65dc97da86SPierre Jolivetgc, oc = pc.getHPDDMComplexities()
66dc97da86SPierre Jolivetif rank == 0:
67dc97da86SPierre Jolivet  print("grid complexity = ", gc, ", operator complexity = ", oc, sep = "")
68