65 integer function calc_xuq_arr(mds_X,mds_sol,grid_eq,grid_X,grid_sol,eq_1,&
66 &eq_2,X,sol,X_id,XUQ_style,time,XUQ,deriv)
result(ierr)
76 character(*),
parameter :: rout_name =
'calc_XUQ_arr'
86 type(
x_1_type),
intent(in),
target :: x
88 integer,
intent(in) :: x_id
89 integer,
intent(in) :: xuq_style
90 real(
dp),
intent(in) :: time(:)
91 complex(dp),
intent(inout) :: xuq(:,:,:,:)
92 logical,
intent(in),
optional :: deriv
101 integer :: n_loc, m_loc
102 integer :: id, jd, kd
103 integer :: xuq_dims(4)
104 integer :: kdl_x(2), kdl_sol(2)
105 integer :: id_lim_x(2), id_lim_sol(2)
106 integer,
pointer :: sec_x_loc(:,:), sec_sol_loc(:,:)
107 real(
dp),
allocatable :: expon(:,:,:)
108 real(
dp),
allocatable :: par_fac(:)
109 real(
dp),
allocatable :: jq(:)
110 real(
dp),
allocatable :: s(:,:,:), inv_j(:,:,:)
111 real(
dp),
pointer :: r_x_loc(:), r_sol_loc(:)
112 real(
dp),
pointer :: theta_f(:,:,:), zeta_f(:,:,:)
113 complex(dp) :: sqrt_sol_val_norm
114 complex(dp),
allocatable :: fac_0(:,:,:), fac_1(:,:,:)
115 complex(dp),
allocatable :: xuq_loc(:,:)
116 complex(dp),
allocatable :: sol_vec(:,:)
117 complex(dp),
allocatable :: sol_vec_tot(:,:,:)
118 complex(dp),
allocatable :: dsol_vec(:,:)
119 complex(dp),
pointer :: u0(:,:,:), u1(:,:,:)
120 logical :: extrap = .true.
122 character(len=max_str_ln) :: err_msg
125 real(
dp),
allocatable :: sol_vec_alt(:)
133 xuq_dims = shape(xuq)
137 if (
present(deriv)) deriv_loc = deriv
140 if (grid_eq%n(1).ne.grid_x%n(1) .or. grid_eq%n(2).ne.grid_x%n(2))
then
142 err_msg =
'Grids need to be compatible'
145 if (grid_eq%n(1).ne.xuq_dims(1) .or. grid_eq%n(2).ne.xuq_dims(2) .or. &
146 &grid_sol%loc_n_r.ne.xuq_dims(3) .or. n_t.ne.xuq_dims(4))
then
148 err_msg =
'XUQ needs to have the correct dimensions'
156 sec_x_loc =>
mds_x%sec(id_lim_x(1):id_lim_x(2),:)
157 sec_sol_loc =>
mds_sol%sec(id_lim_sol(1):id_lim_sol(2),:)
159 n_mod_tot =
size(sec_x_loc,1)
161 if (
size(sec_x_loc,1).ne.
size(sec_sol_loc,1))
then
163 err_msg =
'modes X and sol have inconsistent sizes'
168 sqrt_sol_val_norm = sqrt(sol%val(x_id))
169 if (ip(sqrt_sol_val_norm).gt.0) sqrt_sol_val_norm = - sqrt_sol_val_norm
170 sqrt_sol_val_norm = sqrt_sol_val_norm / abs(sqrt_sol_val_norm)
173 allocate(jq(xuq_dims(3)))
174 allocate(s(xuq_dims(1),xuq_dims(2),xuq_dims(3)))
175 if ((xuq_style.eq.3 .or. xuq_style.eq.4)) &
176 &
allocate(inv_j(xuq_dims(1),xuq_dims(2),xuq_dims(3)))
177 allocate(xuq_loc(xuq_dims(1),xuq_dims(2)))
178 allocate(dsol_vec(sol%n_mod,xuq_dims(3)))
182 ierr =
spline(grid_eq%loc_r_F,eq_1%q_saf_FD(:,0),&
186 ierr =
spline(grid_eq%loc_r_F,eq_1%rot_t_FD(:,0),&
190 do jd = 1,xuq_dims(2)
191 do id = 1,xuq_dims(1)
192 ierr =
spline(grid_eq%loc_r_F,eq_2%S(id,jd,:),&
195 if ((xuq_style.eq.3 .or. xuq_style.eq.4))
then
196 ierr =
spline(grid_eq%loc_r_F,&
197 &1._dp/eq_2%jac_FD(id,jd,:,0,0,0),grid_sol%loc_r_F,&
211 if (xuq_style.eq.2 .or. xuq_style.eq.4)
then
213 allocate(sol_vec_tot(n_mod_tot,grid_sol%loc_n_r,0:1))
221 sol_vec_tot(:,:,id) = sol_vec
227 call writo(
'For mode '//trim(
i2str(
m))//
', testing &
228 &whether Dsol_vec is correct by comparing its integral &
229 &with original sol_vec')
230 kdl_sol = sec_sol_loc(
m,2:3)
231 allocate(sol_vec_alt(1:kdl_sol(2)-kdl_sol(1)+1))
233 ierr =
calc_int(rp(sol_vec_tot(
m,kdl_sol(1):kdl_sol(2),1)),&
234 &grid_sol%loc_r_F(kdl_sol(1):kdl_sol(2)),sol_vec_alt)
237 &[rp(sol_vec_tot(
m,kdl_sol(1):kdl_sol(2),0)),&
238 &sol_vec_alt],[kdl_sol(2)-kdl_sol(1)+1,2]),x=reshape(&
239 &grid_sol%loc_r_F(kdl_sol(1):kdl_sol(2)),&
241 ierr =
calc_int(ip(sol_vec_tot(
m,kdl_sol(1):kdl_sol(2),1)),&
242 &grid_sol%loc_r_F(kdl_sol(1):kdl_sol(2)),sol_vec_alt)
245 &[ip(sol_vec_tot(
m,kdl_sol(1):kdl_sol(2),0)),&
246 &sol_vec_alt],[kdl_sol(2)-kdl_sol(1)+1,2]),x=reshape(&
247 &grid_sol%loc_r_F(kdl_sol(1):kdl_sol(2)),&
249 deallocate(sol_vec_alt)
260 deallocate(sol_vec,sol_vec_tot)
268 allocate(theta_f(xuq_dims(1),xuq_dims(2),xuq_dims(3)))
269 allocate(zeta_f(xuq_dims(1),xuq_dims(2),xuq_dims(3)))
270 do jd = 1,xuq_dims(2)
271 do id = 1,xuq_dims(1)
272 ierr =
spline(grid_eq%loc_r_F,grid_eq%theta_F(id,jd,:),&
273 &grid_sol%loc_r_F,theta_f(id,jd,:))
275 ierr =
spline(grid_eq%loc_r_F,grid_eq%zeta_F(id,jd,:),&
276 &grid_sol%loc_r_F,zeta_f(id,jd,:))
281 theta_f => grid_x%theta_F
282 zeta_f => grid_x%zeta_F
288 if (sec_x_loc(
m,1).ne.sec_sol_loc(
m,1))
then
290 err_msg =
'For mode '//trim(
i2str(
m))//&
291 &
', no consistency for modes in grid_X and grid_sol'
296 kdl_x = sec_x_loc(
m,2:3)
297 kdl_sol = sec_sol_loc(
m,2:3)
300 kdl_x(1) = max(kdl_x(1),grid_x%i_min)
301 kdl_x(2) = min(kdl_x(2),grid_x%i_max)
302 kdl_sol(1) = max(kdl_sol(1),grid_sol%i_min)
303 kdl_sol(2) = min(kdl_sol(2),grid_sol%i_max)
306 kdl_x = kdl_x - grid_x%i_min + 1
307 kdl_sol = kdl_sol - grid_sol%i_min + 1
310 if (kdl_x(1).gt.kdl_x(2) .or. kdl_sol(1).gt.kdl_sol(2)) cycle
313 r_x_loc => grid_x%loc_r_F(kdl_x(1):kdl_x(2))
314 r_sol_loc => grid_sol%loc_r_F(kdl_sol(1):kdl_sol(2))
317 ind_x = sec_x_loc(
m,4)
318 ind_sol = sec_sol_loc(
m,4)
333 allocate(expon(xuq_dims(1),xuq_dims(2),kdl_sol(1):kdl_sol(2)))
334 allocate(fac_0(xuq_dims(1),xuq_dims(2),kdl_sol(1):kdl_sol(2)))
335 allocate(fac_1(xuq_dims(1),xuq_dims(2),kdl_sol(1):kdl_sol(2)))
336 allocate(par_fac(kdl_sol(1):kdl_sol(2)))
339 do kd = kdl_sol(1),kdl_sol(2)
341 kd_tot = kd + grid_sol%i_min - 1
342 n_loc =
mds_sol%n(kd_tot,ind_sol)
343 m_loc =
mds_sol%m(kd_tot,ind_sol)
348 err_msg =
'mode numbers not consistent'
354 par_fac(kd) = n_loc*jq(kd) - m_loc
356 par_fac(kd) = n_loc - m_loc*jq(kd)
358 expon(:,:,kd) = n_loc*zeta_f(:,:,kd) - &
359 &m_loc*theta_f(:,:,kd)
363 select case (xuq_style)
366 do kd = kdl_sol(1),kdl_sol(2)
367 fac_0(:,:,kd) =
iu*par_fac(kd)
377 allocate(u0(xuq_dims(1),xuq_dims(2),&
378 &kdl_sol(1):kdl_sol(2)))
379 allocate(u1(xuq_dims(1),xuq_dims(2),&
380 &kdl_sol(1):kdl_sol(2)))
383 &x%DU_0(:,:,kdl_x(1):kdl_x(2),ind_x),u0,&
384 &r_x_loc,r_sol_loc,extrap)
387 &x%DU_1(:,:,kdl_x(1):kdl_x(2),ind_x),u1,&
388 &r_x_loc,r_sol_loc,extrap)
392 &x%U_0(:,:,kdl_x(1):kdl_x(2),ind_x),u0,&
393 &r_x_loc,r_sol_loc,extrap)
396 &x%U_1(:,:,kdl_x(1):kdl_x(2),ind_x),u1,&
397 &r_x_loc,r_sol_loc,extrap)
402 u0 => x%DU_0(:,:,kdl_x(1):kdl_x(2),ind_x)
403 u1 => x%DU_1(:,:,kdl_x(1):kdl_x(2),ind_x)
405 u0 => x%U_0(:,:,kdl_x(1):kdl_x(2),ind_x)
406 u1 => x%U_1(:,:,kdl_x(1):kdl_x(2),ind_x)
424 err_msg =
'For XUQ_style = '//trim(
i2str(xuq_style))//&
425 &
' calculation of parallel derivative not supported'
428 do kd = kdl_sol(1),kdl_sol(2)
429 fac_0(:,:,kd) =
iu*par_fac(kd)*inv_j(:,:,kd)
435 err_msg =
'For XUQ_style = '//trim(
i2str(xuq_style))//&
436 &
' calculation of parallel derivative not supported'
440 allocate(u0(xuq_dims(1),xuq_dims(2),&
441 &kdl_sol(1):kdl_sol(2)))
442 allocate(u1(xuq_dims(1),xuq_dims(2),&
443 &kdl_sol(1):kdl_sol(2)))
449 &x%DU_0(:,:,kdl_x(1):kdl_x(2),ind_x),u0,&
450 &r_x_loc,r_sol_loc,extrap)
453 &x%DU_1(:,:,kdl_x(1):kdl_x(2),ind_x),u1,&
454 &r_x_loc,r_sol_loc,extrap)
462 u0 => x%DU_0(:,:,kdl_x(1):kdl_x(2),ind_x)
463 u1 => x%DU_1(:,:,kdl_x(1):kdl_x(2),ind_x)
468 fac_0 = u0*inv_j(:,:,kdl_sol(1):kdl_sol(2)) - &
469 &s(:,:,kdl_sol(1):kdl_sol(2))
470 fac_1 = u1*inv_j(:,:,kdl_sol(1):kdl_sol(2))
480 err_msg =
'No XUQ style associated with '//&
481 &trim(
i2str(xuq_style))
487 do kd = kdl_sol(1),kdl_sol(2)
489 xuq_loc = exp(
iu*expon(:,:,kd)) * &
490 &(sol%vec(ind_sol,kd,x_id)*fac_0(:,:,kd) + &
491 &dsol_vec(ind_sol,kd)*fac_1(:,:,kd))
496 xuq(:,:,kd,id) = xuq(:,:,kd,id) + xuq_loc * &
497 &exp(
iu*sqrt_sol_val_norm*time(id)*2*
pi)
502 deallocate(fac_0,fac_1,expon,par_fac)
508 deallocate(theta_f,zeta_f)
512 nullify(r_x_loc,r_sol_loc)
513 nullify(theta_f,zeta_f)
515 nullify(sec_x_loc,sec_sol_loc)