This is an issue to track work related to the case of an (I think) incorrectly initialized dnorm factor in fixaray.f.
The code changes happen on the branch fix_cosmui.
I found this problem when trying to understand the Fourier transform of the forces in VMEC.
The problem appears only when running VMEC with lasym=T.
Any (periodic) function can be decomposed into an even-parity contribution and an odd-parity contribution.
Some force components (armn, brmn, ..., clmn, frcon, fzcon) have even parity, some have odd parity when symmetry is assumed.
In the asymmetric case, the forces are decomposed into definite-parity contributions
and then Fourier-transformed over the poloidal half-interval [0, pi] (1, ..., ntheta2).
The decomposition into definite-parity contributions is done in symforce.
Those-parity contributions that would be the only ones in symmetric mode are Fourier-transformed by tomnsps.
The other-parity contributions are Fourier-transformed using tomnspa.
Concluding, the Fourier integrals computed to get the Fourier coefficients of the forces are only ever computed
over the poloidal half-interval [0, pi] and never over the full-poloidal interval [0, 2pi[ .
The Fourier integrals in tomnsp* make use of the Fourier basis functions
stored in cosmui, sinmui, cosmumi and sinmumi.
These are filled in Sources/Initialization_Cleanup/fixaray.f.
Here, the normalization of the Fourier integrals is being done using the dnorm factor.
Note that this enters also in the flux-surface average weighting factor wint through cosmui3.
dnorm gets changed to 1/(nzeta*ntheta3) if lasym=T.
In that case, ntheta3 equals ntheta1, which refers to the full poloidal interval [0, 2 pi[.
The Fourier integrals done in tomnsp* use this dnorm factor to normalize the discrete integrals there,
which however are still only being computed over half the poloidal range.
I think this is incorrect.
Instead, dnorm as used for cosmui, ..., sinmumi should always be 1/(nzeta*ntheta2-1) as in the symmetric case.
Furthermore, cosmui3 and in turn the weighting factors wint still need to adjust to the changed poloidal interval.
Thus, I propose to introduce dnorm3 in fixaray, which shall get adjusted to reflect the actual number of poloidal grid points.
The actual errors resulting from this mixup seems to be that in the asymmetric case,
the Fourier coefficients of the forces are too low by a factor of ntheta3/(ntheta2-1) which is approx. 2.
VMEC seems to be able to cope with that by just using more iterations,
but I think this should be fixed anyway.
The expected results of fixing this issue are:
- for originally symmetric cases, when switching to
lasym=T, the number of iterations should approximately stay constant
- for asymmetric cases, the number of iterations should go down
The SOLOVEV case from the DESC repository is used as a simple test case here:
&INDATA
! based on input.SOLOVEV from github.com/PlasmaControl/DESC/examples
LASYM = F
NFP = 1
MPOL = 16
NTOR = 0
NS_ARRAY = 16 256
NITER_ARRAY = 1000 20000
FTOL_ARRAY = 1E-16 1E-16
DELT = 9.00E-01
NSTEP = 250
GAMMA = 0.000000E+00
PHIEDGE = 1.00000000000000E+00
CURTOR = 0.00000000000000E+00
PMASS_TYPE = "power_series"
AM = 0.125 -0.125
NCURR = 0
AI = 1.0
RAXIS = 3.999
ZAXIS = 0.00000000000000E+00
RBC( 0,0) = 3.999 ZBS( 0,0) = 0.000
RBC( 0,1) = 1.026 ZBS( 0,1) = 1.580
RBC( 0,2) = -0.068 ZBS( 0,2) = 0.010
/
&END
Running this case with the current master branch, I get the following output:
NS = 16 NO. FOURIER MODES = 16 FTOLV = 1.000E-16 NITER = 1000
PROCESSOR COUNT - RADIAL: 1
ITER FSQR FSQZ FSQL RAX(v=0) DELT WMHD
1 9.56E-02 2.88E-03 3.25E-02 3.999E+00 9.00E-01 2.6381E+00
250 2.15E-15 6.16E-16 4.15E-16 3.990E+00 9.00E-01 2.5484E+00
272 8.89E-17 3.66E-17 2.15E-17 3.990E+00 9.00E-01 2.5484E+00
NS = 256 NO. FOURIER MODES = 16 FTOLV = 1.000E-16 NITER = 20000
PROCESSOR COUNT - RADIAL: 1
ITER FSQR FSQZ FSQL RAX(v=0) DELT WMHD
1 9.94E-04 1.52E-04 1.43E-07 3.990E+00 9.00E-01 2.5484E+00
250 2.37E-10 5.61E-11 6.49E-13 3.989E+00 5.93E-01 2.5484E+00
500 4.14E-12 2.00E-13 1.92E-15 3.989E+00 5.93E-01 2.5484E+00
750 9.16E-13 2.13E-14 3.32E-18 3.989E+00 5.93E-01 2.5484E+00
1000 1.81E-13 3.04E-15 3.45E-20 3.989E+00 5.93E-01 2.5484E+00
1250 1.66E-14 2.26E-16 3.81E-22 3.989E+00 5.93E-01 2.5484E+00
1500 8.72E-16 1.17E-17 1.30E-23 3.989E+00 5.93E-01 2.5484E+00
1698 1.00E-16 1.41E-18 4.74E-24 3.989E+00 5.93E-01 2.5484E+00
Then lasym=T is put in the input file and the output now reads:
NS = 16 NO. FOURIER MODES = 16 FTOLV = 1.000E-16 NITER = 1000
PROCESSOR COUNT - RADIAL: 1
ITER FSQR FSQZ FSQL RAX(v=0) ZAX(v=0) DELT WMHD
1 2.39E-02 7.20E-04 8.13E-03 3.999E+00 0.000E+00 9.00E-01 2.6381E+00
250 8.19E-12 3.05E-13 4.01E-13 3.990E+00 2.528E-16 9.00E-01 2.5484E+00
500 4.96E-16 6.97E-18 1.57E-18 3.990E+00 -5.771E-17 9.00E-01 2.5484E+00
533 9.77E-17 1.49E-18 1.68E-19 3.990E+00 -8.564E-16 9.00E-01 2.5484E+00
NS = 256 NO. FOURIER MODES = 16 FTOLV = 1.000E-16 NITER = 20000
PROCESSOR COUNT - RADIAL: 1
ITER FSQR FSQZ FSQL RAX(v=0) ZAX(v=0) DELT WMHD
1 2.59E-04 4.06E-05 4.06E-08 3.990E+00 -8.564E-16 9.00E-01 2.5484E+00
250 5.93E-12 9.04E-13 1.48E-14 3.989E+00 -2.752E-16 9.00E-01 2.5484E+00
500 8.62E-13 9.57E-14 3.46E-17 3.989E+00 -2.291E-15 9.00E-01 2.5484E+00
750 2.95E-13 2.13E-14 3.01E-19 3.989E+00 -1.379E-15 9.00E-01 2.5484E+00
1000 7.49E-14 2.57E-15 3.11E-20 3.989E+00 -1.565E-15 9.00E-01 2.5484E+00
1250 1.84E-14 3.96E-16 3.08E-21 3.989E+00 -1.876E-15 9.00E-01 2.5484E+00
1500 2.75E-15 4.85E-17 5.63E-22 3.989E+00 -4.524E-15 9.00E-01 2.5484E+00
1750 3.40E-16 6.61E-18 8.85E-23 3.989E+00 -3.454E-15 9.00E-01 2.5484E+00
1906 9.91E-17 2.29E-18 4.60E-23 3.989E+00 -1.048E-15 9.00E-01 2.5484E+00
The number of iterations has increased:
- for
ns=16 from 272 to 533
- for
ns=256 from 1698 to 1906
With the changes on this branch, the symmetric case runs in the same number of iterations
and the asymmetric case runs in 312 (for ns=16) and 1685 (for ns=256) iterations.
TODO:
This is an issue to track work related to the case of an (I think) incorrectly initialized
dnormfactor infixaray.f.The code changes happen on the branch
fix_cosmui.I found this problem when trying to understand the Fourier transform of the forces in VMEC.
The problem appears only when running VMEC with
lasym=T.Any (periodic) function can be decomposed into an even-parity contribution and an odd-parity contribution.
Some force components (armn, brmn, ..., clmn, frcon, fzcon) have even parity, some have odd parity when symmetry is assumed.
In the asymmetric case, the forces are decomposed into definite-parity contributions
and then Fourier-transformed over the poloidal half-interval [0, pi] (1, ..., ntheta2).
The decomposition into definite-parity contributions is done in
symforce.Those-parity contributions that would be the only ones in symmetric mode are Fourier-transformed by
tomnsps.The other-parity contributions are Fourier-transformed using
tomnspa.Concluding, the Fourier integrals computed to get the Fourier coefficients of the forces are only ever computed
over the poloidal half-interval [0, pi] and never over the full-poloidal interval [0, 2pi[ .
The Fourier integrals in
tomnsp*make use of the Fourier basis functionsstored in
cosmui,sinmui,cosmumiandsinmumi.These are filled in
Sources/Initialization_Cleanup/fixaray.f.Here, the normalization of the Fourier integrals is being done using the
dnormfactor.Note that this enters also in the flux-surface average weighting factor
wintthroughcosmui3.dnormgets changed to1/(nzeta*ntheta3)iflasym=T.In that case,
ntheta3equalsntheta1, which refers to the full poloidal interval [0, 2 pi[.The Fourier integrals done in
tomnsp*use thisdnormfactor to normalize the discrete integrals there,which however are still only being computed over half the poloidal range.
I think this is incorrect.
Instead,
dnormas used forcosmui, ...,sinmumishould always be1/(nzeta*ntheta2-1)as in the symmetric case.Furthermore,
cosmui3and in turn the weighting factorswintstill need to adjust to the changed poloidal interval.Thus, I propose to introduce
dnorm3infixaray, which shall get adjusted to reflect the actual number of poloidal grid points.The actual errors resulting from this mixup seems to be that in the asymmetric case,
the Fourier coefficients of the forces are too low by a factor of
ntheta3/(ntheta2-1)which is approx. 2.VMEC seems to be able to cope with that by just using more iterations,
but I think this should be fixed anyway.
The expected results of fixing this issue are:
lasym=T, the number of iterations should approximately stay constantThe
SOLOVEVcase from theDESCrepository is used as a simple test case here:Running this case with the current master branch, I get the following output:
Then
lasym=Tis put in the input file and the output now reads:The number of iterations has increased:
ns=16 from 272 to 533ns=256 from 1698 to 1906With the changes on this branch, the symmetric case runs in the same number of iterations
and the asymmetric case runs in 312 (for
ns=16) and 1685 (forns=256) iterations.TODO:
cosmui, ... are used and see if this has implications there