@@ -59,6 +59,13 @@ end module m_cg_types
59
59
! ! Field extension to wrap PETSc vector data in a field interface
60
60
end type petsc_field_t
61
61
62
+ type, extends(poisson_precon_impl_t) :: petsc_poisson_precon_t
63
+ type (tMat) :: Pmat ! The preconditioner matrix
64
+ contains
65
+ procedure :: init = > init_precon_petsc
66
+ procedure :: apply_precon = > petsc_apply_precon
67
+ end type petsc_poisson_precon_t
68
+
62
69
type, extends(poisson_solver_t) :: petsc_poisson_cg_t
63
70
! ! Conjugate Gradient based Poisson solver using PETSc as a backend.
64
71
! ! Supports any decomposition that is also supported by the underlying
@@ -145,6 +152,155 @@ end subroutine MatShellSetOperation
145
152
146
153
contains
147
154
155
+ module subroutine init_precon_impl (precon , backend )
156
+ class(poisson_precon_impl_t), allocatable , intent (out ) :: precon
157
+ class(base_backend_t), intent (in ) :: backend
158
+
159
+ allocate (petsc_poisson_precon_t :: precon)
160
+ select type (precon)
161
+ type is (petsc_poisson_precon_t)
162
+ call precon% init(backend)
163
+ class default
164
+ print * , " IMPOSSIBLE"
165
+ stop 42
166
+ end select
167
+
168
+ end subroutine init_precon_impl
169
+
170
+ subroutine init_precon_petsc (self , backend )
171
+
172
+ class(petsc_poisson_precon_t), intent (out ) :: self
173
+ class(base_backend_t), intent (in ) :: backend
174
+
175
+ integer :: n
176
+
177
+ type (tMatNullSpace) :: nsp
178
+ integer :: ierr
179
+
180
+ integer , parameter :: nnb = 6 ! Number of neighbours (7-point star has 6 neighbours)
181
+
182
+ integer , dimension (3 ) :: dims
183
+ integer :: i, j, k
184
+ real (dp) :: dx, dy, dz
185
+
186
+ real (dp), dimension (nnb + 1 ) :: coeffs
187
+ integer , dimension (nnb + 1 ) :: cols
188
+ integer :: row
189
+
190
+ logical :: initialised
191
+
192
+ integer :: istep, jstep, kstep
193
+
194
+ call PetscInitialized(initialised, ierr)
195
+ if (.not. initialised) then
196
+ if (backend% mesh% par% nrank == 0 ) then
197
+ print * , " Initialising PETSc"
198
+ end if
199
+ call PetscInitialize(PETSC_NULL_CHARACTER, ierr)
200
+ end if
201
+ if (backend% mesh% par% nrank == 0 ) then
202
+ print * , " PETSc Initialised"
203
+ end if
204
+
205
+ n = product (backend% mesh% get_dims(CELL))
206
+
207
+ call MatCreate(PETSC_COMM_WORLD, self% Pmat, ierr)
208
+ call MatSetSizes(self% Pmat, n, n, PETSC_DECIDE, PETSC_DECIDE, ierr)
209
+ call MatSetFromOptions(self% Pmat, ierr)
210
+ call MatSeqAIJSetPreallocation(self% Pmat, nnb + 1 , PETSC_NULL_INTEGER, ierr)
211
+ call MatMPIAIJSetPreallocation(self% Pmat, nnb + 1 , PETSC_NULL_INTEGER, &
212
+ nnb, PETSC_NULL_INTEGER, &
213
+ ierr)
214
+ call MatSetUp(self% Pmat, ierr)
215
+
216
+ associate(mesh = > backend% mesh)
217
+ call build_index_map(mesh, self% Pmat)
218
+
219
+ dims = mesh% get_dims(CELL)
220
+ dx = mesh% geo% d(1 ); dy = mesh% geo% d(2 ); dz = mesh% geo% d(3 )
221
+
222
+ istep = 1
223
+ jstep = dims(1 ) + 2
224
+ kstep = (dims(1 ) + 2 ) * (dims(2 ) + 2 )
225
+
226
+ row = kstep + jstep + istep + 1
227
+ do k = 1 , dims(3 )
228
+ do j = 1 , dims(2 )
229
+ do i = 1 , dims(1 )
230
+ coeffs = 0
231
+ cols = - 1 ! Set null (simplifies BCs)
232
+ cols(1 ) = row
233
+
234
+ ! d2pdx2
235
+ coeffs(1 ) = coeffs(1 ) - 2 / dx** 2
236
+ coeffs(2 ) = 1 / dx** 2
237
+ coeffs(3 ) = 1 / dx** 2
238
+ cols(2 ) = cols(1 ) - istep
239
+ cols(3 ) = cols(1 ) + istep
240
+
241
+ ! d2pdy2
242
+ coeffs(1 ) = coeffs(1 ) - 2 / dy** 2
243
+ coeffs(4 ) = 1 / dy** 2
244
+ coeffs(5 ) = 1 / dy** 2
245
+ cols(4 ) = cols(1 ) - jstep
246
+ cols(5 ) = cols(1 ) + jstep
247
+
248
+ ! d2pdz2
249
+ coeffs(1 ) = coeffs(1 ) - 2 / dz** 2
250
+ coeffs(6 ) = 1 / dz** 2
251
+ coeffs(7 ) = 1 / dz** 2
252
+ cols(6 ) = cols(1 ) - kstep
253
+ cols(7 ) = cols(1 ) + kstep
254
+
255
+ ! Push to matrix
256
+ ! Recall Fortran (1-based) -> C (0-based) indexing
257
+ call MatSetValuesLocal(self% Pmat, 1 , row - 1 , nnb + 1 , cols - 1 , coeffs, &
258
+ INSERT_VALUES, ierr)
259
+
260
+ ! Advance row counter
261
+ row = row + 1
262
+ end do
263
+ ! Step in j
264
+ row = row + 2
265
+ end do
266
+ ! Step in k
267
+ row = row + 2 * (dims(1 ) + 2 )
268
+ end do
269
+ end associate
270
+
271
+ call MatAssemblyBegin(self% Pmat, MAT_FINAL_ASSEMBLY, ierr)
272
+ call MatAssemblyEnd(self% Pmat, MAT_FINAL_ASSEMBLY, ierr)
273
+
274
+ call MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_TRUE, 0 , PETSC_NULL_VEC, nsp, ierr)
275
+ call MatSetnullSpace(self% Pmat, nsp, ierr)
276
+ call MatNullSpaceDestroy(nsp, ierr)
277
+
278
+ end subroutine init_precon_petsc
279
+
280
+ module subroutine petsc_apply_precon (self , p , b , backend )
281
+ class(petsc_poisson_precon_t) :: self
282
+ class(field_t), intent (in ) :: p
283
+ class(field_t), intent (inout ) :: b
284
+ class(base_backend_t), intent (in ) :: backend
285
+
286
+ type (tVec) :: pVec, bVec
287
+ integer :: ierr
288
+
289
+ integer :: n
290
+
291
+ n = product (backend% mesh% get_dims(CELL))
292
+ call create_vec(pVec, n)
293
+ call create_vec(bVec, n)
294
+
295
+ call copy_field_to_vec(pVec, p, backend)
296
+ call MatMult(self% PMat, pVec, bVec, ierr)
297
+ call copy_vec_to_field(b, bVec, backend)
298
+
299
+ call VecDestroy(pVec, ierr)
300
+ call VecDestroy(bVec, ierr)
301
+
302
+ end subroutine petsc_apply_precon
303
+
148
304
module subroutine solve_petsc (self , p , f , backend )
149
305
class(petsc_poisson_cg_t) :: self
150
306
class(field_t), intent (inout ) :: p ! Pressure solution
@@ -255,6 +411,8 @@ subroutine create_preconditioner(self, mesh, n)
255
411
integer , dimension (nnb + 1 ) :: cols
256
412
integer :: row
257
413
414
+ integer :: istep, jstep, kstep
415
+
258
416
call MatCreate(PETSC_COMM_WORLD, self% Pmat, ierr)
259
417
call MatSetSizes(self% Pmat, n, n, PETSC_DECIDE, PETSC_DECIDE, ierr)
260
418
call MatSetFromOptions(self% Pmat, ierr)
@@ -268,8 +426,12 @@ subroutine create_preconditioner(self, mesh, n)
268
426
269
427
dims = mesh% get_dims(CELL)
270
428
dx = mesh% geo% d(1 ); dy = mesh% geo% d(2 ); dz = mesh% geo% d(3 )
271
- row = ((dims(1 ) + 2 ) * (dims(2 ) + 2 )) + (dims(1 ) + 2 ) + 2
272
- ! row = 1
429
+
430
+ istep = 1
431
+ jstep = dims(1 ) + 2
432
+ kstep = (dims(1 ) + 2 ) * (dims(2 ) + 2 )
433
+
434
+ row = kstep + jstep + istep + 1
273
435
do k = 1 , dims(3 )
274
436
do j = 1 , dims(2 )
275
437
do i = 1 , dims(1 )
@@ -281,22 +443,22 @@ subroutine create_preconditioner(self, mesh, n)
281
443
coeffs(1 ) = coeffs(1 ) - 2 / dx** 2
282
444
coeffs(2 ) = 1 / dx** 2
283
445
coeffs(3 ) = 1 / dx** 2
284
- cols(2 ) = cols(1 ) - 1
285
- cols(3 ) = cols(1 ) + 1
446
+ cols(2 ) = cols(1 ) - istep
447
+ cols(3 ) = cols(1 ) + istep
286
448
287
449
! d2pdy2
288
450
coeffs(1 ) = coeffs(1 ) - 2 / dy** 2
289
451
coeffs(4 ) = 1 / dy** 2
290
452
coeffs(5 ) = 1 / dy** 2
291
- cols(4 ) = cols(1 ) - (dims( 1 ) + 2 )
292
- cols(5 ) = cols(1 ) + (dims( 1 ) + 2 )
453
+ cols(4 ) = cols(1 ) - jstep
454
+ cols(5 ) = cols(1 ) + jstep
293
455
294
456
! d2pdz2
295
457
coeffs(1 ) = coeffs(1 ) - 2 / dz** 2
296
458
coeffs(6 ) = 1 / dz** 2
297
459
coeffs(7 ) = 1 / dz** 2
298
- cols(6 ) = cols(1 ) - (dims( 1 ) + 2 ) * (dims( 2 ) + 2 )
299
- cols(7 ) = cols(1 ) + (dims( 1 ) + 2 ) * (dims( 2 ) + 2 )
460
+ cols(6 ) = cols(1 ) - kstep
461
+ cols(7 ) = cols(1 ) + kstep
300
462
301
463
! Push to matrix
302
464
! Recall Fortran (1-based) -> C (0-based) indexing
@@ -452,7 +614,9 @@ subroutine build_neighbour_index_map(idx, mesh, global_start)
452
614
! ! X halos
453
615
! Left halo
454
616
associate(offset_left = > info(1 , 1 , 1 ), &
455
- nx_left = > info(2 , 1 , 1 ), ny_left = > info(3 , 1 , 1 ), nz_left = > info(4 , 1 , 1 ))
617
+ nx_left = > info(2 , 1 , 1 ), &
618
+ ny_left = > info(3 , 1 , 1 ), &
619
+ nz_left = > info(4 , 1 , 1 ))
456
620
ctr = offset_left + (nx_left - 1 ) ! Global starting index -> xend
457
621
do k = 1 , nz_left
458
622
do j = 1 , ny_left
@@ -463,7 +627,9 @@ subroutine build_neighbour_index_map(idx, mesh, global_start)
463
627
end associate
464
628
! Right halo
465
629
associate(offset_right = > info(1 , 2 , 1 ), &
466
- nx_right = > info(2 , 2 , 1 ), ny_right = > info(3 , 2 , 1 ), nz_right = > info(4 , 2 , 1 ))
630
+ nx_right = > info(2 , 2 , 1 ), &
631
+ ny_right = > info(3 , 2 , 1 ), &
632
+ nz_right = > info(4 , 2 , 1 ))
467
633
ctr = offset_right ! Global starting index == xstart
468
634
do k = 1 , nz_right
469
635
do j = 1 , ny_right
@@ -476,7 +642,9 @@ subroutine build_neighbour_index_map(idx, mesh, global_start)
476
642
! ! Y halos
477
643
! Bottom halo
478
644
associate(offset_down = > info(1 , 1 , 2 ), &
479
- nx_down = > info(2 , 1 , 2 ), ny_down = > info(3 , 1 , 2 ), nz_down = > info(4 , 1 , 2 ))
645
+ nx_down = > info(2 , 1 , 2 ), &
646
+ ny_down = > info(3 , 1 , 2 ), &
647
+ nz_down = > info(4 , 1 , 2 ))
480
648
ctr = offset_down + (ny_down - 1 ) * nx_down ! Global starting index -> yend
481
649
do k = 1 , nz_down
482
650
do i = 1 , nx_down
@@ -489,7 +657,9 @@ subroutine build_neighbour_index_map(idx, mesh, global_start)
489
657
end associate
490
658
! Top halo
491
659
associate(offset_up = > info(1 , 2 , 2 ), &
492
- nx_up = > info(2 , 2 , 2 ), ny_up = > info(3 , 2 , 2 ), nz_up = > info(4 , 2 , 2 ))
660
+ nx_up = > info(2 , 2 , 2 ), &
661
+ ny_up = > info(3 , 2 , 2 ), &
662
+ nz_up = > info(4 , 2 , 2 ))
493
663
ctr = offset_up ! Global starting index == ystart
494
664
do k = 1 , nz_up
495
665
do i = 1 , nx_up
@@ -504,7 +674,9 @@ subroutine build_neighbour_index_map(idx, mesh, global_start)
504
674
! ! Z halos
505
675
! Back halo
506
676
associate(offset_back = > info(1 , 1 , 3 ), &
507
- nx_back = > info(2 , 1 , 3 ), ny_back = > info(3 , 1 , 3 ), nz_back = > info(4 , 1 , 3 ))
677
+ nx_back = > info(2 , 1 , 3 ), &
678
+ ny_back = > info(3 , 1 , 3 ), &
679
+ nz_back = > info(4 , 1 , 3 ))
508
680
ctr = offset_back + ny_back * nx_back ! Global starting index -> zend
509
681
do j = 1 , ny_back
510
682
do i = 1 , nx_back
@@ -515,7 +687,9 @@ subroutine build_neighbour_index_map(idx, mesh, global_start)
515
687
end associate
516
688
! Front halo
517
689
associate(offset_front = > info(1 , 2 , 3 ), &
518
- nx_front = > info(2 , 2 , 3 ), ny_front = > info(3 , 2 , 3 ), nz_front = > info(4 , 2 , 3 ))
690
+ nx_front = > info(2 , 2 , 3 ), &
691
+ ny_front = > info(3 , 2 , 3 ), &
692
+ nz_front = > info(4 , 2 , 3 ))
519
693
ctr = offset_front ! Global startin index == zstart
520
694
do j = 1 , ny_front
521
695
do i = 1 , nx_front
@@ -529,36 +703,46 @@ subroutine build_neighbour_index_map(idx, mesh, global_start)
529
703
ctr = 1
530
704
do k = 1 , nz + 2
531
705
do j = 1 , ny + 2
532
- do i = 1 , nx + 2
533
- if ((j > 1 ) .and. (j < (ny + 2 )) .and. &
534
- (k > 1 ) .and. (k < (nz + 2 ))) then
535
- if (i == 1 ) then
536
- idx(ctr) = halobuf_x(1 , j - 1 , k - 1 )
537
- else if (i == (nx + 2 )) then
538
- idx(ctr) = halobuf_x(2 , j - 1 , k - 1 )
539
- end if
540
- end if
541
706
542
- if ((i > 1 ) .and. (i < (nx + 2 ))) then
543
- if ((k > 1 ) .and. (k < (nz + 2 ))) then
544
- if (j == 1 ) then
545
- idx(ctr) = halobuf_y(i - 1 , 1 , k - 1 )
546
- else if (j == (ny + 2 )) then
547
- idx(ctr) = halobuf_y(i - 1 , 2 , k - 1 )
548
- end if
707
+ ! Left halo
708
+ if ((j > 1 ) .and. (j < (ny + 2 )) .and. &
709
+ (k > 1 ) .and. (k < (nz + 2 ))) then
710
+ idx(ctr) = halobuf_x(1 , j - 1 , k - 1 )
711
+ end if
712
+ ctr = ctr + 1
713
+
714
+ do i = 2 , nx + 1
715
+
716
+ if ((k > 1 ) .and. (k < (nz + 2 ))) then
717
+ if (j == 1 ) then
718
+ ! Bottom halo
719
+ idx(ctr) = halobuf_y(i - 1 , 1 , k - 1 )
720
+ else if (j == (ny + 2 )) then
721
+ ! Top halo
722
+ idx(ctr) = halobuf_y(i - 1 , 2 , k - 1 )
549
723
end if
724
+ end if
550
725
551
- if ((j > 1 ) .and. (j < (ny + 2 ))) then
552
- if (k == 1 ) then
553
- idx(ctr) = halobuf_z(i - 1 , j - 1 , 1 )
554
- else if (k == (nz + 2 )) then
555
- idx(ctr) = halobuf_z(i - 1 , j - 1 , 2 )
556
- end if
726
+ if ((j > 1 ) .and. (j < (ny + 2 ))) then
727
+ if (k == 1 ) then
728
+ ! Back halo
729
+ idx(ctr) = halobuf_z(i - 1 , j - 1 , 1 )
730
+ else if (k == (nz + 2 )) then
731
+ ! Front halo
732
+ idx(ctr) = halobuf_z(i - 1 , j - 1 , 2 )
557
733
end if
558
734
end if
559
735
560
736
ctr = ctr + 1
561
737
end do
738
+
739
+ ! Right halo
740
+ if ((j > 1 ) .and. (j < (ny + 2 )) .and. &
741
+ (k > 1 ) .and. (k < (nz + 2 ))) then
742
+ idx(ctr) = halobuf_x(2 , j - 1 , k - 1 )
743
+ end if
744
+ ctr = ctr + 1
745
+
562
746
end do
563
747
end do
564
748
0 commit comments