MODFLOW 6  version 6.7.0.dev3
USGS Modular Hydrologic Model
PetscImsPreconditioner.F90
Go to the documentation of this file.
2 #include <petsc/finclude/petscksp.h>
3  use petscksp
4  use kindmodule, only: dp, i4b
6  use petscmatrixmodule, only: petscmatrixtype
9  use simvariablesmodule, only: iout
10 
11  implicit none
12  private
13 
14  public :: pcshellctxtype
15  public :: pcshell_apply
16  public :: pcshell_setup
17 
18  character(len=9), dimension(4) :: ims_pc_type = ["IMS ILU0 ", &
19  "IMS MILU0", &
20  "IMS ILUT ", &
21  "IMS MILUT"]
22 
24  character(len=LENMEMPATH) :: memory_path !< the memory path, taken from the system matrix
25  class(petscmatrixtype), pointer :: system_matrix !< pointer to the petsc system matrix
26  type(imslinearsettingstype), pointer :: linear_settings !< the linear settings from IMS
27  integer(I4B) :: ipc !< the IMS preconditioner type: 1=ILU0, 2=MILU0, 3=ILUT, 4=MILUT
28  character(len=16) :: ims_pc_type !< the IMS preconditioner type as a string
29  ! PC matrix
30  integer(I4B), dimension(:), contiguous, pointer :: iapc => null() !< CSR row pointer
31  integer(I4B), dimension(:), contiguous, pointer :: japc => null() !< CSR columns
32  real(dp), dimension(:), contiguous, pointer :: apc => null() !< CSR Preconditioner matrix values
33  ! work vectors
34  integer(I4B), dimension(:), contiguous, pointer :: iw => null() !< (M)ILU0 work array
35  real(dp), dimension(:), contiguous, pointer :: w => null() !< (M)ILU0 work array
36  integer(I4B), dimension(:), contiguous, pointer :: jlu => null() !< (M)ILUT work array
37  integer(I4B), dimension(:), contiguous, pointer :: jw => null() !< (M)ILUT work array
38  real(dp), dimension(:), contiguous, pointer :: wlu => null() !< (M)ILUT work array
39  contains
40  procedure :: create => pctx_create
41  procedure :: destroy => pctx_destroy
42 
43  end type
44 
45  interface
46  subroutine pcshellgetcontext(pc, ctx, ierr)
47  import pcshellctxtype, tpc
48  type(tpc) :: pc
49  type(pcshellctxtype), pointer :: ctx
50  integer :: ierr
51  end subroutine
52  end interface
53 
54 contains
55 
56  !> @brief Create the preconditioner context from the system matrix
57  !<
58  subroutine pctx_create(this, matrix, lin_settings)
61  class(pcshellctxtype) :: this !< this instance
62  class(petscmatrixtype), pointer :: matrix !< the linear system matrix
63  type(imslinearsettingstype), pointer :: lin_settings !< linear settings from IMS
64  ! local
65  integer(I4B) :: n, neq, nja
66  integer(I4B), dimension(:), contiguous, pointer :: ia, ja
67  real(DP), dimension(:), contiguous, pointer :: amat
68  integer(I4B) :: niapc, njapc, njlu, njw, nwlu
69 
70  this%memory_path = matrix%memory_path
71  this%linear_settings => lin_settings
72 
73  this%ipc = 1
74  if (this%linear_settings%level > 0) then
75  this%ipc = this%ipc + 2
76  end if
77  if (this%linear_settings%relax > 0.0_dp) this%ipc = this%ipc + 1
78  this%ims_pc_type = ims_pc_type(this%ipc)
79 
80  this%system_matrix => matrix
81  call matrix%get_aij_local(ia, ja, amat)
82 
83  neq = matrix%nrow
84  nja = matrix%nnz_local
85  call ims_calc_pcdims(neq, nja, ia, this%linear_settings%level, this%ipc, &
86  niapc, njapc, njlu, njw, nwlu)
87 
88  ! preconditioner matrix
89  call mem_allocate(this%IAPC, niapc + 1, 'IAPC', this%memory_path)
90  call mem_allocate(this%JAPC, njapc, 'JAPC', this%memory_path)
91  call mem_allocate(this%APC, njapc, 'APC', this%memory_path)
92  if (this%ipc == 1 .or. this%ipc == 2) then
93  call ims_base_pccrs(niapc, njapc, ia, ja, this%IAPC, this%JAPC)
94  end if
95  do n = 1, njapc
96  this%APC(n) = dzero
97  end do
98 
99  ! (M)ILU0 work arrays
100  call mem_allocate(this%IW, niapc, 'IW', this%memory_path)
101  call mem_allocate(this%W, niapc, 'W', this%memory_path)
102  do n = 1, niapc
103  this%IW(n) = izero
104  this%W(n) = dzero
105  end do
106 
107  ! (M)ILUT work arrays
108  call mem_allocate(this%JLU, njlu, 'JLU', this%memory_path)
109  call mem_allocate(this%JW, njw, 'JW', this%memory_path)
110  call mem_allocate(this%WLU, nwlu, 'WLU', this%memory_path)
111 
112  do n = 1, njlu
113  this%JLU(n) = izero
114  end do
115  do n = 1, njw
116  this%JW(n) = izero
117  end do
118  do n = 1, nwlu
119  this%WLU(n) = dzero
120  end do
121 
122  end subroutine pctx_create
123 
124  !> @brief Cleanup the context
125  !<
126  subroutine pctx_destroy(this)
128  class(pcshellctxtype) :: this
129 
130  ! matrix
131  call mem_deallocate(this%IAPC)
132  call mem_deallocate(this%JAPC)
133  call mem_deallocate(this%APC)
134 
135  ! work arrays
136  call mem_deallocate(this%IW)
137  call mem_deallocate(this%W)
138  call mem_deallocate(this%JLU)
139  call mem_deallocate(this%JW)
140  call mem_deallocate(this%WLU)
141 
142  this%system_matrix => null()
143 
144  end subroutine pctx_destroy
145 
146  !> @brief Apply shell preconditioner
147  !< (this is not a type bound procedure)
148  subroutine pcshell_apply(pc, x, y, ierr)
150  external lusol ! from ilut.f90
151  pc :: pc !< the shell preconditioner
152  vec :: x !< the input vector
153  vec :: y !< the output vector
154  petscerrorcode :: ierr !< PETSc error code
155  ! local
156  type(pcshellctxtype), pointer :: pc_ctx => null()
157  real(dp), dimension(:), pointer :: local_x, local_y
158  integer(I4B) :: neq, nja
159 
160  call pcshellgetcontext(pc, pc_ctx, ierr)
161  chkerrq(ierr)
162 
163  call vecgetarrayreadf90(x, local_x, ierr)
164  chkerrq(ierr)
165  call vecgetarrayf90(y, local_y, ierr)
166  chkerrq(ierr)
167 
168  neq = pc_ctx%system_matrix%nrow
169  nja = pc_ctx%system_matrix%nnz_local
170  select case (pc_ctx%ipc)
171  case (1, 2)
172  call ims_base_ilu0a(nja, neq, pc_ctx%APC, pc_ctx%IAPC, pc_ctx%JAPC, &
173  local_x, local_y)
174  case (3, 4)
175  call lusol(neq, local_x, local_y, pc_ctx%APC, pc_ctx%JLU, pc_ctx%IW)
176  end select
177 
178  call vecrestorearrayf90(x, local_x, ierr)
179  chkerrq(ierr)
180  call vecrestorearrayf90(y, local_y, ierr)
181  chkerrq(ierr)
182 
183  end subroutine pcshell_apply
184 
185  !> @brief Set up the custom preconditioner
186  !< (this is not a type bound procedure)
187  subroutine pcshell_setup(pc, ierr)
189  pc :: pc !< the shell preconditioner
190  petscerrorcode :: ierr !< PETSc error code
191  ! local
192  type(pcshellctxtype), pointer :: pc_ctx => null()
193  integer(I4B) :: neq, nja
194  integer(I4B) :: niapc, njapc, njlu, njw, nwlu
195  integer(I4B), dimension(:), contiguous, pointer :: ia, ja
196  real(dp), dimension(:), contiguous, pointer :: amat
197 
198  call pcshellgetcontext(pc, pc_ctx, ierr)
199  chkerrq(ierr)
200 
201  ! note the two different matrix types here:
202  ! bridging between PETSc and IMS
203  call pc_ctx%system_matrix%get_aij_local(ia, ja, amat)
204 
205  neq = pc_ctx%system_matrix%nrow
206  nja = pc_ctx%system_matrix%nnz_local
207  niapc = size(pc_ctx%IAPC) - 1
208  njapc = size(pc_ctx%JAPC)
209  njlu = size(pc_ctx%JLU)
210  njw = size(pc_ctx%JW)
211  nwlu = size(pc_ctx%WLU)
212  call ims_base_pcu(iout, nja, neq, niapc, njapc, &
213  pc_ctx%ipc, pc_ctx%linear_settings%relax, &
214  amat, ia, ja, &
215  pc_ctx%APC, pc_ctx%IAPC, pc_ctx%JAPC, &
216  pc_ctx%IW, pc_ctx%W, &
217  pc_ctx%linear_settings%level, &
218  pc_ctx%linear_settings%droptol, &
219  njlu, njw, nwlu, &
220  pc_ctx%JLU, pc_ctx%JW, pc_ctx%WLU)
221 
222  end subroutine pcshell_setup
223 
subroutine lusol(n, y, x, alu, jlu, ju)
Definition: ilut.f90:466
This module contains simulation constants.
Definition: Constants.f90:9
integer(i4b), parameter izero
integer constant zero
Definition: Constants.f90:51
real(dp), parameter dzero
real constant zero
Definition: Constants.f90:65
integer(i4b), parameter lenmempath
maximum length of the memory path
Definition: Constants.f90:27
This module contains the IMS linear accelerator subroutines.
subroutine ims_base_pcu(IOUT, NJA, NEQ, NIAPC, NJAPC, IPC, RELAX, AMAT, IA, JA, APC, IAPC, JAPC, IW, W, LEVEL, DROPTOL, NJLU, NJW, NWLU, JLU, JW, WLU)
@ brief Update the preconditioner
subroutine ims_base_pccrs(NEQ, NJA, IA, JA, IAPC, JAPC)
@ brief Generate CRS pointers for the preconditioner
subroutine ims_calc_pcdims(neq, nja, ia, level, ipc, niapc, njapc, njlu, njw, nwlu)
subroutine ims_base_ilu0a(NJA, NEQ, APC, IAPC, JAPC, R, D)
@ brief Apply the ILU0 and MILU0 preconditioners
This module defines variable data types.
Definition: kind.f90:8
subroutine, public pcshell_setup(pc, ierr)
Set up the custom preconditioner.
subroutine pctx_destroy(this)
Cleanup the context.
subroutine, public pcshell_apply(pc, x, y, ierr)
Apply shell preconditioner.
subroutine pctx_create(this, matrix, lin_settings)
Create the preconditioner context from the system matrix.
character(len=9), dimension(4) ims_pc_type
This module contains simulation variables.
Definition: SimVariables.f90:9
integer(i4b) iout
file unit number for simulation output