PB3D [2.47]
Ideal linear high-n MHD stability in 3-D
Loading...
Searching...
No Matches
SLEPC_utilities.f90
Go to the documentation of this file.
1!------------------------------------------------------------------------------!
2!> Numerical utilities related to SLEPC (and PETSC) operations.
3!------------------------------------------------------------------------------!
4!> \see
5!! References:
6!! \cite Hernandez2005slepc
7!------------------------------------------------------------------------------!
9#include <PB3D_macros.h>
10#include <wrappers.h>
11#include <slepc/finclude/slepceps.h>
12! for slepc 3.6.0:
13!#include <slepc/finclude/slepcepsdef.h>
14! for slepc 3.5.3:
15!#include <finclude/slepcepsdef.h>
17 use output_ops
18 use messages
19 use slepceps
20 use num_vars, only: iu, dp, max_str_ln
21
22 implicit none
23 private
24 public insert_block_mat
25#if ldebug
27#endif
28
29 ! global variables
30#if ldebug
31 logical :: debug_insert_block_mat = .false. !< plot debug information for insert_block_mat() \ldebug
32#endif
33
34contains
35 !> Insert a block pertaining to 1 normal point into a matrix.
36 !!
37 !! Optionally, also set the Hermitian transpose and / or overwrite instead
38 !! of add value.
39 !!
40 !! This routine takes into account that if the mode numbers change as a
41 !! function of the normal coordinate, as is the case for X_style 2 (fast),
42 !! part of the local blocks, which were set up without taking this into
43 !! account, can have information that correspond to mode numbers that are
44 !! not present any more for off-diagonal entries, and lack an equal amount
45 !! of information that corresponds to the mode numbers that have taken their
46 !! places.
47 !!
48 !! Omission of this effect is justifiable if there are many more mode
49 !! couplings that are not omitted (i.e. when \c n_mod_X is large), so that
50 !! it is a small effect, and/or when the coupling between these modes is
51 !! already negligible.
52 !!
53 !! Unfortunately, it can be argued that this is not generally the case for
54 !! the fast version (\c X_style = 2) since \f$\widetilde{PV}^1\f$ and
55 !! \f$\widetilde{PV}^2\f$ are both \f$\sim (nq-m)\f$, which indicates that
56 !! the smallest elements in the corresponding off-diagonal blocks lie in the
57 !! central columns for \f$\widetilde{PV}^1\f$ and in the central columns and
58 !! rows for \f$\widetilde{PV}^2\f$, while the problematic elements lie
59 !! farthest away from the central columns for \f$\widetilde{PV}^1\f$ and the
60 !! central columns and rows for \f$\widetilde{PV}^2\f$, so these are
61 !! generally not small.
62 !!
63 !! The coefficients due to normal discretization get increasingly small for
64 !! higher orders, though, which compensates this for higher orders.
65 !!
66 !! Finally, an alternative would be to set the problematic elements not to
67 !! zero but extrapolated from the closest elements, but then consistency
68 !! would be sacrified, for example in the energy reconstruction of the
69 !! POST-processing: In the energy reconstruction the exact same terms are
70 !! neglected as well.
71 !!
72 !! To conclude, for fast \c X_style 2, the number of modes (\c n_mod_X) has
73 !! to be chosen high enough compared with the variation of the mode numbers;
74 !! i.e. the variation of the safety factor or rotational transform.
75 !!
76 !! \note The grid in which the modes variables \c mds are tabulated up must
77 !! be the same as the one in which \c mat is set up. If this is not the
78 !! case, the indices in \c mds have to be adapted.
79 !!
80 !! \return ierr
81 integer function insert_block_mat(mds,block,mat,r_id,ind,n_r,transp,&
82 &overwrite,ind_insert) result(ierr)
83 use x_vars, only: modes_type
84 use num_vars, only: use_pol_flux_f
85#if ldebug
86 use num_vars, only: rank
88#endif
89
90 character(*), parameter :: rout_name = 'insert_block_mat'
91
92 ! input / output
93 type(modes_type), intent(in), target :: mds !< general modes variables
94 petscscalar, intent(in) :: block(:,:) !< (\cn_mod x \cn_mod) block matrix for 1 normal point
95 mat, intent(inout) :: mat !< matrix in which to insert block
96 petscint, intent(in) :: r_id !< normal position of corresponding \f$\widetilde{V}^0\f$ (starting at 0)
97 petscint, intent(in) :: ind(2) !< 2D index in matrix, relative to \cr_id
98 petscint, intent(in) :: n_r !< number of grid points of solution grid
99 petscbool, intent(in), optional :: transp !< also set Hermitian transpose
100 petscbool, intent(in), optional :: overwrite !< overwrite
101 petscbool, intent(in), optional :: ind_insert !< individual insert, only important for debugging
102
103 ! local variables
104 petscint, pointer :: nm_x(:,:) ! m (pol. flux) or n (tor. flux)
105 petscbool :: transp_loc ! local copy of transp
106 petscbool :: overwrite_loc ! local copy of overwrite
107 character(len=max_str_ln) :: err_msg ! error message
108 petscint :: operation ! either ADD_VALUES or INSERT_VALUES
109 petscscalar, allocatable :: block_loc(:,:) ! local block, possibly shifted from block
110 petscbool :: ind_insert_loc ! local ind_insert
111
112 ! initialize ierr
113 ierr = 0
114
115 ! set up local transp, overwrite and ind_insert
116 transp_loc = .false.
117 if (present(transp)) transp_loc = transp
118 overwrite_loc = .false.
119 if (present(overwrite)) overwrite_loc = overwrite
120 ind_insert_loc = .false.
121 if (present(ind_insert)) ind_insert_loc = ind_insert
122
123 ! set operation
124 if (overwrite_loc) then
125 operation = insert_values
126 else
127 operation = add_values
128 end if
129
130 ! set nm_X
131 if (use_pol_flux_f) then
132 nm_x => mds%m
133 else
134 nm_x => mds%n
135 end if
136
137#if ldebug
138 ! user output
139 if (debug_insert_block_mat) then
140 if (.not.ind_insert_loc) call sleep(rank)
141 call writo('>>> rank '//trim(i2str(rank))//&
142 &': at (k,m) = '//trim(i2str(r_id))//' + ('//&
143 &trim(i2str(ind(1)))//','//trim(i2str(ind(2)))//'):',&
144 &persistent=.true.)
145 call lvl_ud(1)
146 end if
147#endif
148
149 ! only set values if within matrix range
150 if (minval(r_id+ind).ge.0 .and. maxval(r_id+ind).lt.n_r) then
151 ! set error message
152 err_msg = 'Couldn''t add values to matrix'
153
154 ! initialize
155 allocate(block_loc(size(block,1),size(block,2)))
156
157 ! untransposed block
158 call setup_local_block(nm_x,r_id,ind(1:2),block,block_loc)
159
160 ! set values
161 call matsetvaluesblocked(mat,1,r_id+ind(1),1,r_id+ind(2),&
162 &transpose(block_loc),operation,ierr)
163 chckerr(err_msg)
164
165 ! untransposed block
166 if (transp_loc) then
167#if ldebug
168 if (debug_insert_block_mat) then
169 call writo('Also at the transposed place:')
170 end if
171#endif
172
173 ! transposed block
174 call setup_local_block(nm_x,r_id,ind(2:1:-1),&
175 &transpose(conjg(block)),block_loc)
176
177 call matsetvaluesblocked(mat,1,r_id+ind(2),1,r_id+ind(1),&
178 &transpose(block_loc),operation,ierr)
179 chckerr(err_msg)
180 end if
181
182 ! clean up
183 deallocate(block_loc)
184 else
185#if ldebug
187 &call writo('Due to out of range no local block is added',&
188 &persistent=.true.)
189#endif
190 end if
191
192 ! clean up
193 nullify(nm_x)
194
195#if ldebug
196 if (debug_insert_block_mat) then
197 call pause_prog(ind_insert_loc)
198 call lvl_ud(-1)
199 endif
200#endif
201 contains
202 !> /private Set up local block, possibly translated for fast PB3D.
203 !!
204 !! \note For BC_style 3, there is a grid extension of n_r
205 !! beyond the tabulated modes variables, which is why there is a
206 !! 'min(..,size(nm_X,1))' here.
207 subroutine setup_local_block(nm_X,r_id,ind,block,block_loc)
208 use x_vars, only: n_mod_x
209
210 ! input / output
211 petscint, intent(in) :: nm_x(:,:) !< m (pol. flux) or n (tor. flux)
212 petscint, intent(in) :: r_id !< normal position of corresponding \f$\widetilde{V}^0\f$ (starting at 0)
213 petscint, intent(in) :: ind(2) !< 2D index in matrix, relative to \cr_id
214 petscscalar, intent(in) :: block(:,:) !< n_mod_X x n_mod_X block
215 petscscalar, intent(inout) :: block_loc(:,:) !< adapted block
216
217 ! local variables
218 petscint :: k, m ! counters
219 petscint :: k_loc, m_loc ! local k and m
220
221 block_loc = 0._dp
222 do m = 1,n_mod_x
223 do k = 1,n_mod_x
224 k_loc = k + nm_x(r_id+1,k) - &
225 &nm_x(min(r_id+1+ind(1),size(nm_x,1)),k)
226 m_loc = m + nm_x(r_id+1,m) - &
227 &nm_x(min(r_id+1+ind(2),size(nm_x,1)),m)
228 if (k_loc.ge.1 .and. m_loc.ge.1 .and. &
229 &k_loc.le.n_mod_x .and. m_loc.le.n_mod_x) &
230 block_loc(k_loc,m_loc) = block(k,m)
231 end do
232 end do
233
234#if ldebug
235 if (debug_insert_block_mat) then
236 call writo('following local block is going to be added by &
237 &rank '//trim(i2str(rank))//':',persistent=.true.)
238 call writo('Re =',persistent=.true.)
239 call print_ar_2(rp(block_loc))
240 call writo('Im =',persistent=.true.)
241 call print_ar_2(ip(block_loc))
242 if (overwrite_loc) then
243 call writo('(with operation INSERT_VALUES)',&
244 &persistent=.true.)
245 else
246 call writo('(with operation ADD_VALUES)',&
247 &persistent=.true.)
248 end if
249 endif
250#endif
251 end subroutine setup_local_block
252 end function insert_block_mat
253end module slepc_utilities
subroutine setup_local_block(nm_x, r_id, ind, block, block_loc)
/private Set up local block, possibly translated for fast PB3D.
Numerical utilities related to input.
subroutine, public pause_prog(ind)
Pauses the running of the program.
Numerical utilities related to giving output.
Definition messages.f90:4
subroutine, public lvl_ud(inc)
Increases/decreases lvl of output.
Definition messages.f90:254
subroutine, public print_ar_2(arr)
Print an array of dimension 2 on the screen.
Definition messages.f90:475
subroutine, public writo(input_str, persistent, error, warning, alert)
Write output to file identified by output_i.
Definition messages.f90:275
Numerical variables used by most other modules.
Definition num_vars.f90:4
integer, parameter, public dp
double precision
Definition num_vars.f90:46
complex(dp), parameter, public iu
complex unit
Definition num_vars.f90:85
integer, parameter, public max_str_ln
maximum length of strings
Definition num_vars.f90:50
integer, public rank
MPI rank.
Definition num_vars.f90:68
logical, public use_pol_flux_f
whether poloidal flux is used in F coords.
Definition num_vars.f90:114
Operations concerning giving output, on the screen as well as in output files.
Definition output_ops.f90:5
Numerical utilities related to SLEPC (and PETSC) operations.
logical, public debug_insert_block_mat
plot debug information for insert_block_mat()
integer function, public insert_block_mat(mds, block, mat, r_id, ind, n_r, transp, overwrite, ind_insert)
Insert a block pertaining to 1 normal point into a matrix.
Operations on strings.
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
Variables pertaining to the perturbation quantities.
Definition X_vars.f90:4
integer, public n_mod_x
size of m_X (pol. flux) or n_X (tor. flux)
Definition X_vars.f90:129
mode number type
Definition X_vars.f90:36