on one flux surface, find for an given list of (thet_j,zeta_j), the corresponding (thet_j,zeta_j) positions, given Here, new boozer angles are theta=theta+Gt(theta,zeta) zeta=zeta+nu(theta,zeta), with Gt=lambda+iotanu and nu periodic functions and zero average and same base Note that in this routine, we will use a 2d root search with a newton method, setting [f1,f2]^T = [thet+A(thet,zeta)-thet=0, zeta+B(thet,zeta)-zeta*=0]^T that includes the derivatives (Jacobian), so that the newton step needs to the solved: -[f1] [ 1+dA/dthet dA/dzeta] [dthet] | | = | | | | -[f2] [ dB/dthet 1+dB/dzeta] [dzeta]
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nrho |
number of surfaces, (second dimension of LA_in and nu_in modes) |
||
| real(kind=wp), | intent(in) | :: | iota(nrho) |
iota at the rho positions. |
||
| type(t_fBase), | intent(in) | :: | fbase_in | |||
| real(kind=wp), | intent(in) | :: | LA_in(1:fbase_in%modes,nrho) | |||
| real(kind=wp), | intent(in) | :: | nu_in(1:fbase_in%modes,nrho) | |||
| integer, | intent(in) | :: | tz_dim | |||
| real(kind=wp), | intent(in) | :: | tz_boozer(2,tz_dim) | |||
| real(kind=wp), | intent(out) | :: | thetzeta_out(2,tz_dim,nrho) |
theta,zeta position in original angles, for given boozer angles |
SUBROUTINE find_boozer_angles(nrho,iota,fbase_in,LA_in,nu_in,tz_dim,tz_boozer,thetzeta_out) ! MODULES USE MODgvec_Globals,ONLY: UNIT_stdOut,PI,ProgressBar,testlevel USE MODgvec_fbase ,ONLY: t_fbase IMPLICIT NONE !----------------------------------------------------------------------------------------------------------------------------------- ! INPUT VARIABLES INTEGER ,INTENT(IN) :: nrho !! number of surfaces, (second dimension of LA_in and nu_in modes) REAL(wp) ,INTENT(IN) :: iota(nrho) !! iota at the rho positions. TYPE(t_fbase),INTENT(IN) ::fbase_in !< same basis of lambda and nu REAL(wp) ,INTENT(IN) :: LA_in(1:fbase_in%modes,nrho) !< fourier coefficients of thet*=thet+LA(theta,zeta)+iota*nu(theta,zeta) REAL(wp) ,INTENT(IN) :: nu_in(1:fbase_in%modes,nrho) !< coefficients of zeta*=zeta+nu(theta,zeta) INTEGER ,INTENT(IN) :: tz_dim !< size of the list of in thetstar,zetastar REAL(wp) ,INTENT(IN) :: tz_boozer(2,tz_dim) !< theta,zeta positions in boozer angle (same for all rho) !----------------------------------------------------------------------------------------------------------------------------------- ! OUTPUT VARIABLES REAL(wp) ,INTENT(OUT) :: thetzeta_out(2,tz_dim,nrho) !! theta,zeta position in original angles, for given boozer angles !----------------------------------------------------------------------------------------------------------------------------------- ! LOCAL VARIABLES INTEGER :: irho,j REAL(wp) :: bounds(2),x0(2) REAL(wp) :: check(tz_dim),maxerr(2,nrho) REAL(wp) :: Gt(1:fbase_in%modes) !! transform in theta: lambda + iota*nu LOGICAL :: docheck !=================================================================================================================================== __PERFON('find_boozer_angles') SWRITE(UNIT_StdOut,'(A,2(I8,A))')'Find boozer angles via 2D Newton on nrho=',nrho,' times ntheta_zeta= ',tz_dim, " points" docheck=(testlevel.GT.0) bounds=(/PI, PI/fbase_in%nfp/) CALL ProgressBar(0,nrho)!init DO irho=1,nrho Gt(:)=LA_in(:,irho)+iota(irho)*nu_in(:,irho) !$OMP PARALLEL DO SCHEDULE(STATIC) DEFAULT(NONE) & !$OMP PRIVATE(j,x0) FIRSTPRIVATE(irho,bounds) & !$OMP SHARED(tz_dim,tz_boozer,thetzeta_out,fbase_in,Gt,nu_in) DO j=1,tz_dim x0=tz_boozer(:,j) thetzeta_out(:,j,irho)=get_booz_newton(x0,bounds,fbase_in,Gt,nu_in(:,irho)) END DO !j !$OMP END PARALLEL DO CALL ProgressBar(irho,nrho) END DO !irho IF(docheck)THEN DO irho=1,nrho check=fbase_in%evalDOF_xn(tz_dim,thetzeta_out(:,:,irho),0,(LA_in(:,irho)+iota(irho)*nu_in(:,irho))) maxerr(1,irho)=maxval(abs(check+(thetzeta_out(1,:,irho)-tz_boozer(1,:)))) check=fbase_in%evalDOF_xn(tz_dim,thetzeta_out(:,:,irho),0,nu_in(:,irho)) maxerr(2,irho)=maxval(abs(check+(thetzeta_out(2,:,irho)-tz_boozer(2,:)))) END DO IF(ANY(maxerr(:,:).GT.1.0e-12)) THEN WRITE(UNIT_stdout,*)'CHECK BOOZER THETA*',MAXVAL(maxerr(1,:)) WRITE(UNIT_stdout,*)'CHECK BOOZER ZETA*', maxerr CALL abort(__STAMP__, & "find_boozer_angles: Error in transform") END IF END IF !docheck SWRITE(UNIT_StdOut,'(A)') '...DONE.' __PERFOFF('find_boozer_angles') END SUBROUTINE find_boozer_angles