11 #include <PB3D_macros.h>
14 #include <slepc/finclude/slepceps.h>
39 petscreal :: step_size
42 integer,
allocatable :: c_tot(:,:,:)
43 logical :: use_hermitian = .false.
48 real(
dp) :: diff_coeff
70 character(*),
parameter :: rout_name =
'solve_EV_system_SLEPC'
84 character(len=max_str_ln) :: err_msg
90 call writo(
'Initialize generalized Eigenvalue problem')
97 step_size = (grid_sol%r_F(grid_sol%n(3))-grid_sol%r_F(1))/&
101 call writo(
'Set up matrices')
109 call writo(
'Testing if A and B are Hermitian by multiplying with &
110 &their Hermitian Transpose and subtracting 1')
113 ierr = test_mat_hermiticity(a,
'A')
116 ierr = test_mat_hermiticity(b,
'B')
124 call writo(
'Set up boundary conditions')
127 select case (matrix_slepc_style)
129 ierr =
set_bc(mds,grid_sol,x,vac,a,b)
133 call writo(
'Testing if AFTER INSERTING BC''s, A and B &
134 &are Hermitian by multiplying with their &
135 &Hermitian Transpose and subtracting 1')
138 ierr = test_mat_hermiticity(a,
'A_BC')
141 ierr = test_mat_hermiticity(b,
'B_BC')
149 err_msg =
'NOT YET IMPLEMENTED FOR SHELL MATRICES'
156 call writo(
'Set up EV solver with defaults')
160 call writo(
'Test spectrum of A or B instead of solving &
161 &generalized Eigenvalue problem?')
163 call writo(
'Spectrum of A (true) or B (false)?')
166 call writo(
'Testing spectrum of A')
170 call writo(
'Testing spectrum of B')
190 call writo(
'Set up guess')
198 call writo(
'Get solution')
204 call writo(
'Summarize solution')
210 call writo(
'Store results for '//trim(
i2str(max_n_ev))//
' least &
211 &stable Eigenvalues')
217 call writo(
'Finalize SLEPC')
226 integer function test_mat_hermiticity(mat,mat_name)
result(ierr)
230 character(*),
parameter :: rout_name =
'test_mat_hermiticity'
233 mat,
intent(in) :: mat
234 character(len=*) :: mat_name
239 petscscalar :: one = 1.0
240 petscviewer :: file_viewer
241 character(len=max_str_ln) :: file_name
247 call matconvert(mat,matmpiaij,mat_initial_matrix,mat_loc,ierr)
248 chckerr(
'Failed to convert mat into mat_loc')
251 call mathermitiantranspose(mat_loc,mat_initial_matrix,mat_t,ierr)
252 chckerr(
'Hermitian transpose of mat failed')
253 call mataxpy(mat_t,-one,mat_loc,same_nonzero_pattern,ierr)
254 chckerr(
'mat-mat_t failed')
257 call petscoptionssetvalue(petsc_null_options,
'-draw_pause',
'-1',&
259 chckerr(
'Failed to set option')
260 call writo(trim(mat_name)//
' =')
261 call matview(mat,petsc_viewer_stdout_world,ierr)
263 chckerr(
'Failed to view')
264 call writo(trim(mat_name)//
' - '//trim(mat_name)//
'^*T =')
265 call matview(mat_t,petsc_viewer_stdout_world,ierr)
266 chckerr(
'Failed to view')
269 call matdestroy(mat_t,ierr)
270 chckerr(
'Failed to destroy matrix mat_t')
271 call matdestroy(mat_loc,ierr)
272 chckerr(
'Failed to destroy matrix mat_loc')
280 file_name = trim(
data_dir)//
'/'//trim(mat_name)
281 call petscviewerasciiopen(petsc_comm_world,trim(file_name),&
283 chckerr(
'Unable to open file viewer')
285 call petscviewersetformat(file_viewer,petsc_viewer_ascii_matlab,ierr)
286 chckerr(
'Unable to set format')
288 call matview(mat,file_viewer,ierr)
289 chckerr(
'Unable to write matrix to file')
290 call petscviewerdestroy(file_viewer,ierr)
291 chckerr(
'Unable to destroy file viewer')
324 end function test_mat_hermiticity
336 character(*),
parameter :: rout_name =
'start_SLEPC'
339 integer,
intent(in) :: n_r_sol
344 character(len=max_str_ln) :: option_name
345 character(len=max_str_ln) :: err_msg
351 call writo(
'initialize SLEPC...')
355 petsc_comm_world = mpi_comm_world
358 &
', while beyond '//trim(
i2str(n_r_sol))//&
359 &
' does not bring improvement',warning=.true.)
361 call slepcinitialize(petsc_null_character,ierr)
362 chckerr(
'SLEPC failed to initialize')
373 call writo(
'run tests...')
374 #if defined(PETSC_USE_COMPLEX)
377 err_msg =
'PETSC and SLEPC have to be configured and compiled &
378 &with the option "--with-scalar-type=complex"'
379 call slepcfinalize(ierr)
387 if (trim(option_name).ne.
'')
then
388 call petscoptionshasname(petsc_null_options,&
389 &petsc_null_character,trim(option_name),flg,ierr)
392 err_msg =
'Failed to decide whether option has a name'
408 integer function setup_mats(mds,grid_sol,X,A,B)
result(ierr)
421 character(*),
parameter :: rout_name =
'setup_mats'
426 type(
x_2_type),
intent(in),
target :: x
427 mat,
intent(inout) :: a
428 mat,
intent(inout) :: b
432 integer :: norm_id(2)
434 petscint :: i_lims(2)
435 petscint,
allocatable :: d_nz(:)
436 petscint,
allocatable :: o_nz(:)
437 character(len=max_str_ln) :: err_msg
440 petscint :: bulk_i_lim(2)
446 select case (norm_disc_style_sol)
448 call writo(
'Normal discretization with central finite &
449 &differences of order '//trim(
i2str(ndps))//&
450 &
', stencil width '//trim(
i2str(2*ndps+1)))
452 call writo(
'Normal discretization with left finite &
453 &differences of order '//trim(
i2str(ndps))//&
454 &
', stencil width '//trim(
i2str(ndps+1)))
456 err_msg =
'No solution normal discretization style associated &
457 &with '//trim(
i2str(norm_disc_style_sol))
464 call writo(
'Test introduction of numerical friction?')
467 call writo(
'The friction coefficient will be multiplied with &
468 &the central block, and inserted in the off-diagonal parts')
469 call writo(
'How large should it be?')
478 err_msg =
'Need square matrix of size [n_mod_X:n_mod_X]'
483 if (.not.
allocated(c_tot))
then
487 c_tot(id,kd,1) =
c([id,kd],.true.,
n_mod_x)
488 c_tot(id,kd,2) =
c([id,kd],.false.,
n_mod_x)
494 ierr =
trim_grid(grid_sol,grid_sol_trim,norm_id)
498 if (rank.lt.sol_n_procs)
then
499 loc_n_r = grid_sol_trim%loc_n_r
503 n_r = grid_sol_trim%n(3)
506 ierr = set_bulk_lims(grid_sol_trim,bulk_i_lim)
508 i_lims = [grid_sol_trim%i_min, grid_sol_trim%i_max]
511 if (norm_disc_style_sol.eq.1 .and. bc_style(2).eq.3)
then
513 if (rank.eq.sol_n_procs-1)
then
514 loc_n_r = loc_n_r + ndps
515 i_lims(2) = i_lims(2) + ndps
520 select case (matrix_slepc_style)
523 call set_nonzeros(i_lims)
528 &petsc_null_integer,d_nz,petsc_null_integer,o_nz,a,ierr)
529 err_msg =
'MatCreateAIJ failed for matrix A'
533 deallocate(d_nz,o_nz)
536 ierr = fill_mat(x%PV_0(1,:,norm_id(1):norm_id(2),:),&
537 &x%PV_1(1,:,norm_id(1):norm_id(2),:),&
538 &x%PV_2(1,:,norm_id(1):norm_id(2),:),bulk_i_lim,a)
541 call writo(
'matrix A set up:')
542 ierr = disp_mat_info(a)
546 call matduplicate(a,mat_share_nonzero_pattern,b,ierr)
547 chckerr(
'failed to duplicate A into B')
550 ierr = fill_mat(x%KV_0(1,:,norm_id(1):norm_id(2),:),&
551 &x%KV_1(1,:,norm_id(1):norm_id(2),:),&
552 &x%KV_2(1,:,norm_id(1):norm_id(2),:),bulk_i_lim,b)
555 call writo(
'matrix B set up:')
556 ierr = disp_mat_info(b)
560 err_msg =
'NOT YET IMPLEMENTED FOR SHELL MATRICES'
565 call grid_sol_trim%dealloc()
570 integer function set_bulk_lims(grid_sol,i_lim)
result(ierr)
571 character(*),
parameter :: rout_name =
'set_bulk_lims'
575 integer,
intent(inout) :: i_lim(2)
581 select case (bc_style(1))
583 i_lim(1) = max(grid_sol%i_min,ndps+1)
585 err_msg =
'Left BC''s cannot have BC type '//&
586 &trim(
i2str(bc_style(1)))
590 err_msg =
'No BC style associated with '//&
591 &trim(
i2str(bc_style(1)))
602 select case (bc_style(2))
604 i_lim(2) = min(grid_sol%i_max,n_r)
606 i_lim(2) = min(grid_sol%i_max,n_r)
608 err_msg =
'No BC style associated with '//&
609 &trim(
i2str(bc_style(2)))
613 end function set_bulk_lims
623 integer function fill_mat(V_0,V_1,V_2,bulk_i_lim,mat)
result(ierr)
626 character(*),
parameter :: rout_name =
'fill_mat'
629 petscscalar,
intent(in) :: v_0(:,:,:)
630 petscscalar,
intent(in) :: v_1(:,:,:)
631 petscscalar,
intent(in) :: v_2(:,:,:)
632 petscint,
intent(in) :: bulk_i_lim(2)
633 mat,
intent(inout) :: mat
636 character(len=max_str_ln) :: err_msg
637 petscscalar,
allocatable :: loc_block(:,:)
638 petscreal,
allocatable :: ndc(:)
639 petscint :: id, jd, kd
645 petscscalar,
allocatable :: loc_block_0_backup(:,:)
649 petscint :: r_sol_start, r_sol_end
655 call matgetownershiprange(mat,r_sol_start,r_sol_end,ierr)
656 err_msg =
'Couldn''t get ownership range of matrix'
658 r_sol_start = r_sol_start/
n_mod_x
660 if (norm_disc_style_sol.eq.1 .and. bc_style(2).eq.3)
then
661 if (rank.eq.sol_n_procs-1) r_sol_end = r_sol_end - ndps
663 if (rank.lt.sol_n_procs)
then
664 if (grid_sol_trim%i_min.ne.r_sol_start+1)
then
666 err_msg =
'start of matrix in this process does not &
667 &coincide with tabulated value'
670 if (grid_sol_trim%i_max.ne.r_sol_end)
then
672 err_msg =
'end of matrix in this process does not &
673 &coincide with tabulated value'
682 do kd = bulk_i_lim(1)-1,bulk_i_lim(2)-1
684 kd_loc = kd+2-grid_sol_trim%i_min
687 select case (norm_disc_style_sol)
689 if ((bc_style(2).eq.2 .or. bc_style(2).eq.4) &
690 &.and. kd.gt.n_r-1-ndps)
then
691 ndc_ind = 1+2*ndps - (n_r-1-kd)
713 &
con(sum(v_0(:,kd_loc,c_tot(k,m,1))),&
717 loc_block = loc_block*step_size
723 loc_block_0_backup = loc_block
737 loc_block(k,m) = sum(v_1(:,kd_loc,c_tot(k,m,2)))
740 loc_block = loc_block*step_size
746 &kd,[0,jd-ndc_ind],n_r,transp=.true.)
757 &
con(sum(v_2(:,kd_loc,c_tot(k,m,1))),[k,m],.true.)
760 loc_block = loc_block*step_size
764 loc_block = loc_block + diff_coeff*loc_block_0_backup
765 deallocate(loc_block_0_backup)
774 &mat,kd,[id-ndc_ind,jd-ndc_ind],n_r)
781 call matassemblybegin(mat,mat_final_assembly,ierr)
782 chckerr(
'Coulnd''t begin assembly of matrix')
783 call matassemblyend(mat,mat_final_assembly,ierr)
784 chckerr(
'Coulnd''t end assembly of matrix')
787 if (use_hermitian)
then
788 call matsetoption(mat,mat_hermitian,petsc_true,ierr)
789 chckerr(
'Coulnd''t set option Hermitian')
793 deallocate(loc_block)
794 end function fill_mat
798 integer function disp_mat_info(mat)
result(ierr)
799 character(*),
parameter :: rout_name =
'disp_mat_info'
802 mat,
intent(inout) :: mat
805 real(dp) :: mat_info(mat_info_size)
812 select case (matrix_slepc_style)
814 call matgetinfo(mat,mat_global_sum,mat_info,ierr)
816 call writo(
'memory usage: '//&
817 &trim(
r2strt(mat_info(mat_info_memory)*1.e-6_dp))//&
819 call writo(
'nonzero''s allocated: '//&
820 &trim(
r2strt(mat_info(mat_info_nz_allocated))))
821 if (mat_info(mat_info_nz_unneeded).gt.0._dp)
then
822 call writo(
'of which unused: '//&
823 &trim(
r2strt(mat_info(mat_info_nz_unneeded))))
826 call writo(
'shell matrix')
830 end function disp_mat_info
835 subroutine set_nonzeros(i_lims)
837 petscint,
intent(in) :: i_lims(2)
840 petscint,
allocatable :: col_lims(:,:)
841 petscint,
allocatable :: tot_nz(:)
842 petscint :: st_size(2)
845 allocate(tot_nz(loc_n_r)); tot_nz = 0
846 allocate(d_nz(loc_n_r)); d_nz = 0
847 allocate(o_nz(loc_n_r)); o_nz = 0
850 allocate(col_lims(loc_n_r,2)); col_lims = 0
852 if (rank.lt.sol_n_procs)
then
854 select case (norm_disc_style_sol)
856 st_size = [ndps,ndps]
869 col_lims(kd,1) = max(kd+i_lims(1)-1-sum(st_size),1)
870 col_lims(kd,2) = min(kd+i_lims(1)-1+sum(st_size),n_r)
875 tot_nz = col_lims(:,2) - col_lims(:,1) + 1
883 o_nz(kd) = max(0,i_lims(1)-col_lims(kd,1)) + &
884 &max(0,col_lims(kd,2)-i_lims(2))
896 end subroutine set_nonzeros
932 integer function set_bc(mds,grid_sol,X,vac,A,B)
result(ierr)
940 character(*),
parameter :: rout_name =
'set_BC'
947 mat,
intent(inout) :: a
948 mat,
intent(inout) :: b
952 petscint :: n_min, n_max
953 character(len=max_str_ln) :: err_msg
958 call writo(
'Preparing variables')
964 err_msg =
'Need square matrix of size [n_mod_X:n_mod_X]'
975 err_msg =
'Left BC''s cannot have BC type '//&
980 err_msg =
'No BC style associated with '//&
1002 err_msg =
'No BC style associated with '//&
1008 call writo(
'Setting BC deep within plasma')
1014 if (grid_sol%i_min.le.kd .and. grid_sol%i_max.ge.kd)
then
1017 ierr = set_bc_1(kd-1,a,b,.false.)
1020 err_msg =
'Left BC''s cannot have BC type '//&
1025 err_msg =
'No BC style associated with '//&
1034 call matassemblybegin(a,mat_final_assembly,ierr)
1035 chckerr(
'Coulnd''t begin assembly of matrix')
1036 call matassemblybegin(b,mat_final_assembly,ierr)
1037 chckerr(
'Coulnd''t begin assembly of matrix')
1038 call matassemblyend(a,mat_final_assembly,ierr)
1039 chckerr(
'Coulnd''t end assembly of matrix')
1040 call matassemblyend(b,mat_final_assembly,ierr)
1041 chckerr(
'Coulnd''t end assembly of matrix')
1049 call writo(
'Setting BC at plasma edge')
1053 do kd = grid_sol%n(3),grid_sol%n(3)-n_max+1,-1
1054 if (grid_sol%i_min.le.kd .and. grid_sol%i_max.ge.kd)
then
1057 ierr = set_bc_1(kd-1,a,b,.true.)
1060 ierr = set_bc_2(kd-1,a)
1063 ierr = set_bc_3(kd-1,a)
1066 ierr = set_bc_4(kd-1,kd-grid_sol%i_min+1,x,a,b,&
1070 err_msg =
'No BC style associated with '//&
1079 call matassemblybegin(a,mat_final_assembly,ierr)
1080 chckerr(
'Coulnd''t begin assembly of matrix')
1081 call matassemblybegin(b,mat_final_assembly,ierr)
1082 chckerr(
'Coulnd''t begin assembly of matrix')
1083 call matassemblyend(a,mat_final_assembly,ierr)
1084 chckerr(
'Coulnd''t end assembly of matrix')
1085 call matassemblyend(b,mat_final_assembly,ierr)
1086 chckerr(
'Coulnd''t end assembly of matrix')
1096 integer function set_bc_1(r_id,A,B,BC_right)
result(ierr)
1097 character(*),
parameter :: rout_name =
'set_BC_1'
1100 integer,
intent(in) :: r_id
1101 mat,
intent(inout) :: a, b
1106 petscscalar,
allocatable :: loc_block(:,:)
1114 call writo(
'Boundary style at row '//trim(
i2str(r_id+1))//&
1115 &
': Eigenvector set to zero',persistent=.true.)
1121 loc_block(kd,kd) = 1.0_dp
1141 &overwrite=.true.,ind_insert=.true.)
1144 &overwrite=.true.,ind_insert=.true.)
1151 &n_r,overwrite=.true.,transp=.true.,ind_insert=.true.)
1154 &n_r,overwrite=.true.,transp=.true.,ind_insert=.true.)
1159 deallocate(loc_block)
1160 end function set_bc_1
1165 integer function set_bc_2(r_id,A)
result(ierr)
1166 character(*),
parameter :: rout_name =
'set_BC_2'
1169 integer,
intent(in) :: r_id
1170 mat,
intent(inout) :: a
1176 call writo(
'Boundary style at row '//trim(
i2str(r_id+1))//&
1177 &
': Minimization of surface energy through asymmetric finite &
1178 & differences',persistent=.true.)
1185 chckerr(
'Vacuum has not been implemented yet!')
1189 end function set_bc_2
1194 integer function set_bc_3(r_id,A)
result(ierr)
1195 character(*),
parameter :: rout_name =
'set_BC_3'
1198 integer,
intent(in) :: r_id
1199 mat,
intent(inout) :: a
1205 call writo(
'Boundary style at row '//trim(
i2str(r_id+1))//&
1206 &
': Minimization of surface energy through extension of grid',&
1214 chckerr(
'Vacuum has not been implemented yet!')
1218 end function set_bc_3
1226 integer function set_bc_4(r_id,r_id_loc,X,A,B,n_r)
result(ierr)
1230 character(*),
parameter :: rout_name =
'set_BC_4'
1233 integer,
intent(in) :: r_id
1234 integer,
intent(in) :: r_id_loc
1236 mat,
intent(inout) :: a, b
1237 integer,
intent(in) :: n_r
1243 petscreal,
allocatable :: ndc(:)
1244 petscscalar,
allocatable :: loc_block(:,:,:)
1250 call writo(
'Boundary style at row '//trim(
i2str(r_id+1))//&
1251 &
': Explicit introduction of surface energy minimization',&
1274 loc_block(k,m,1) = conjg(sum(&
1275 &x%PV_1(1,:,r_id_loc,c([m,k],.false.,
n_mod_x))))
1276 loc_block(k,m,2) = conjg(sum(&
1277 &x%KV_1(1,:,r_id_loc,c([m,k],.false.,
n_mod_x))))
1280 loc_block(:,:,1) = loc_block(:,:,1) + vac%res
1284 &[0,0],n_r,overwrite=.true.,ind_insert=.true.)
1288 &[0,0],n_r,overwrite=.true.,ind_insert=.true.)
1297 loc_block(k,m,1) = &
1298 &
con(sum(x%PV_2(1,:,r_id_loc,c([k,m],.true.,
n_mod_x))),&
1300 loc_block(k,m,2) = &
1301 &
con(sum(x%KV_2(1,:,r_id_loc,c([k,m],.true.,
n_mod_x))),&
1309 &ndc(jd+st_size+1)*ndc(1+st_size),a,&
1310 &r_id,[0,jd],n_r,overwrite=.true.,&
1314 &ndc(jd+st_size+1)*ndc(1+st_size),b,&
1315 &r_id,[0,jd],n_r,overwrite=.true.,&
1319 end function set_bc_4
1325 integer function setup_solver(X,A,B,solver)
result(ierr)
1331 character(*),
parameter :: rout_name =
'setup_solver'
1335 mat,
intent(in) :: a, b
1336 eps,
intent(inout) :: solver
1339 petscscalar :: one = 1.0
1342 character(len=max_str_ln) :: err_msg
1350 err_msg =
'Need square matrix of size [n_mod_X:n_mod_X]'
1355 call epscreate(petsc_comm_world,solver,ierr)
1356 chckerr(
'EPSCreate failed')
1358 call epssetoperators(solver,a,b,ierr)
1359 chckerr(
'EPSetOperators failed')
1361 if (use_hermitian)
then
1362 call writo(
'Set problem type to Generalized Hermitian')
1363 call epssetproblemtype(solver,eps_ghep,ierr)
1364 chckerr(
'Set problem type failed')
1371 call writo(
'set algorithm to Krylov-Schur')
1372 call epssettype(solver,epskrylovschur,ierr)
1373 err_msg =
'Failed to set type to Krylov-Schur'
1377 call epsgetst(solver,solver_st,ierr)
1378 err_msg =
'Failed to get ST from solver'
1383 call writo(
'use shift-invert')
1384 call stsettype(solver_st,stsinvert,ierr)
1385 err_msg =
'Failed to set type to STSINVERT'
1389 call writo(
'set algorithm to Generalized Davidson')
1390 call epssettype(solver,epsgd,ierr)
1391 err_msg =
'Failed to set type to Generalized Davidson'
1396 call writo(
'This is often less robust than the Krylov-Schur &
1397 &method.',alert=.true.)
1399 call writo(
'If it converges to a strange result, try using &
1405 call epsgetst(solver,solver_st,ierr)
1406 err_msg =
'Failed to get ST from solver'
1410 call writo(
'Use preconditioner')
1411 call stsettype(solver_st,stprecond,ierr)
1412 err_msg =
'Failed to set type to STPRECOND'
1415 call writo(
'SLEPC solver style '//&
1422 call epssettarget(solver,
ev_guess*one,ierr)
1423 err_msg =
'Failed to set the target of solver'
1428 call writo(
'max. nr. of solutions requested capped to problem &
1431 call writo(
'Increase either n_r or number of pol. modes or &
1432 &decrease n_sol_requested')
1437 call epssetdimensions(solver,n_sol,petsc_decide,&
1439 chckerr(
'EPSSetDimensions failed')
1441 chckerr(
'EPSSetTolerances failed')
1445 call writo(
'set maximum nr. of iterations to '//&
1452 integer function setup_guess(sol,A,solver)
result(ierr)
1453 character(*),
parameter :: rout_name =
'setup_guess'
1457 mat,
intent(in) :: a
1458 eps,
intent(inout) :: solver
1461 vec,
allocatable :: guess_vec(:)
1463 petscint :: n_ev_prev
1464 petscscalar,
pointer :: guess_vec_ptr(:)
1465 character(len=max_str_ln) :: err_msg
1473 if (
allocated(sol%val))
then
1475 n_ev_prev =
size(sol%val)
1477 if (n_ev_prev.gt.0)
then
1480 &
' vector(s) as guess')
1483 allocate(guess_vec(n_ev_prev))
1488 call matcreatevecs(a,guess_vec(kd),petsc_null_vec,ierr)
1489 chckerr(
'Failed to create vector')
1492 call vecgetarrayf90(guess_vec(kd),guess_vec_ptr,ierr)
1493 chckerr(
'Failed to get pointer')
1496 guess_vec_ptr(1:
size(sol%vec(:,:,kd))) = &
1497 &reshape([sol%vec(:,:,kd)],&
1498 &[
size(sol%vec(:,:,kd))])
1499 guess_vec_ptr(
size(sol%vec(:,:,kd))+1:
size(guess_vec_ptr)) &
1500 &= guess_vec_ptr(
size(sol%vec(:,:,kd)))
1503 call vecrestorearrayf90(guess_vec(kd),guess_vec_ptr,ierr)
1504 chckerr(
'Failed to restore pointer')
1512 call epssetinitialspace(solver,n_ev_prev,guess_vec,ierr)
1513 chckerr(
'Failed to set guess')
1516 do kd = 1,
size(guess_vec)
1517 call vecdestroy(guess_vec(kd),ierr)
1518 err_msg =
'Failed to destroy guess vector '//trim(
i2str(kd))
1521 deallocate(guess_vec)
1523 call writo(
'No vectors saved to use as guess')
1534 character(*),
parameter :: rout_name =
'get_solution'
1537 eps,
intent(inout) :: solver
1540 character(len=max_str_ln) :: err_msg
1548 call epssetfromoptions(solver,ierr)
1549 chckerr(
'EPSetFromOptions failed')
1552 call epssolve(solver,ierr)
1553 err_msg =
'EPS couldn''t find a solution. Maybe you should increase &
1554 &the number of parallel points.'
1566 character(*),
parameter :: rout_name =
'summarize_solution'
1569 eps,
intent(inout) :: solver
1570 petscint,
intent(inout) :: max_n_ev
1575 petscint :: n_ev, ncv, mpd
1586 call epsgettype(solver,eps_type,ierr)
1587 chckerr(
'EPSGetType failed')
1588 call epsgettolerances(solver,tol,max_it,ierr)
1589 chckerr(
'EPSGetTolerances failed')
1590 call writo(trim(eps_type)//
' solver with tolerance '//&
1591 &trim(
r2strt(tol))//
' and maximum '//trim(
i2str(max_it))//&
1593 call epsgetconverged(solver,n_conv,ierr)
1594 chckerr(
'EPSGetConverged failed')
1595 call epsgetiterationnumber(solver,n_it,ierr)
1596 chckerr(
'EPSGetIterationNumber failed')
1597 call epsgetdimensions(solver,n_ev,ncv,mpd,ierr)
1598 chckerr(
'EPSGetDimensions failed')
1599 call writo(
'number of iterations: '//trim(
i2str(n_it)))
1600 call writo(
'number of converged solutions: '//trim(
i2str(n_conv)))
1601 call writo(
'number of requested solutions: '//trim(
i2str(n_ev)))
1602 call writo(
'maximum dimension of the subspace to be used by solver: '//&
1604 call writo(
'maximum dimension allowed for projected problem : '//&
1609 if (n_conv.eq.0)
then
1610 call writo(
'no solutions found',warning=.true.)
1612 call writo(
'max. nr. of solutions found only '//&
1613 &trim(
i2str(n_conv)),warning=.true.)
1621 if (max_n_ev.le.0)
then
1623 chckerr(
'No solutions found')
1632 integer function store_results(mds,grid_sol,sol,solver,max_n_EV,A,B) &
1643 character(*),
parameter :: rout_name =
'store_results'
1648 type(
sol_type),
intent(inout) :: sol
1649 eps,
intent(inout) :: solver
1650 petscint,
intent(inout) :: max_n_ev
1651 mat,
intent(inout) :: a
1652 mat,
intent(inout) :: b
1663 petscint,
allocatable :: sol_vec_max_loc(:)
1665 petscreal :: error_est
1666 petscreal :: err_norm
1667 petscreal :: tol_complex
1668 petscreal :: tol_ev_bc = 1.e-3_dp
1669 petscreal,
parameter :: infinity = 1.e40_dp
1670 petscscalar :: sol_val_loc
1671 petscscalar :: err_val
1672 petscscalar :: e_val(2)
1673 petscscalar,
allocatable :: sol_vec_loc(:,:)
1674 petscscalar,
allocatable :: sol_vec_max(:)
1675 character(len=max_str_ln) :: full_output_name
1676 character(len=max_str_ln) :: format_val
1677 character(len=max_str_ln) :: format_head
1678 character(len=max_str_ln) :: ev_err_str
1679 character(len=max_str_ln) :: err_msg
1680 character(len=2*max_str_ln) :: temp_output_str
1690 ierr =
trim_grid(grid_sol,grid_sol_trim)
1694 if (
allocated(sol%val))
call sol%dealloc()
1695 call sol%init(mds,grid_sol_trim,max_n_ev)
1698 call veccreatempiwitharray(petsc_comm_world,one,loc_n_r*
n_mod_x,&
1699 &n_r*
n_mod_x,petsc_null_scalar,sol_vec,ierr)
1700 chckerr(
'Failed to create MPI vector with arrays')
1710 n_digits = min(ceiling(log10(1._dp*max_n_ev)),16)
1711 format_val =
'(A2,I'//trim(
i2str(n_digits))//
'," ",ES23.16," ",&
1712 &ES23.16," ",ES23.16)'
1713 format_head =
'(A'//trim(
i2str(n_digits+3))//
'," ",A23," ",A23," ",&
1721 open(
output_ev_i,file=full_output_name,status=
'replace',&
1723 chckerr(
'Cannot open EV output file')
1730 &
'# Eigenvalues normalized to the squared Alfven &
1731 &frequency omega_A^2 = '
1732 chckerr(
'Failed to write')
1736 &
'# ('//trim(
r2str(1._dp/
t_0))//
' Hz)^2 = '//&
1737 &trim(
r2str(1._dp/
t_0**2))//
' Hz^2'
1738 chckerr(
'Failed to write')
1741 &
'# (MISHKA normalization)'
1742 chckerr(
'Failed to write')
1745 write(unit=
output_ev_i,fmt=
'(A)',iostat=ierr)
'# Eigenvalues'
1746 chckerr(
'Failed to write')
1748 write(temp_output_str,format_head) &
1750 &
'real part ',
'imaginary part ', &
1751 &
'relative precision '
1752 write(unit=
output_ev_i,fmt=
'(A)',iostat=ierr) trim(temp_output_str)
1753 chckerr(
'Failed to write')
1757 allocate(sol_vec_max(
n_procs))
1758 allocate(sol_vec_max_loc(2))
1759 allocate(sol_vec_loc(
n_mod_x,loc_n_r))
1766 do while (id.le.max_n_ev)
1767 call vecplacearray(sol_vec,sol_vec_loc,ierr)
1768 chckerr(
'Failed to place array')
1769 call epsgeteigenpair(solver,id_tot-1,sol%val(id),petsc_null_scalar,&
1770 &sol_vec,petsc_null_vec,ierr)
1771 chckerr(
'EPSGetEigenpair failed')
1772 sol%vec(:,:,id) = sol_vec_loc(:,1:
size(sol%vec,2))
1773 call epscomputeerror(solver,id_tot-1,eps_error_relative,error,ierr)
1775 chckerr(
'EPSComputeError failed')
1778 sol_val_loc = sol%val(id)
1782 if (abs(ip(sol%val(id))/rp(sol%val(id))).gt.tol_complex)
then
1783 ev_err_str =
'# WARNING: Unphysical complex Eigenvalue!'
1784 n_err(1) = n_err(1)+1
1785 call remove_ev(id,max_n_ev)
1786 else if (abs(rp(sol%val(id)-
ev_bc)/
ev_bc).lt.tol_ev_bc)
then
1787 ev_err_str =
'# WARNING: Eigenvalue probably due to BC''s &
1789 n_err(2) = n_err(2)+1
1790 call remove_ev(id,max_n_ev)
1791 else if (abs(sol%val(id)).gt.infinity)
then
1792 ev_err_str =
'# WARNING: The next Eigenvalues are larger &
1793 &than '//trim(
r2strt(infinity))//
' and are discarded'
1795 call remove_ev(id,max_n_ev,remove_next=.true.)
1801 if (ev_err_str.ne.
'')
then
1802 write(temp_output_str,format_val)
'#', id,rp(sol_val_loc),&
1803 &ip(sol_val_loc),error
1805 write(temp_output_str,format_val)
'', id,rp(sol_val_loc),&
1806 &ip(sol_val_loc),error
1809 &trim(temp_output_str)
1810 chckerr(
'Failed to write')
1813 if (ev_err_str.ne.
'')
then
1816 chckerr(
'Failed to write')
1821 if (ev_err_str.eq.
'')
then
1823 sol_vec_max_loc = maxloc(abs(sol%vec(:,:,id)))
1825 &[sol%vec(sol_vec_max_loc(1),sol_vec_max_loc(2),id)],&
1826 &sol_vec_max,scatter=.true.)
1829 sol_vec_max_loc(1) = maxloc(abs(sol_vec_max),1)
1830 sol%vec(:,:,id) = sol%vec(:,:,id) / &
1831 &sol_vec_max(sol_vec_max_loc(1))
1833 call epsgeterrorestimate(solver,id_tot-1,error_est,ierr)
1834 chckerr(
'EPSGetErrorEstimate failed')
1836 call writo(
'Checking whether A x - omega^2 B x = 0 for EV '//&
1837 &trim(
i2str(id))//
': '//trim(
c2strt(sol%val(id))))
1841 call matduplicate(a,mat_share_nonzero_pattern,err_mat,ierr)
1842 err_msg =
'failed to duplicate mat into err_mat'
1844 call matcopy(a,err_mat,mat_share_nonzero_pattern,ierr)
1845 chckerr(
'Failed to copy mat into mat_loc')
1846 call mataxpy(err_mat,-sol%val(id),b,different_nonzero_pattern,&
1848 chckerr(
'Failed to perform AXPY')
1851 call vecduplicate(sol_vec,err_vec,ierr)
1852 chckerr(
'Failed to duplicate vector')
1855 call matmult(err_mat,sol_vec,err_vec,ierr)
1856 chckerr(
'Failed to multiply')
1859 call vecdot(err_vec,sol_vec,err_val,ierr)
1860 chckerr(
'Failed to do dot product')
1861 call writo(
'X*(A-omega^2B)X = '//trim(
c2strt(err_val)))
1864 call vecnorm(err_vec,norm_2,err_norm,ierr)
1865 chckerr(
'Failed to calculate norm')
1868 err_norm = err_norm/abs(sol%val(id))
1871 call writo(
'error: '//trim(
r2str(err_norm))//
', given: '//&
1872 &trim(
r2str(error))//
', estimate: '//trim(
r2str(error_est)))
1877 call vecduplicate(sol_vec,e_vec(1),ierr)
1878 chckerr(
'Failed to duplicate vector')
1879 call vecduplicate(sol_vec,e_vec(2),ierr)
1880 chckerr(
'Failed to duplicate vector')
1883 call matmult(a,sol_vec,e_vec(1),ierr)
1884 chckerr(
'Failed to multiply')
1885 call matmult(b,sol_vec,e_vec(2),ierr)
1886 chckerr(
'Failed to multiply')
1889 call vecdot(e_vec(1),sol_vec,e_val(1),ierr)
1890 chckerr(
'Failed to do dot product')
1891 call writo(
'step_size = '//trim(
r2str(step_size)))
1892 call writo(
'E_pot = X*AX*step_size = '//&
1893 &trim(
c2str(e_val(1)*step_size)))
1894 call vecdot(e_vec(2),sol_vec,e_val(2),ierr)
1895 chckerr(
'Failed to do dot product')
1896 call writo(
'E_kin = X*BX*step_size = '//&
1897 &trim(
c2str(e_val(2)*step_size)))
1898 call writo(
'X*AX/X*BX = '//trim(
c2str(e_val(1)/e_val(2))))
1899 call writo(
'omega^2 = '//trim(
c2str(sol%val(id))))
1902 if (rp(sol%val(id)).gt.0._dp)
then
1903 call writo(
'The eigenvalue is positive, so the mode could &
1904 &be stable.',warning=.true.)
1906 call writo(
'But this could also be due to value of "ncv" &
1908 call writo(
'Have a look at the POST output and/or try &
1909 &increasing "ncv".')
1919 call vecdestroy(err_vec,ierr)
1920 chckerr(
'Failed to destroy err_vec')
1921 call matdestroy(err_mat,ierr)
1922 chckerr(
'Failed to destroy err_mat')
1923 do jd = 1,
size(e_vec)
1924 call vecdestroy(e_vec(jd),ierr)
1925 err_msg =
'Failed to destroy E_vec '//trim(
i2str(jd))
1934 call vecresetarray(sol_vec,ierr)
1935 chckerr(
'Failed to reset array')
1942 deallocate(sol_vec_max_loc)
1943 deallocate(sol_vec_max)
1950 &
' Eigenvalues were written in the file "'//&
1951 &trim(full_output_name)//
'"')
1952 if (sum(n_err).ne.0)
then
1953 call writo(
'there were some Eigenvalues that were removed:')
1956 if (n_err(1).gt.0)
call writo(trim(
i2str(n_err(1)))//&
1957 &
' unphysical complex Eigenvalues')
1958 if (n_err(2).gt.0)
call writo(trim(
i2str(n_err(2)))//&
1959 &
' Eigenvalues due to the boundary conditions')
1960 if (n_err(3).gt.0)
call writo(
'The final Eigenvalues became &
1965 call writo(
'(But this was overriden using "retain_all_sol")')
1967 call writo(
'(Override this behavior using "retain_all_sol")')
1971 if (max_n_ev.gt.0)
then
1972 call writo(
'basic statistics:')
1976 call writo(
'max: '//trim(
c2strt(sol%val(max_n_ev))))
1984 call vecdestroy(sol_vec,ierr)
1985 chckerr(
'Failed to destroy sol_vec')
1990 call grid_sol_trim%dealloc()
1995 subroutine remove_ev(id,max_id,remove_next)
1997 petscint,
intent(inout) :: id
1998 petscint,
intent(inout) :: max_id
1999 petscbool,
intent(in),
optional :: remove_next
2002 petscscalar,
allocatable :: sol_val_loc(:)
2003 petscscalar,
allocatable :: sol_vec_loc(:,:,:)
2004 petscbool :: remove_next_loc = .false.
2011 if (
present(remove_next)) remove_next_loc = remove_next
2014 allocate(sol_val_loc(max_id))
2015 allocate(sol_vec_loc(
n_mod_x,grid_sol_trim%loc_n_r,max_id))
2016 sol_val_loc = sol%val
2017 sol_vec_loc = sol%vec
2020 deallocate(sol%val,sol%vec)
2021 if (remove_next_loc)
then
2022 allocate(sol%val(id-1))
2023 allocate(sol%vec(
n_mod_x,grid_sol_trim%loc_n_r,id-1))
2025 allocate(sol%val(max_id-1))
2026 allocate(sol%vec(
n_mod_x,grid_sol_trim%loc_n_r,max_id-1))
2030 sol%val(1:id-1) = sol_val_loc(1:id-1)
2031 sol%vec(:,:,1:id-1) = sol_vec_loc(:,:,1:id-1)
2032 if (.not.remove_next_loc)
then
2033 sol%val(id:max_id-1) = sol_val_loc(id+1:max_id)
2034 sol%vec(:,:,id:max_id-1) = sol_vec_loc(:,:,id+1:max_id)
2038 if (remove_next_loc)
then
2045 deallocate(sol_val_loc,sol_vec_loc)
2047 end subroutine remove_ev
2053 integer function stop_slepc(A,B,solver)
result(ierr)
2054 character(*),
parameter :: rout_name =
'stop_SLEPC'
2057 mat,
intent(in) :: a, b
2058 eps,
intent(in) :: solver
2066 call epsdestroy(solver,ierr)
2067 chckerr(
'Failed to destroy EPS solver')
2068 call matdestroy(a,ierr)
2069 chckerr(
'Failed to destroy matrix A')
2070 call matdestroy(b,ierr)
2071 chckerr(
'Failed to destroy matrix B')
2074 call slepcfinalize(ierr)
2075 chckerr(
'Failed to Finalize SLEPC')