2D Fourier base in the two angular directions: (poloidal,toroidal) ~ (m,n) ~ (theta,zeta) [0,2pi]x[0,2pi/nfp]
explicit real fourier basis: sin(x_mn) or cos(x_mn) with x_mn=(mtheta - nnfp*zeta) , with mode numbers m and n
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| character(len=8), | public | :: | sin_cos_map(3) | = | (/"_sin_ ", "_cos_ ", "_sincos_"/) | ||
| logical, | private | :: | test_called | = | .FALSE. |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| integer, | public | :: | mn_max(2) |
input parameter: maximum number of fourier modes: m_max=mn_max(1),n_max=mn_max(2) |
|||
| integer, | public | :: | mn_nyq(2) |
number of equidistant integration points (trapezoidal rule) in m and n |
|||
| integer, | public | :: | mn_IP |
=mn_nyq(1)*mn_nyq(2) |
|||
| integer, | public | :: | nfp |
number of field periods (toroidal repetition after 2pi/nfp) |
|||
| integer, | public | :: | sin_cos |
can be either only sine: SIN or only cosine COS or full: SINCOS |
|||
| logical, | public | :: | exclude_mn_zero |
=true: exclude m=n=0 mode in the basis (only important if cos is in basis) |
|||
| integer, | public | :: | modes |
total(global) number of modes in basis (depends if only sin/cos or sin & cos are used) |
|||
| integer, | public | :: | modes_str |
local range of modes, when distributed over MPI subdomains |
|||
| integer, | public | :: | modes_end |
local range of modes, when distributed over MPI subdomains |
|||
| integer, | public, | ALLOCATABLE | :: | offset_modes(:) |
allocated (0:nRanks), gives range on each rank: modes_str:modes_end=offset_modes(myRank)+1:offset_modes(myRank+1) |
||
| integer, | public, | ALLOCATABLE | :: | whichRank(:) |
know the MPI rank for each mode |
||
| logical, | public | :: | initialized | = | .FALSE. |
set to true in init, set to false in free |
|
| integer, | public | :: | sin_range(2) |
sin_range(1)+1:sin_range(2) is range with sine bases |
|||
| integer, | public | :: | cos_range(2) |
sin_range(1)+1:sin_range(2) is range with cosine bases |
|||
| integer, | public | :: | mn_zero_mode |
points to m=0,n=0 mode in mode array (1:mn_modes) (only one can exist for cosine, else =-1) |
|||
| real(kind=wp), | public | :: | d_thet |
integration weight in theta direction: =2pi/mn_nyq(1) |
|||
| real(kind=wp), | public | :: | d_zeta |
integration weight in zeta direction : =nfp(2pi/nfp)/mn_nyq(2)=2pi/mn_nyq(2) |
|||
| integer, | public, | ALLOCATABLE | :: | Xmn(:,:) |
mode number (m,n*nfp) for each iMode=1,modes, size(2,modes) |
||
| integer, | public, | ALLOCATABLE | :: | zero_odd_even(:) |
=0 for m=n=0 mode, =1 for m= odd mode, =2 for m=even mode size(modes) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | x_IP(:,:) |
(theta,zeta)position of interpolation points theta [0,2pi]x[0,2pi/nfp]size(2,mn_IP) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | thet_IP(:) |
1d theta position of interpolation points theta [0,2pi] size(mn_nyq(1)) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | zeta_IP(:) |
1d zeta position of interpolation points theta [0,2pi/nfp] size(mn_nyq(2)) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | base_IP(:,:) |
basis functions, size(1:mn_IP,1:modes) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | base_dthet_IP(:,:) |
dthet derivative of basis functions, (1:mn_IP,1:modes) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | base_dzeta_IP(:,:) |
dzeta derivative of basis functions, (1:mn_IP,1:modes) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | snorm_base(:) |
1/norm of each basis function, size(1:modes), norm=int_0^2pi int_0^pi (base_mn(thet,zeta))^2 dthet dzeta |
||
| integer, | public | :: | mTotal1D |
mTotal1D =mn_max(1)+1 for sin or cos base, and mTotal=2*(mn_max(1)+1) for sin&cos base |
|||
| real(kind=wp), | public, | ALLOCATABLE | :: | base1D_IPthet(:,:,:) |
1D basis, size(1:mn_nyq(1),1:2,1:mTotal1D), if sin(m t-n z): sin(m t), -cos(m t) and if cos(m t-n z): cos(m t),sin(m t) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | base1D_dthet_IPthet(:,:,:) |
derivative of 1D basis, size(1:mn_nyq(1),1:2,1:mTotal1D) if sin(m t-n z): m cos(m t),m sin(m t) and if cos(m t-n z): -m sin(m t),m cos(m t) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | base1D_IPzeta(:,:,:) |
1D basis functions, size(1:2,-mn_max(2):mn_max(2),1:mn_nyq(2)) for sin/cos(m t-n z): cos(n z),sin(n z) |
||
| real(kind=wp), | public, | ALLOCATABLE | :: | base1D_dzeta_IPzeta(:,:,:) |
derivative of 1D basis functions, size(1:2,-mn_max(2):mn_max(2),1:mn_nyq(2)) for sin/cos(m t-n z): -n sin(n z),n cos(n z) |
| procedure, public :: init => fBase_init | |
| procedure, public :: free => fBase_free | |
| procedure, public :: copy => fBase_copy | |
| procedure, public :: compare => fBase_compare | |
| procedure, public :: change_base => fBase_change_base | |
| procedure, public :: eval => fBase_eval | |
| procedure, public :: eval_xn => fBase_eval_xn | |
| procedure, public :: evalDOF_x => fBase_evalDOF_x | |
| procedure, public :: evalDOF_xn => fBase_evalDOF_xn | |
| procedure, public :: evalDOF_xn_tens => fBase_evalDOF_xn_tens | |
| procedure, public :: evalDOF_IP => fBase_evalDOF_IP_tens | |
| procedure, public :: projectIPtoDOF => fBase_projectIPtoDOF_tens | |
| procedure, public :: projectxntoDOF => fBase_projectxntoDOF | |
| procedure, public :: initDOF => fBase_initDOF |
evaluate all modes at specific given point in theta and zeta
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| real(kind=wp), | intent(in) | :: | x(2) |
theta,zeta point position |
evaluate all modes at a list of given points in theta and zeta
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| integer, | intent(in) | :: | np |
number of points in xn |
||
| real(kind=wp), | intent(in) | :: | xn(2,1:np) |
theta,zeta point positions |
evaluate special 1D base in theta direction (cos(mt_i),sin(mt_i)) or its derivative(s) on a given set of points for tensor-product evaluation of 2D sin and cos base: sin(mthet-nzeta) = sin(mthet)cos(nzeta)-cos(mthet)sin(nzeta) == dot_product( (sin(mthet),-cos(mthet)) , (cos(nzeta),sin(nzeta))) cos(mthet-nzeta) = cos(mthet)cos(nzeta)+sin(mthet)sin(nzeta) == dot_product( (cos(mthet), sin(mthet)) , (cos(nzeta),sin(nzeta))) so for the 1D base, mTotal1d depends on using sin/cos/sin+cos base.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| integer, | intent(in) | :: | deriv |
=0: base, =1: dthet , =2: dthet^2 |
||
| integer, | intent(in) | :: | nthet |
number of points in theta |
||
| real(kind=wp), | intent(in) | :: | thet(1:nthet) |
theta 1D point positions |
evaluate special 1D base in zeta direction (cos(mt_i),sin(mt_i)) or its derivative(s) on a given set of points for tensor-product evaluation of 2D sin and cos base: sin(mthet-nzeta) = sin(mthet)cos(nzeta)-cos(mthet)sin(nzeta) == dot_product( (sin(mthet),-cos(mthet)) , (cos(nzeta),sin(nzeta))) cos(mthet-nzeta) = cos(mthet)cos(nzeta)+sin(mthet)sin(nzeta) == dot_product( (cos(mthet), sin(mthet)) , (cos(nzeta),sin(nzeta))) so for the 1D base, nTotal1d is always 2*n_max+1
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| integer, | intent(in) | :: | deriv |
=0: base, =1: dzeta , =2: dzeta^2 |
||
| integer, | intent(in) | :: | nzeta |
number of points in zeta |
||
| real(kind=wp), | intent(in) | :: | zeta(1:nzeta) |
zeta 1D point positions |
evaluate all modes at a given interpolation point
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| real(kind=wp), | intent(in) | :: | x(2) |
input coordinate theta,zeta in [0,2pi]^2 |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| real(kind=wp), | intent(in) | :: | DOFs(:) |
array of all modes |
evaluate all modes at a list of interpolation points
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| integer, | intent(in) | :: | np |
number of points to be evaluated |
||
| real(kind=wp), | intent(in) | :: | xn(2,1:np) |
input coordinate theta,zeta in [0,2pi]^2 |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| real(kind=wp), | intent(in) | :: | DOFs(:) |
array of all modes |
evaluate all modes on a tensor-produc grid (t_i,z_j), making use of the tensor product in the fourier series: y_ij = DOFs_mn * SIN(mt_i - nz_j ) => SIN(mt_i) DOFs_mn COS(nz_j) -COS(mt_i) DOFs_mn SIN(nz_j) y_ij = DOFs_mn * COS(mt_i - nz_j ) => COS(mt_i) DOFs_mn COS(nz_j) +SIN(mt_i) DOFs_mn SIN(nz_j) => a1_im DOFs_mn b1_nj + a2_im DOFs_mn b2_nj can be written as 2 SPECIAL MATMAT operations: c(i,1,n)=a1(i,m) DOFs(m,n) , c(i,2,n) = a2(i,m) DOFs(m,n) => c(i,d,n) = DOT_PROD(a(i,d,1:mmax),DOFs(1:mmax,n)) y(i,j) = c(i,1,n) b1(n,j) + c(i,2,n) b2(n,j) = DOT_PROD(c(i,1:2,1:nmax),b(1:2,1:nmax,j) the 1D ordering in y does not neead a reshape, y(i,j) => y(1:mn_IP), 1D array data can be kept, as it is passed (with its start adress) to DGEMM.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| integer, | intent(in) | :: | nthet |
number of points in theta |
||
| integer, | intent(in) | :: | nzeta |
number of points in zeta |
||
| real(kind=wp), | intent(in) | :: | thet(1:nthet) |
theta positions |
||
| real(kind=wp), | intent(in) | :: | zeta(1:nzeta) |
zeta positions |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| real(kind=wp), | intent(in) | :: | DOFs(:) |
array of all modes |
DOFS evaluated on tensor-product grid,
evaluate all modes at all interpolation points
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| real(kind=wp), | intent(in) | :: | DOFs(:) |
array of all modes |
evaluate all modes at all interpolation points, making use of the tensor product: y_ij = DOFs_mn * SIN(mt_i - nz_j ) => SIN(mt_i) DOFs_mn COS(nz_j) -COS(mt_i) DOFs_mn SIN(nz_j) y_ij = DOFs_mn * COS(mt_i - nz_j ) => COS(mt_i) DOFs_mn COS(nz_j) +SIN(mt_i) DOFs_mn SIN(nz_j) => a1_im DOFs_mn b1_nj + a2_im DOFs_mn b2_nj can be written as 2 SPECIAL MATMAT operations: c(i,1,n)=a1(i,m) DOFs(m,n) , c(i,2,n) = a2(i,m) DOFs(m,n) => c(i,d,n) = DOT_PROD(a(i,d,1:mmax),DOFs(1:mmax,n)) y(i,j) = c(i,1,n) b1(n,j) + c(i,2,n) b2(n,j) = DOT_PROD(c(i,1:2,1:nmax),b(1:2,1:nmax,j) the 1D ordering in y does not neead a reshape, y(i,j) => y(1:mn_IP), 1D array data can be kept, as it is passed (with its start adress) to DGEMM.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| real(kind=wp), | intent(in) | :: | DOFs(:) |
array of all modes (sf%modes) |
take values interpolated at sf%s_IP positions and project onto fourier basis by integration
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| real(kind=wp), | intent(in) | :: | g_IP(:) |
interpolation values at theta_IP zeta_IP positions |
||
| real(kind=wp), | intent(in), | optional | :: | thet_zeta_start(2) |
projection to fourier base
allocate the type fBase
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(t_fBase), | intent(inout), | ALLOCATABLE | :: | sf |
self |
|
| integer, | intent(in) | :: | mn_max_in(2) |
maximum mode in m and n |
||
| integer, | intent(in) | :: | mn_nyq_in(2) |
number of integration points |
||
| integer, | intent(in) | :: | nfp_in |
number of field periods |
||
| character(len=8), | intent(in) | :: | sin_cos_in |
can be either only sine: " sin" only cosine: " cos" or full: "sin_cos" |
||
| logical, | intent(in) | :: | exclude_mn_zero_in |
=true: exclude m=n=0 mode in the basis (only important if cos is in basis) |
initialize the type fBase maximum mode numbers, number of integration points, type of basis (sin/cos or sin and cos)
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(inout) | :: | sf |
self |
||
| integer, | intent(in) | :: | mn_max_in(2) |
maximum mode in m and n |
||
| integer, | intent(in) | :: | mn_nyq_in(2) |
number of integration points |
||
| integer, | intent(in) | :: | nfp_in |
number of field periods |
||
| character(len=8), | intent(in) | :: | sin_cos_in |
can be either only sine: " sin" only cosine: " cos" or full: "sin_cos" |
||
| logical, | intent(in) | :: | exclude_mn_zero_in |
=true: exclude m=n=0 mode in the basis (only important if cos is in basis) |
allocate all variables in fBase
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(inout) | :: | sf |
self |
finalize the type fBase
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(inout) | :: | sf |
self |
change data from oldBase to self. Forier modes are directly copied so, if new mode space is smaller, its like a Fourier cut-off. if new modes do not match old ones, they are set to zero. Note that a change of nfp is not possible· as well as a change from sine to cosine
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| class(t_fBase), | intent(in) | :: | old_fBase |
base of old_data |
||
| integer, | intent(in) | :: | iterDim |
iterate on first or second dimension or old_data/sf_data |
||
| real(kind=wp), | intent(in) | :: | old_data(:,:) | |||
| real(kind=wp), | intent(out) | :: | sf_data(:,:) |
project from interpolation points to all modes DOFs = addDOFs+ fac MATMUL(base_IP_DOF,y_IP)
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| logical, | intent(in) | :: | add |
=F initialize DOFs , =T add to DOFs |
||
| real(kind=wp), | intent(in) | :: | factor |
scale result by factor, before adding to DOFs (should be =1.0_wp if not needed) |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| real(kind=wp), | intent(in) | :: | y_IP(:) | |||
| real(kind=wp), | intent(inout) | :: | DOFs(1:sf%modes) |
array of all modes |
project from any 2D set of interpolation points, at tensor-product of (theta,zeta) positions given by "xn", to all modes DOFs = addDOFs+ fac MATMUL(base_xn,yn)
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| logical, | intent(in) | :: | add |
=F initialize DOFs , =T add to DOFs |
||
| real(kind=wp), | intent(in) | :: | factor |
scale result by factor, before adding to DOFs (should be =1.0_wp if not needed) |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| integer, | intent(in) | :: | np |
total number of 2D interpolation points |
||
| real(kind=wp), | intent(in) | :: | xn(2,1:np) |
(theta=1,zeta=2) position of tensor-product interpolation points, [0,2pi]x[0,2pi/nfp],size(2,mn_IP) |
||
| real(kind=wp), | intent(in) | :: | yn(1:np) |
value at interpolation points |
||
| real(kind=wp), | intent(inout) | :: | DOFs(1:sf%modes) |
array of all modes |
inverse of fBase_evalDOF_IP_tens
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(in) | :: | sf |
self |
||
| logical, | intent(in) | :: | add |
=F initialize DOFs , =T add to DOFs |
||
| real(kind=wp), | intent(in) | :: | factor |
scale result by factor, before adding to DOFs (should be =1.0_wp if not needed) |
||
| integer, | intent(in) | :: | deriv |
=0: base, =2: dthet , =3: dzeta |
||
| real(kind=wp), | intent(in) | :: | y_IP(:) |
point values (at sf%x_IP if x_IP_in not given) |
||
| real(kind=wp), | intent(inout) | :: | DOFs(1:sf%modes) |
array of all modes |
test fBase variable
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(t_fBase), | intent(inout) | :: | sf |
self |