32 use const_gbl,
only: stdout
35 use mpi_gbl,
only: mpi_mod_allgather, mpi_mod_scan_sum
43 #include <finclude/petsc.h>
53 petscint,
allocatable :: col(:)
54 petscscalar,
allocatable :: coeff(:)
72 petscint :: start_row_petsc
73 petscint :: end_row_petsc
74 petscint :: local_size_petsc
75 petscint :: matrix_dimension_petsc
78 petscint,
allocatable :: diagonal_nonzero(:)
79 petscint,
allocatable :: offdiagonal_nonzero(:)
82 integer :: diagonal_start,diagonal_end
83 logical :: compressed = .false.
84 logical :: mat_created = .false.
117 petscerrorcode :: ierr
119 call slepcinitialize(petsc_null_character, ierr)
120 write (stdout,
"('SLEPc initialization status = ',I0)") ierr
128 integer,
intent(in) :: num_cols
130 if (
allocated(this % coeff))
deallocate(this % coeff)
131 if (
allocated(this % col))
deallocate(this % col)
133 allocate(this % coeff(num_cols))
134 allocate(this % col(num_cols))
142 if (
allocated(this % col))
deallocate(this % col)
143 if (
allocated(this % coeff))
deallocate(this % coeff)
151 call qsortcsr (this % col, this % coeff)
167 petscint,
intent(in) :: matrix_size
168 integer,
intent(in) :: matrix_type
169 integer :: ierr, non_zero_guess
171 if (this % mat_created)
then
172 stop
"PETSC matrix already created!!"
183 this % mat_created = .true.
190 petscerrorcode :: ierr
192 if (this % mat_created)
then
193 call matdestroy(this % A, ierr)
198 this % mat_created = .false.
205 petscint,
intent(inout) :: a(:)
207 integer :: i, randpos, temp
210 do i =
size(a), 2, -1
211 call random_number(r)
212 randpos = int(r * i) + 1
224 integer,
intent(in) :: matrix_size, matrix_type, block_size
226 petscint :: non_zero_guess, petsc_row, to_insert, one = 1, dummy_int
227 petscerrorcode :: ierr
228 real(wp) :: mem_usage_begin, mem_usage_end, ratio, dummy_real
229 integer :: ido, total_vals, per_elm, l_update, c_update, indicies, total_elems, nprocs
231 integer,
allocatable :: mem_use_total(:)
232 petscint,
allocatable :: test_insertion_ij(:)
233 petscscalar,
allocatable :: test_insertion_val(:)
238 call this % slepc_cache % construct
239 call this % destroy_PETSC_mat
241 this % matrix_dimension_PETSC = this % matrix_dimension
242 write (stdout,
"('Mat_size = ',i8)") this % matrix_dimension_PETSC
244 call this % create_PETSC_mat(this % matrix_dimension_PETSC, matrix_type)
246 this % local_size_PETSC = petsc_decide
249 call petscsplitownership(int(grid % gcomm, kind(petsc_comm_world)), &
250 this % local_size_PETSC, this % matrix_dimension_PETSC, ierr)
253 this % local_size = this % local_size_PETSC
255 write (stdout,
"('Local_size = ',i8)") this % local_size
256 write (stdout,
"('THRESHOLD = ',es16.8)") this % threshold
259 call mpi_mod_scan_sum(this % local_size, this % end_row, grid % gcomm)
261 this % start_row = this % end_row - this % local_size
264 this % start_row_PETSC = this % start_row
265 this % end_row_PETSC = this % end_row
266 write (stdout,
"('start,end = ',2i8)") this % start_row, this % end_row
269 if (this % matrix_type ==
mat_dense)
then
270 call petscmemorygetcurrentusage(mem_usage_begin, ierr)
271 call matcreatedense(grid % gcomm, petsc_decide, petsc_decide, matrix_size, matrix_size, &
272 petsc_null_scalar, this % A, ierr)
273 call petscmemorygetcurrentusage(mem_usage_end, ierr)
275 write (stdout,
"('Matrix uses ',f8.3,' GB of memory')") (mem_usage_end - mem_usage_begin) / 1024**3
276 this % mem_track = mem_usage_end - mem_usage_begin
278 call master_memory % track_memory(this % mem_track, 1, 0,
'PETSC MATRIX')
283 if (
allocated(this % diagonal_nonzero))
deallocate(this % diagonal_nonzero)
284 if (
allocated(this % offdiagonal_nonzero))
deallocate(this % offdiagonal_nonzero)
287 allocate(this % diagonal_nonzero(this % local_size), stat = ierr)
288 allocate(this % offdiagonal_nonzero(this % local_size), stat = ierr)
290 this % diagonal_nonzero = 0
291 this % offdiagonal_nonzero = 0
295 this % diagonal_start = this % start_row_PETSC
296 this % diagonal_end = min(this % start_row_PETSC + this % local_size, this % matrix_dimension)
298 do ido = 1, this % local_size
299 total_vals = this % matrix_dimension - this % start_row - ido + 1
300 this % diagonal_nonzero(ido) = this % diagonal_end - this % diagonal_start + 1 - ido
301 this % offdiagonal_nonzero(ido) = total_vals - this % diagonal_nonzero(ido)
304 if ((this % start_row + ido - 1) >= block_size)
then
307 ratio = real(this % diagonal_nonzero(ido)) / real(total_vals)
309 total_vals = real(total_vals) * 0.1
313 this % diagonal_nonzero(ido) = max(1, int(real(total_vals) * ratio))
314 this % offdiagonal_nonzero(ido) = int(real(total_vals) * (1.0 - ratio))
316 total_elems = total_elems + this % diagonal_nonzero(ido) + this % offdiagonal_nonzero(ido)
320 call petscmemorygetcurrentusage(mem_usage_begin, ierr)
322 this % continuum_counter = 0
323 this % L2_counter = 0
325 call matcreatesbaij(grid % gcomm, 1, petsc_decide, petsc_decide, matrix_size, matrix_size, &
326 petsc_default_integer, this % diagonal_nonzero, petsc_default_integer, this % offdiagonal_nonzero, &
346 call matsetoption(this % A, mat_ignore_off_proc_entries, petsc_true, ierr)
347 call matsetoption(this % A, mat_no_off_proc_entries, petsc_true, ierr)
348 call matsetoption(this % A, mat_ignore_lower_triangular, petsc_true, ierr)
349 call matsetoption(this % A, mat_new_nonzero_allocation_err, petsc_false, ierr)
351 deallocate(this % diagonal_nonzero, this % offdiagonal_nonzero)
353 allocate(test_insertion_ij(this % matrix_dimension), test_insertion_val(this % matrix_dimension))
355 do ido = 1, this % matrix_dimension
356 test_insertion_ij(ido) = ido - 1
357 test_insertion_val(ido) = 1.0_wp
362 do ido = 1, this % local_size
363 total_vals = this % matrix_dimension - this % start_row - ido + 1
365 dummy_int = this % start_row + ido
366 if ((dummy_int - 1) < block_size)
then
367 to_insert =
size(test_insertion_ij(dummy_int:this % matrix_dimension))
370 call matsetvaluesblocked(this % A, one, dummy_int - one, to_insert, &
371 test_insertion_ij(dummy_int : this % matrix_dimension), &
372 test_insertion_val(dummy_int : this % matrix_dimension), &
378 call matassemblybegin(this % A, mat_flush_assembly, ierr)
379 call matassemblyend(this % A, mat_flush_assembly, ierr)
382 call matzeroentries(this % A, ierr)
385 deallocate(test_insertion_ij, test_insertion_val)
387 write (stdout,
"('PETSC matrix creation completed!')")
391 call petscmemorygetcurrentusage(mem_usage_end, ierr)
393 write (stdout,
"('Matrix uses ',f15.8,' B of memory')") mem_usage_end - mem_usage_begin
394 write (stdout,
"('Estimated uses ',i12,' B of memory')") total_elems * 16
396 this % mem_track = mem_usage_end - mem_usage_begin
398 allocate(mem_use_total(grid % gprocs))
400 total_elems = total_elems*16
402 call mpi_mod_allgather(total_elems, mem_use_total, grid % gcomm)
404 total_elems = sum(mem_use_total)
405 total_elems = total_elems / nprocs
406 this % mem_track = total_elems
408 deallocate(mem_use_total)
410 write (stdout,
"('Average uses ',i12,' B of memory')") total_elems
412 call master_memory % track_memory(1, total_elems, 0,
'PETSC MATRIX')
420 integer,
intent(in) :: idx
421 integer,
intent(out) :: i, j
422 real(wp),
intent(out) :: coeff
436 do ido = 1, this % local_size
437 write (stdout,
"('dnnz = ',i8,'onnz = ',i8)") this % diagonal_nonzero(ido), this % offdiagonal_nonzero(ido)
445 type(
csrformat),
allocatable,
intent(out) :: csr_matrix(:)
448 integer :: ido, jdo, start_idx, end_idx, num_elems, row_count, row_idx, first_row
449 integer :: current_chunk, current_row, next_row, last_chunk, i, j
455 if (this % matrix_type ==
mat_dense)
return
458 call matrix_cache % sort
462 do ido = 1, matrix_cache % get_size()
463 call matrix_cache % get_from_cache(ido, i, j, coeff)
464 if (ido == 1) first_row = i
465 if (i /= current_row)
then
466 row_count = row_count + 1
473 num_elems = matrix_cache % get_size()
475 if (row_count == 0)
then
480 if (
allocated(csr_matrix))
deallocate(csr_matrix)
483 allocate(csr_matrix(row_count))
485 csr_matrix(:) % num_cols = 0
493 current_row = first_row
496 do while (ido <= num_elems)
500 do jdo = ido, num_elems
501 call matrix_cache % get_from_cache(jdo, i, j, coeff)
504 if (i == current_row)
then
505 if (abs(coeff) > this % threshold) row_count = row_count + 1
512 csr_matrix(row_idx) % row = current_row
513 csr_matrix(row_idx) % num_cols = row_count
516 if (row_count > 0)
then
518 call csr_matrix(row_idx) % construct(row_count)
521 do jdo = 1, row_count
523 call matrix_cache % get_from_cache(jdo + start_idx - 1, i, j, coeff)
525 csr_matrix(row_idx) % col(jdo) = j
526 csr_matrix(row_idx) % coeff(jdo) = coeff
527 current_chunk = matrix_cache % get_chunk_idx(jdo + start_idx - 1)
529 if (last_chunk /= current_chunk)
then
530 call matrix_cache % matrix_arrays(last_chunk) % destroy
531 last_chunk = current_chunk
538 start_idx = end_idx + 1
539 row_idx = row_idx + 1
540 current_row = next_row
546 call matrix_cache % destroy
547 call matrix_cache % construct
561 integer,
intent(in) :: row, column
562 real(wp),
intent(in) :: coefficient
564 petscerrorcode :: ierr
571 if (abs(coefficient) < this % threshold)
return
574 if (this % matrix_type ==
mat_dense)
then
575 if (i >= this % start_row .or. i < this % end_row )
then
576 call matsetvalue(this % A, i, j, coefficient, insert_values, ierr)
578 if (j >= this % start_row .or. j < this % end_row)
then
579 call matsetvalue(this % A, j, i, coefficient, insert_values, ierr)
585 if (j < this % start_row .or. j >= this % end_row)
then
594 call matsetvalue(this % A, j, i, coefficient, insert_values, ierr)
596 this % n = this % n + 1
605 petscint :: row, column, ido, one = 1
606 petscerrorcode :: ierr
608 if (this % matrix_type ==
mat_dense)
return
615 if (row < this % start_row .or. row >= this % end_row) cycle
616 if (csr(ido) % num_cols == 0) cycle
619 call matsetvaluesblocked(this % A, one, csr(ido) % row, csr(ido) % num_cols, &
620 csr(ido) % col, csr(ido) % coeff, insert_values, ierr)
622 this % n = this % n + csr(ido) % num_cols
630 petscerrorcode :: ierr
632 if (.not. this % mat_created)
then
633 stop
"Finalizing matrix that doesn't exist!!!"
635 write (stdout,
"('Finalizing SLEPC matrix')")
637 call matassemblybegin(this % A, mat_final_assembly, ierr)
638 call matassemblyend(this % A, mat_final_assembly, ierr)
643 write (stdout,
"('Finished assembly')")
652 write (stdout,
"('-------TEMP CACHE---------')")
653 call this % temp_cache % print
670 call this % destroy_PETSC_mat
675 petscint,
intent(inout),
dimension(:) :: a
676 petscscalar,
intent(inout),
dimension(:) :: coeff
679 if (
size(a) > 1)
then
681 call qsortcsr(a(:iq-1), coeff(:iq-1))
689 petscint,
intent(inout),
dimension(:) :: a
690 petscscalar,
intent(inout),
dimension(:) :: coeff
691 integer,
intent(out) :: marker
694 petscscalar :: temp_coeff
704 if (a(j) <= x_a)
exit
714 temp_a = a(i); a(i) = a(j); a(j) = temp_a
715 temp_coeff = coeff(i); coeff(i) = coeff(j); coeff(j) = temp_coeff
716 else if (i == j)
then