diff --git a/.gitignore b/.gitignore index ad1d2f6ee..fc1bbe77b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,11 @@ *~ *# - *.o *.mod *.a *.so *.zip +*.egg-info .DS* *.dSYM ._* @@ -69,3 +69,9 @@ PB3D .vscode/ LIBSTELL/.makefile.swp +pySTEL/build +pySTEL/dist + +*.sublime-project +*.sublime-workspace +fort.* diff --git a/BEAMS3D/BEAMS3D.dep b/BEAMS3D/BEAMS3D.dep index 8244f82e0..122413f3f 100644 --- a/BEAMS3D/BEAMS3D.dep +++ b/BEAMS3D/BEAMS3D.dep @@ -10,7 +10,7 @@ beams3d_beam_density.o: \ ../../LIBSTELL/$(LOCTYPE)/mpi_params.o beams3d_interface_mod.o: \ - beams3d_input_mod.o \ + ../../LIBSTELL/$(LOCTYPE)/beams3d_input_mod.o \ beams3d_runtime.o \ beams3d_grid.o \ beams3d_lines.o \ @@ -20,7 +20,7 @@ beams3d_interface_mod.o: \ beams3d_imas_module.o: \ beams3d_interface_mod.o \ - beams3d_input_mod.o + ../../LIBSTELL/$(LOCTYPE)/beams3d_input_mod.o beams3d_fix_poloidal.o: \ @@ -143,7 +143,7 @@ beams3d_init.o: \ ../../LIBSTELL/$(LOCTYPE)/adas_mod_parallel.o \ beams3d_runtime.o \ beams3d_grid.o \ - beams3d_input_mod.o \ + ../../LIBSTELL/$(LOCTYPE)/beams3d_input_mod.o \ beams3d_lines.o\ fidasim_input_mod.o \ @@ -260,16 +260,6 @@ beams3d_init_continuegrid.o: \ beams3d_grid.o -beams3d_input_mod.o: \ - ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o \ - ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ - ../../LIBSTELL/$(LOCTYPE)/mpi_params.o \ - ../../LIBSTELL/$(LOCTYPE)/mpi_inc.o \ - beams3d_runtime.o \ - beams3d_lines.o \ - beams3d_grid.o - - beams3d_lines.o: \ ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o diff --git a/BEAMS3D/ObjectList b/BEAMS3D/ObjectList index 0374cefc1..1dc183492 100644 --- a/BEAMS3D/ObjectList +++ b/BEAMS3D/ObjectList @@ -46,7 +46,6 @@ beams3d_grid.o \ backspace_out.o \ beams3d_follow_gc.o \ gauss_rand.o \ -beams3d_input_mod.o \ beams3d_init_beams.o \ fgc_rkh68.o \ fgc_lsode.o diff --git a/BEAMS3D/Sources/beams3d_grid.f90 b/BEAMS3D/Sources/beams3d_grid.f90 index 9f4c3abaa..683c62e79 100644 --- a/BEAMS3D/Sources/beams3d_grid.f90 +++ b/BEAMS3D/Sources/beams3d_grid.f90 @@ -11,6 +11,19 @@ MODULE beams3d_grid USE stel_kinds, ONLY: rprec USE EZspline_obj USE EZspline + USE beams3d_globals, ONLY: nr, nphi, nz, rmin, rmax, zmin, zmax, & + phimin, phimax, vc_adapt_tol, nte, & + nne, nti,nzeff, npot, plasma_mass, & + plasma_Zmean, therm_factor, & + B_kick_min, B_kick_max, freq_kick, & + E_kick, rho_fullorbit, rmin_fida, & + rmax_fida, zmin_fida, zmax_fida, & + phimin_fida, phimax_fida, nr_fida, & + nphi_fida, nz_fida, nenergy_fida, & + npitch_fida, & + t_fida, dexionT, dexionD,dexionHe3, & + s_max,s_max_te, s_max_ne,s_max_zeff,& + s_max_ti, s_max_pot !----------------------------------------------------------------------- ! Module Variables @@ -40,7 +53,6 @@ MODULE beams3d_grid ! plasma_Zmean [Z] = sum(n*Z*Z*mi/mj)/sum(n*Z) sum over j ion species (mi: plasma mass) !----------------------------------------------------------------------- IMPLICIT NONE - INTEGER :: nr, nphi, nz, nte, nne, nti, nzeff, npot, dexionT, dexionD, dexionHe3 INTEGER :: win_raxis, win_phiaxis, win_zaxis, win_B_R, win_B_PHI, win_B_Z,& win_MODB, win_TE, win_NE, win_TI, win_ZEFF_ARR,& win_S_ARR, win_U_ARR,win_X_ARR,win_Y_ARR, win_POT_ARR, win_BR4D, win_BPHI4D, & @@ -49,16 +61,12 @@ MODULE beams3d_grid win_wall_load, win_wall_shine, win_hr, win_hp, win_hz, & win_hri, win_hpi, win_hzi, win_NI5D, win_NI, & win_raxis_fida, win_phiaxis_fida, win_zaxis_fida, win_energy_fida, win_pitch_fida, & - win_beam_density, win_NEUTRONS, win_E_NEUTRONS, & - nr_fida, nphi_fida, nz_fida, nenergy_fida, npitch_fida - REAL(rprec) :: rmin, rmax, zmin, zmax, phimin, phimax, tmin, tmax, delta_t, & - vc_adapt_tol, psiedge_eq, phiedge_eq, plasma_Zmean, plasma_mass, & - reff_eq, therm_factor, B_kick_min, B_kick_max, & - E_kick, freq_kick, t_fida, rho_fullorbit, rho_help,& - s_max,s_max_te, s_max_ne,s_max_zeff,s_max_ti, s_max_pot + win_beam_density, win_NEUTRONS, win_E_NEUTRONS + REAL(rprec) :: emin_fida, pimin_fida + REAL(rprec) :: tmin, tmax, delta_t, psiedge_eq, phiedge_eq, & + reff_eq, rho_help REAL(rprec), POINTER :: raxis(:), zaxis(:), phiaxis(:) REAL(rprec), POINTER :: req_axis(:), zeq_axis(:), E_NEUTRONS(:) - REAL :: rmin_fida, rmax_fida, zmin_fida, zmax_fida, phimin_fida, phimax_fida, emin_fida, pimin_fida REAL(rprec), POINTER :: raxis_fida(:), zaxis_fida(:), phiaxis_fida(:), energy_fida(:), pitch_fida(:) REAL(rprec), POINTER :: wall_load(:,:), wall_shine(:,:) REAL(rprec), POINTER :: B_R(:,:,:),B_PHI(:,:,:), B_Z(:,:,:), MODB(:,:,:),& diff --git a/BEAMS3D/Sources/beams3d_lines.f90 b/BEAMS3D/Sources/beams3d_lines.f90 index ad9eff62d..dfb832326 100644 --- a/BEAMS3D/Sources/beams3d_lines.f90 +++ b/BEAMS3D/Sources/beams3d_lines.f90 @@ -10,6 +10,8 @@ MODULE beams3d_lines ! Libraries !----------------------------------------------------------------------- USE stel_kinds, ONLY: rprec + USE beams3d_globals, ONLY: nparticles, ns_prof1, ns_prof2, & + ns_prof3, ns_prof4, ns_prof5, partvmax !----------------------------------------------------------------------- ! Module Variables @@ -22,15 +24,16 @@ MODULE beams3d_lines !----------------------------------------------------------------------- IMPLICIT NONE LOGICAL :: ltherm - INTEGER :: ns_prof1, ns_prof2, ns_prof3, ns_prof4, ns_prof5, nsh_prof4 - INTEGER :: nparticles, nsteps, myline, mybeam, mytdex, myend, mystart_save, myend_save + INTEGER :: nsh_prof4 + INTEGER :: nsteps, myline, mybeam, mytdex, myend, mystart_save, myend_save INTEGER :: win_epower, win_ipower, win_ndot, win_dense, win_jprof, win_dist5d, win_dist5d_fida REAL(rprec) :: xlast,ylast,zlast ! for storing position REAL(rprec) :: moment, mycharge, myZ, mymass, myv_neut(3), my_end, & myqm, rand_prob, cum_prob, tau, next_t, & - partvmax, fact_crit, fact_pa, fact_vsound, fact_kick, & + fact_crit, fact_pa, fact_vsound, fact_kick, & fact_coul, fact_crit_pro, & - partpmax, h2_prof, h3_prof, h4_prof, h5_prof, r_h, z_h, p_h, e_h, pi_h, E_by_v + partpmax, h2_prof, h3_prof, h4_prof, h5_prof, r_h, & + z_h, p_h, e_h, pi_h, E_by_v LOGICAL, ALLOCATABLE :: neut_lines(:,:) INTEGER, ALLOCATABLE :: end_state(:) REAL(rprec), ALLOCATABLE :: shine_through(:), shine_port(:), GFactor(:), t_last(:) diff --git a/BEAMS3D/Sources/beams3d_runtime.f90 b/BEAMS3D/Sources/beams3d_runtime.f90 index e557341d5..6ec156f2e 100644 --- a/BEAMS3D/Sources/beams3d_runtime.f90 +++ b/BEAMS3D/Sources/beams3d_runtime.f90 @@ -51,12 +51,35 @@ ! v4.07 01/11/24 - Added ability to specifiy weights in the input !----------------------------------------------------------------------- MODULE beams3d_runtime - !----------------------------------------------------------------------- + !------------------------------------------------------------------- ! Libraries - !----------------------------------------------------------------------- + !------------------------------------------------------------------- USE stel_kinds, ONLY: rprec USE mpi_params USE EZspline + USE beams3d_globals, ONLY: r_start_in, z_start_in, phi_start_in, & + vll_start_in, mu_start_in, vr_start_in, & + vphi_start_in, vz_start_in, t_end_in, & + mass_in, charge_in, Zatom_in, weight_in, & + NE_AUX_S, TE_AUX_S, NI_AUX_S, TI_AUX_S, & + NE_AUX_F, TE_AUX_F, NI_AUX_F, TI_AUX_F, & + ZEFF_AUX_S, POT_AUX_S, ZEFF_AUX_F, & + POT_AUX_F, NI_AUX_M, NI_AUX_Z, & + Adist_beams, Asize_beams, DIV_BEAMS, & + DEX_BEAMS, R_BEAMS, Z_BEAMS, PHI_BEAMS, & + E_BEAMS, MASS_BEAMS, CHARGE_BEAMS, & + ZATOM_BEAMS, P_BEAMS, nparticles_start, & + npoinc, follow_tol, int_type, ne_scale, & + te_scale, ti_scale, zeff_scale, & + fusion_scale, lendt_m, te_col_min, & + duplicate_factor, ldebug, lbeam, & + MAXBEAMS, lbeam, MAXBEAMS, nbeams, & + pi2, NION, & + MAXPROFLEN, MAXPARTICLES, lverb, & + lbbnbi, lcollision, lfusion, & + lrestart_particles, lfusion_alpha, & + lfusion_He3, lfusion_proton, & + lfusion_tritium, lkick, lgcsim, id_string !----------------------------------------------------------------------- ! Module Variables ! lverb Logical to control screen output @@ -123,46 +146,26 @@ MODULE beams3d_runtime INTEGER, PARAMETER :: MPI_BCAST_ERR = 83 INTEGER, PARAMETER :: MPI_FINE_ERR = 89 - INTEGER, PARAMETER :: MAXPARTICLES = 2**18 - INTEGER, PARAMETER :: MAXBEAMS = 32 - INTEGER, PARAMETER :: MAXPROFLEN = 512 - INTEGER, PARAMETER :: NION = 4 - DOUBLE PRECISION, PARAMETER :: one = 1.0D0 ! 1.0 - - LOGICAL :: lverb, lvmec, lpies, lspec, lcoil, lmgrid, & - lvessel, lvac, lcontinue_grid, lrestart_particles, lneut, & - lbeam, lhitonly, lread_input, lplasma_only, lraw,& - ldepo, lbeam_simple, ldebug, lcollision, lw7x, lsuzuki, & - lascot, lascot4, lbbnbi, lfidasim, lfidasim_cyl, lsplit, lvessel_beam, lascotfl, lrandomize, & - lfusion, lfusion_alpha, leqdsk, lhint, lkick, lgcsim, & - lboxsim, limas, lfieldlines, lfusion_tritium, lfusion_proton, lfusion_He3, lbeamdensity - INTEGER :: nextcur, npoinc, nbeams, nparticles_start, nprocs_beams, & - ndt, ndt_max, duplicate_factor - INTEGER, DIMENSION(MAXBEAMS) :: Dex_beams + LOGICAL :: lvmec, lpies, lspec, lcoil, lmgrid, & + lvessel, lvac, lcontinue_grid, lneut, & + lhitonly, lread_input, lplasma_only, lraw, & + ldepo, lbeam_simple, lw7x, lsuzuki, & + lascot, lascot4, lfidasim, lfidasim_cyl, lsplit, & + lvessel_beam, lascotfl, lrandomize, leqdsk, lhint, & + lboxsim, limas, lfieldlines, lbeamdensity + INTEGER :: nextcur, nprocs_beams, ndt, ndt_max INTEGER, ALLOCATABLE :: beam(:) - REAL(rprec) :: dt, follow_tol, pi, pi2, invpi2, mu0, to3, dt_save, & - ne_scale, te_scale, ti_scale, zeff_scale, fusion_scale, & - lendt_m, te_col_min, rminor_norm - REAL(rprec), DIMENSION(MAXBEAMS) :: Adist_beams, Asize_beams, Div_beams, E_beams, mass_beams, & - charge_beams, Zatom_beams, P_beams - REAL(rprec), DIMENSION(MAXBEAMS, 2) :: r_beams, z_beams, phi_beams - REAL(rprec), DIMENSION(MAXPROFLEN) :: TE_AUX_S, TE_AUX_F, NE_AUX_S, NE_AUX_F, TI_AUX_S, TI_AUX_F,& - POT_AUX_S, POT_AUX_F, ZEFF_AUX_S, ZEFF_AUX_F - REAL(rprec), DIMENSION(MAXPROFLEN) :: NI_AUX_S - REAL(rprec), DIMENSION(NION,MAXPROFLEN) :: NI_AUX_F - INTEGER, DIMENSION(NION) :: NI_AUX_Z - REAL(rprec), DIMENSION(NION) :: NI_AUX_M - REAL(rprec), DIMENSION(MAXPARTICLES) :: r_start_in, phi_start_in, z_start_in, vll_start_in, & - & mu_start_in, charge_in, Zatom_in, mass_in, t_end_in, & - vr_start_in, vphi_start_in, vz_start_in, weight_in + REAL(rprec) :: dt, pi, invpi2, mu0, to3, dt_save, rminor_norm LOGICAL, ALLOCATABLE :: lgc2fo_start(:) REAL(rprec), ALLOCATABLE :: R_start(:), phi_start(:), Z_start(:), vll_start(:), mu_start(:), & & mass(:), charge(:), Zatom(:), t_end(:), weight(:), vr_start(:), vphi_start(:), vz_start(:) REAL(rprec), ALLOCATABLE :: extcur(:) CHARACTER(LEN=10) :: qid_str_saved ! For ASCOT5 - CHARACTER(256) :: id_string, mgrid_string, coil_string, & - vessel_string, int_type, restart_string, continue_grid_string, bbnbi_string, eqdsk_string + CHARACTER(256) :: mgrid_string, coil_string, & + vessel_string, restart_string, & + continue_grid_string, bbnbi_string, & + eqdsk_string REAL(rprec), PARAMETER :: BEAMS3D_VERSION = 4.07 ! this is the full orbit test version diff --git a/BENCHMARKS/BEAMS3D_TEST/input.ORBITS_slow b/BENCHMARKS/BEAMS3D_TEST/input.ORBITS_slow index 8efbb9582..1f68ed9f9 100644 --- a/BENCHMARKS/BEAMS3D_TEST/input.ORBITS_slow +++ b/BENCHMARKS/BEAMS3D_TEST/input.ORBITS_slow @@ -52,32 +52,20 @@ RBC( 0, 1) = 1.0000000000e+00 ZBS( 0, 1) = 1.0000000000e+00 INT_TYPE = 'LSODE' FOLLOW_TOL = 1.00000000000000E-08 VC_ADAPT_TOL = 1.00E-03 - R_START_IN = 40*10.5 Z_START_IN = 40*0.0 PHI_START_IN = 40*0.0 CHARGE_IN = 40*1.60217733E-19 - MASS_IN = 40*1.6726231E-27 + MASS_IN = 40*3.3434954106E-27 ZATOM_IN = 40*1.0 T_END_IN = 40*1.0E-3 NPOINC = 1000 - NE_AUX_S = 0.0 0.2 0.4 0.6 0.8 1.0 - NE_AUX_F = 1.2E20 1.0E20 0.8E20 0.6E20 0.4E20 0.2E20 - TE_AUX_S = 0.0 0.2 0.4 0.6 0.8 1.0 - TE_AUX_F = 1.0E04 0.8E04 0.6E04 0.4E04 0.2E04 0.0E04 - TI_AUX_S = 0.0 0.2 0.4 0.6 0.8 1.0 - TI_AUX_F = 1.0E04 0.8E04 0.6E04 0.4E04 0.2E04 0.0E04 - VLL_START_IN = 4.3767277259E+04 8.7521428600E+04 1.3124934778E+05 1.7493796783E+05 2.1857428054E+05 2.6214535568E+05 - 3.0563836005E+05 3.4904057609E+05 3.9233942017E+05 4.3552246036E+05 4.7857743375E+05 5.2149226315E+05 - 5.6425507318E+05 6.0685420574E+05 6.4927823469E+05 6.9151597983E+05 7.3355652011E+05 7.7538920600E+05 - 8.1700367103E+05 8.5838984243E+05 8.9953795097E+05 9.4043853987E+05 9.8108247275E+05 1.0214609408E+06 - 1.0615654689E+06 1.1013879211E+06 1.1409205047E+06 1.1801557741E+06 1.2190866335E+06 1.2577063383E+06 - 1.2960084967E+06 1.3339870693E+06 1.3716363692E+06 1.4089510599E+06 1.4459261541E+06 1.4825570104E+06 - 1.5188393303E+06 1.5547691543E+06 1.5903428569E+06 1.6255571421E+06 - MU_START_IN = 3.2040342566E-15 3.2030734306E-15 3.2014733340E-15 3.1992358826E-15 3.1963637506E-15 3.1928603627E-15 - 3.1887298836E-15 3.1839772059E-15 3.1786079357E-15 3.1726283762E-15 3.1660455093E-15 3.1588669756E-15 - 3.1511010522E-15 3.1427566301E-15 3.1338431883E-15 3.1243707683E-15 3.1143499465E-15 3.1037918055E-15 - 3.0927079046E-15 3.0811102500E-15 3.0690112633E-15 3.0564237505E-15 3.0433608700E-15 3.0298361006E-15 - 3.0158632094E-15 3.0014562196E-15 2.9866293783E-15 2.9713971254E-15 2.9557740614E-15 2.9397749174E-15 - 2.9234145242E-15 2.9067077830E-15 2.8896696366E-15 2.8723150412E-15 2.8546589399E-15 2.8367162358E-15 - 2.8185017680E-15 2.8000302866E-15 2.7813164309E-15 2.7623747069E-15 + NE_AUX_S = 0.0 0.2 0.4 0.6 0.8 1.0 + NE_AUX_F = 1.2E19 1.2E19 1.2E19 1.2E19 1.2E19 1.2E19 + TE_AUX_S = 0.0 0.2 0.4 0.6 0.8 1.0 + TE_AUX_F = 1.0E03 1.0E03 1.0E03 1.0E03 1.0E03 1.0E03 + TI_AUX_S = 0.0 0.2 0.4 0.6 0.8 1.0 + TI_AUX_F = 1.0E02 1.0E02 1.0E02 1.0E02 1.0E02 1.0E02 + R_START_IN = 1.0200000000E+01 1.0215384615E+01 1.0230769231E+01 1.0246153846E+01 1.0261538462E+01 1.0276923077E+01 1.0292307692E+01 1.0307692308E+01 1.0323076923E+01 1.0338461538E+01 1.0353846154E+01 1.0369230769E+01 1.0384615385E+01 1.0400000000E+01 1.0415384615E+01 1.0430769231E+01 1.0446153846E+01 1.0461538462E+01 1.0476923077E+01 1.0492307692E+01 1.0507692308E+01 1.0523076923E+01 1.0538461538E+01 1.0553846154E+01 1.0569230769E+01 1.0584615385E+01 1.0600000000E+01 1.0615384615E+01 1.0630769231E+01 1.0646153846E+01 1.0661538462E+01 1.0676923077E+01 1.0692307692E+01 1.0707692308E+01 1.0723076923E+01 1.0738461538E+01 1.0753846154E+01 1.0769230769E+01 1.0784615385E+01 1.0800000000E+01 + VLL_START_IN = 2.9409892275E+05 3.5702255112E+05 4.1040958524E+05 4.5761004502E+05 5.0037773626E+05 5.3976736155E+05 5.7647179483E+05 6.1097516798E+05 6.4363155728E+05 6.7470920194E+05 7.0441708726E+05 7.3292179560E+05 7.6035865492E+05 7.8683937990E+05 8.1245746683E+05 8.3729210020E+05 8.6141104398E+05 8.8487282269E+05 9.0772839439E+05 9.3002245330E+05 9.7541577801E+05 1.1647286686E+06 1.3273092340E+06 1.4720416890E+06 1.6037654646E+06 1.7254624299E+06 1.8391241199E+06 1.9461588989E+06 2.0476062588E+06 2.1442593879E+06 2.2367398717E+06 2.3255455672E+06 2.4110825611E+06 2.4936872394E+06 2.5736419680E+06 2.6511865100E+06 2.7265265160E+06 2.7998399550E+06 2.8712820664E+06 2.9409892275E+06 + MU_START_IN = 3.1896056946E-18 4.7081133792E-18 6.2315977198E-18 7.7601060613E-18 9.2936866557E-18 1.0832387855E-17 1.2376258535E-17 1.3925348047E-17 1.5479706129E-17 1.7039381490E-17 1.8604425960E-17 2.0174891379E-17 2.1750824724E-17 2.3332282145E-17 2.4919310716E-17 2.6511966656E-17 2.8110298441E-17 2.9714358526E-17 3.1324201032E-17 3.2939878046E-17 3.6298197246E-17 5.1847620675E-17 6.7452916238E-17 8.3114598332E-17 9.8833182498E-17 1.1460919764E-16 1.3044312906E-16 1.4633550987E-16 1.6228686521E-16 1.7829770574E-16 1.9436854291E-16 2.1049989802E-16 2.2669231404E-16 2.4294627705E-16 2.5926231508E-16 2.7564097855E-16 2.9208279343E-16 3.0858830244E-16 3.2515807667E-16 3.4179263442E-16 / diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS.py index 534739538..be275e9cc 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS.py @@ -3,38 +3,27 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 failtol = 1.0 filename='beams3d_ORBITS.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) # Calc values -rho = np.sqrt(data['S_lines']) +rho = np.sqrt(b3d.S_lines) rho_max = np.max(rho,axis=1) rho_min = np.min(rho,axis=1) +data = {} data['delta'] = rho_max-rho_min -x = data['R_lines']-10.0 -y = data['Z_lines'] +x = b3d.R_lines - 10.0 +y = b3d.Z_lines theta = np.arctan2(y,x) theta = np.where(theta > np.pi,theta-pi,theta) data['turning'] = np.max(theta,axis=1) -data['R0']=data['R_lines'][:,0] -data['R1']=data['R_lines'][:,1] -data['R100']=data['R_lines'][:,100] -data['R500']=data['R_lines'][:,500] -print('BEAMS3D VERSION: ' + str(data['VERSION'])) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} varlist['turning']=np.array([0.122773,0.178807,0.234767,0.290948,0.347227,0.403768,0.460658,0.517991, \ @@ -47,27 +36,6 @@ 0.074195,0.07795 ,0.081667,0.085351,0.089 ,0.092616,0.096198,0.099746, \ 0.103264,0.106749,0.110207,0.113636,0.117039,0.120418,0.123759,0.058065, \ 0.049486,0.045529,0.04275 ,0.040595,0.038827,0.037335,0.036049,0.034923]) -varlist['R0'] = np.array([10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5,\ - 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, \ - 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5]) -varlist['R1'] = np.array([10.499992,10.499976,10.499953,10.499923,10.499885,10.49984 ,10.499788, \ - 10.499728,10.499661,10.499588,10.499507,10.499419,10.499325,10.499223, \ - 10.499115,10.499 ,10.498879,10.498752,10.498619,10.49848 ,10.498335, \ - 10.498187,10.498033,10.497875,10.497711,10.497541,10.497367,10.497187, \ - 10.497001,10.49681 ,10.496615,10.496416,10.496213,10.496006,10.495796, \ - 10.495583,10.495366,10.495147,10.494925,10.4947 ]) -varlist['R100'] = np.array([10.499754,10.499221,10.498481,10.497609,10.496721,10.495958,10.495459, \ - 10.495355,10.495747,10.496633,10.497904,10.499233,10.499991,10.499159, \ - 10.495212,10.486074,10.469125,10.44148 ,10.400467,10.344393,10.273494, \ - 10.190546,10.101022,10.012309, 9.932664, 9.870525, 9.835362, 9.842661, \ - 9.930143,10.205196,10.613181, 9.510904,10.425695, 9.862287, 9.611502, \ - 9.512494, 9.503419, 9.576901, 9.733121, 9.957221]) -varlist['R500'] = np.array([10.503795,10.50326 ,10.500566,10.495214,10.486654,10.474814,10.460831, \ - 10.447396,10.438981,10.440809,10.456342,10.481885,10.499768,10.479957, \ - 10.405566,10.307023,10.251583,10.303552,10.476386,10.579363,10.342586, \ - 10.078698,10.120321,10.468361,10.197734, 9.873231,10.388056,10.003795, \ - 9.85138 , 9.783241,10.426957, 9.47885 , 9.722051,10.438802, 9.614975, \ - 9.973302, 9.643847,10.326634, 9.500989,10.320038]) for temp in varlist: act = varlist[temp] cal = data[temp] @@ -75,17 +43,19 @@ cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) perct = 100*sum(abs(act-cal)/div) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(round(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) + sys.exit(0) diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_depo.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_depo.py index a7060d8d7..1089bca6e 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_depo.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_depo.py @@ -3,47 +3,70 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 -failtol = 5.0 +failtol = 20.0 filename='beams3d_ORBITS_depo.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) # Calc values +data = {} +data['Shinethrough'] = b3d.Shinethrough +[rho,depo]= b3d.calcDepo(ns=16) +data['Deposition_B1E1'] = depo[0,:] +data['Deposition_B1E2'] = depo[1,:] +data['Deposition_B1E3'] = depo[2,:] +data['Deposition_B2E1'] = depo[3,:] +data['Deposition_B2E2'] = depo[4,:] +#data['Deposition_B2E3'] = depo[5,:] -print('BEAMS3D VERSION: ' + str(round(data['VERSION'],2))) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} -varlist['Shinethrough']=np.array([34, 18, 10, 1, 1, 1]) -#print(data['Shinethrough']) +#varlist['Shinethrough']=np.array([34, 18, 10, 1, 0, 0]) +varlist['Deposition_B1E1']=np.array([6.632940e+18,2.594600e+18,1.431116e+18,1.012614e+18,7.867336e+17, \ + 6.228894e+17,4.855791e+17,4.210176e+17,3.390240e+17,3.075314e+17, \ + 2.658876e+17,2.119868e+17,1.523728e+17,1.426544e+17,9.585534e+16, \ + 5.917356e+16]) +varlist['Deposition_B1E2']=np.array([1.671878e+19,6.162154e+18,3.473067e+18,2.389185e+18,1.718217e+18, \ + 1.470851e+18,1.243820e+18,1.094551e+18,8.874908e+17,7.915353e+17, \ + 6.467071e+17,5.569967e+17,4.268296e+17,3.553849e+17,2.420271e+17, \ + 1.791050e+17]) +varlist['Deposition_B1E3']=np.array([2.547626e+19,8.600564e+18,5.248852e+18,3.758316e+18,2.831966e+18, \ + 2.494977e+18,1.845696e+18,1.730327e+18,1.528507e+18,1.287941e+18, \ + 1.081973e+18,9.562760e+17,7.542674e+17,6.753299e+17,4.477863e+17, \ + 2.704863e+17]) +varlist['Deposition_B2E1']=np.array([1.502596e+19,3.208317e+18,1.637006e+18,1.215329e+18,9.440003e+17, \ + 8.338557e+17,7.134530e+17,5.970941e+17,5.603523e+17,5.046326e+17, \ + 4.198645e+17,3.591806e+17,2.852193e+17,2.213884e+17,1.769476e+17, \ + 8.392739e+16]) +varlist['Deposition_B2E2']=np.array([1.046748e+19,3.297453e+18,2.037332e+18,1.656553e+18,1.659661e+18, \ + 1.577892e+18,1.382742e+18,1.425945e+18,1.295802e+18,1.216265e+18, \ + 1.116363e+18,1.000230e+18,8.233047e+17,7.038711e+17,5.307589e+17, \ + 2.932251e+17]) +#varlist['Deposition_B2E3']=np.array([5.945498e+18,2.521645e+18,1.877535e+18,1.797673e+18,1.923841e+18, \ +# 2.078492e+18,1.921390e+18,2.017907e+18,2.056794e+18,1.922589e+18, \ +# 1.900198e+18,1.785054e+18,1.552839e+18,1.315236e+18,1.034035e+18, \ +# 5.391188e+17]) for temp in varlist: act = varlist[temp] cal = data[temp] + #print(np.array2string(cal,precision=6, separator=',')) cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) - perct = max(abs(act-cal)) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(round(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + perct = 100*sum(abs(act-cal)/div) + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) - - - - + sys.exit(0) diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_depo_adas.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_depo_adas.py index 0c5610515..472be2034 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_depo_adas.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_depo_adas.py @@ -3,47 +3,69 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 failtol = 5.0 filename='beams3d_ORBITS_depo_adas.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) # Calc values +data = {} +[rho,depo]= b3d.calcDepo(ns=16) +data['Deposition_B1E1'] = depo[0,:] +data['Deposition_B1E2'] = depo[1,:] +data['Deposition_B1E3'] = depo[2,:] +data['Deposition_B2E1'] = depo[3,:] +data['Deposition_B2E2'] = depo[4,:] +data['Deposition_B2E3'] = depo[5,:] -print('BEAMS3D VERSION: ' + str(round(data['VERSION'],2))) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} -varlist['Shinethrough']=np.array([34, 22, 12, 5]) -#print(data['Shinethrough']) +#varlist['Shinethrough']=np.array([34, 18, 10, 1, 0, 0]) +varlist['Deposition_B1E1']=np.array([6.632940e+18,2.594600e+18,1.431116e+18,1.012614e+18,7.867336e+17, \ + 6.228894e+17,4.855791e+17,4.210176e+17,3.390240e+17,3.075314e+17, \ + 2.658876e+17,2.119868e+17,1.523728e+17,1.426544e+17,9.585534e+16, \ + 5.917356e+16]) +varlist['Deposition_B1E2']=np.array([1.671878e+19,6.162154e+18,3.473067e+18,2.389185e+18,1.718217e+18, \ + 1.470851e+18,1.243820e+18,1.094551e+18,8.874908e+17,7.915353e+17, \ + 6.467071e+17,5.569967e+17,4.268296e+17,3.553849e+17,2.420271e+17, \ + 1.791050e+17]) +varlist['Deposition_B1E3']=np.array([2.547626e+19,8.600564e+18,5.248852e+18,3.758316e+18,2.831966e+18, \ + 2.494977e+18,1.845696e+18,1.730327e+18,1.528507e+18,1.287941e+18, \ + 1.081973e+18,9.562760e+17,7.542674e+17,6.753299e+17,4.477863e+17, \ + 2.704863e+17]) +varlist['Deposition_B2E1']=np.array([1.502596e+19,3.208317e+18,1.637006e+18,1.215329e+18,9.440003e+17, \ + 8.338557e+17,7.134530e+17,5.970941e+17,5.603523e+17,5.046326e+17, \ + 4.198645e+17,3.591806e+17,2.852193e+17,2.213884e+17,1.769476e+17, \ + 8.392739e+16]) +varlist['Deposition_B2E2']=np.array([1.046748e+19,3.297453e+18,2.037332e+18,1.656553e+18,1.659661e+18, \ + 1.577892e+18,1.382742e+18,1.425945e+18,1.295802e+18,1.216265e+18, \ + 1.116363e+18,1.000230e+18,8.233047e+17,7.038711e+17,5.307589e+17, \ + 2.932251e+17]) +varlist['Deposition_B2E3']=np.array([5.945498e+18,2.521645e+18,1.877535e+18,1.797673e+18,1.923841e+18, \ + 2.078492e+18,1.921390e+18,2.017907e+18,2.056794e+18,1.922589e+18, \ + 1.900198e+18,1.785054e+18,1.552839e+18,1.315236e+18,1.034035e+18, \ + 5.391188e+17]) for temp in varlist: act = varlist[temp] cal = data[temp] + #print(np.array2string(cal,precision=6, separator=',')) cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) - perct = max(abs(act-cal)) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(round(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + perct = 100*sum(abs(act-cal)/div) + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) - - - - + sys.exit(0) diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_eqdsk.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_eqdsk.py index 475d75cd6..e186e2804 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_eqdsk.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_eqdsk.py @@ -3,48 +3,70 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 -failtol = 10.0 +failtol = 20.0 filename='beams3d_ORBITS_eqdsk.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) # Calc values +data = {} +data['Shinethrough'] = b3d.Shinethrough +[rho,depo]= b3d.calcDepo(ns=16) +data['Deposition_B1E1'] = depo[0,:] +data['Deposition_B1E2'] = depo[1,:] +data['Deposition_B1E3'] = depo[2,:] +data['Deposition_B2E1'] = depo[3,:] +data['Deposition_B2E2'] = depo[4,:] +data['Deposition_B2E3'] = depo[5,:] -print('BEAMS3D VERSION: ' + str(round(data['VERSION'],2))) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} -varlist['Shinethrough']=np.array([18.543322,13.09413 ,11.835307,19.003081,13.060472,12.109276]) -#print(data['Shinethrough']) +#varlist['Shinethrough']=np.array([34, 18, 10, 1, 0, 0]) +varlist['Deposition_B1E1']=np.array([4.466062e+19,3.112300e+19,2.348636e+19,1.487319e+19,1.103912e+19, \ + 8.094944e+18,6.257979e+18,5.400623e+18,4.874593e+18,4.197121e+18, \ + 3.579773e+18,3.633305e+18,3.020388e+18,2.750214e+18,2.418788e+18, \ + 9.718464e+17]) +varlist['Deposition_B1E2']=np.array([7.714851e+19,5.602495e+19,3.913470e+19,2.883455e+19,2.080546e+19, \ + 1.675960e+19,1.312089e+19,1.243215e+19,1.114408e+19,1.041841e+19, \ + 9.067863e+18,7.988774e+18,7.539497e+18,7.576122e+18,6.276814e+18, \ + 2.410528e+18]) +varlist['Deposition_B1E3']=np.array([9.937372e+19,6.797368e+19,4.925968e+19,3.829194e+19,2.930141e+19, \ + 2.275644e+19,2.072090e+19,1.771813e+19,1.748743e+19,1.591874e+19, \ + 1.457257e+19,1.360660e+19,1.366905e+19,1.426168e+19,1.130261e+19, \ + 5.104438e+18]) +varlist['Deposition_B2E1']=np.array([4.587507e+19,3.445716e+19,2.316060e+19,1.485832e+19,1.041520e+19, \ + 8.142330e+18,6.454796e+18,5.737334e+18,4.873494e+18,4.302033e+18, \ + 3.765762e+18,3.134169e+18,3.052567e+18,2.869484e+18,2.405204e+18, \ + 9.035431e+17]) +varlist['Deposition_B2E2']=np.array([7.954348e+19,5.803747e+19,3.988500e+19,2.859940e+19,1.935425e+19, \ + 1.736060e+19,1.342601e+19,1.171052e+19,1.034543e+19,1.011741e+19, \ + 8.893924e+18,8.495731e+18,7.935270e+18,7.512586e+18,6.675309e+18, \ + 2.552085e+18]) +varlist['Deposition_B2E3']=np.array([9.830415e+19,6.944995e+19,5.248501e+19,3.670912e+19,2.849720e+19, \ + 2.286985e+19,2.069946e+19,1.809512e+19,1.662198e+19,1.546932e+19, \ + 1.463727e+19,1.396286e+19,1.425235e+19,1.363103e+19,1.200816e+19, \ + 4.618210e+18]) for temp in varlist: act = varlist[temp] cal = data[temp] #print(np.array2string(cal,precision=6, separator=',')) cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) - perct = max(abs(act-cal)) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(round(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + perct = 100*sum(abs(act-cal)/div) + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) - - - - + sys.exit(0) diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_er.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_er.py index 01d6a27af..2377c1e0b 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_er.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_er.py @@ -1,74 +1,41 @@ #!/usr/bin/env python3 import sys, os sys.path.insert(0, '../../pySTEL/') -import numpy as np #For Arrays +import numpy as np from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 failtol = 1.0 filename='beams3d_ORBITS_er.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) # Calc values -rho = np.sqrt(data['S_lines']) +rho = np.sqrt(b3d.S_lines) rho_max = np.max(rho,axis=1) rho_min = np.min(rho,axis=1) +data = {} data['delta'] = rho_max-rho_min -x = data['R_lines']-10.0 -y = data['Z_lines'] +x = b3d.R_lines - 10.0 +y = b3d.Z_lines theta = np.arctan2(y,x) theta = np.where(theta > np.pi,theta-pi,theta) data['turning'] = np.max(theta,axis=1) -data['R0']=data['R_lines'][:,0] -data['R1']=data['R_lines'][:,1] -data['R100']=data['R_lines'][:,100] -data['R500']=data['R_lines'][:,500] -print('BEAMS3D VERSION: ' + str(data['VERSION'])) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} -varlist['turning']=np.array([0.731838,0.790795,0.850828,0.912093,0.974706,1.038889,1.104832,1.17283, \ - 1.243056,1.316021,1.392038,1.47161 ,1.555389,1.644199,1.739122,1.841615, \ - 1.953885,2.079128,2.223145,2.39678 ,2.630406,3.141537,3.137031,3.140399, \ - 3.140612,3.139513,3.124417,3.137346,3.131421,3.135479,3.137099,3.128988, \ - 3.140575,3.049741,3.140872,3.131329,3.139236,3.092125,3.102366,3.070513]) +varlist['turning']=np.array([0.731858,0.790553,0.850824,0.912077,0.974712,1.038719,1.104833,1.172821, \ + 1.243094,1.316038,1.392032,1.471591,1.555411,1.644194,1.739137,1.841611, \ + 1.953852,2.07912 ,2.223097,2.396782,2.630352,3.141335,3.137608,3.139102, \ + 3.14006 ,3.131666,3.140788,3.139625,3.139039,3.12906 ,3.13544 ,3.131839, \ + 3.140812,3.141167,3.141409,3.135179,3.141481,3.140862,3.140919,3.07051 ]) varlist['delta']= np.array([0.054275,0.058177,0.062093,0.066008,0.069844,0.073672,0.077491,0.081266, \ 0.085027,0.088759,0.092453,0.096132,0.099778,0.103395,0.106995,0.110572, \ 0.114112,0.11766 ,0.121189,0.124668,0.128161,0.054815,0.046612,0.042663, \ 0.039882,0.037724,0.035944,0.034453,0.033163,0.032031,0.031029,0.030138, \ 0.029342,0.0286 ,0.027936,0.02734 ,0.026778,0.02624 ,0.025781,0.025343]) -varlist['R0'] = np.array([10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5,\ - 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, \ - 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5]) -varlist['R1'] = np.array([10.49942 ,10.499323,10.499219,10.499107,10.498988,10.498862,10.498729, \ - 10.498589,10.498442,10.498289,10.49813 ,10.497966,10.497795,10.497618, \ - 10.497434,10.497243,10.497045,10.49684 ,10.496629,10.496412,10.49619 , \ - 10.495963,10.495731,10.495494,10.495253,10.495006,10.494756,10.494502, \ - 10.494243,10.493981,10.493715,10.493446,10.493174,10.492899,10.492621, \ - 10.49234 ,10.492057,10.491772,10.491486,10.491197]) -varlist['R100'] = np.array([10.493531,10.49579 ,10.498172,10.49983 ,10.499366,10.494715,10.483092, \ - 10.461105,10.425261,10.372748,10.302666,10.217086,10.121516,10.024057, \ - 9.93403 , 9.860654, 9.813137, 9.804805, 9.867944,10.106374,10.624615, \ - 9.574294,10.212791, 9.699082, 9.53475 , 9.499776, 9.564192, 9.732641, \ - 9.991137,10.273848,10.466821,10.485276,10.348775,10.139999, 9.928042, \ - 9.748598, 9.616247, 9.536444, 9.511127, 9.540217]) -varlist['R500'] = np.array([10.402748,10.420905,10.459104,10.495759,10.484648,10.394469,10.270076, \ - 10.205655,10.279346,10.495961,10.564013,10.233509,10.008089,10.192777, \ - 10.474815, 9.921363, 9.989771,10.457151, 9.692552,10.130114,10.581929, \ - 9.612629, 9.490115, 9.567085,10.498358, 9.519236,10.404771, 9.508298, \ - 10.48246 , 9.586777, 9.95068 ,10.198179, 9.509421,10.282663,10.013566, \ - 9.526892,10.309831,10.088302, 9.51169 ,10.132791]) - for temp in varlist: act = varlist[temp] cal = data[temp] @@ -76,18 +43,16 @@ cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) perct = 100*sum(abs(act-cal)/div) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(round(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) - - - - + sys.exit(0) diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_fusion.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_fusion.py index 6ba78c971..66711b470 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_fusion.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_fusion.py @@ -3,49 +3,42 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 failtol = 5.0 filename='beams3d_ORBITS_fusion.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) # Calc values -rho = np.sqrt(data['S_lines']) -#print(data.keys()) -weight = data['Weight'] -beam = data['Beam'] - -wtemp = np.where(beam==1,weight,0) -data['birth_rate_He4'], temp = np.histogram(rho[:,0],weights=wtemp,bins=[0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]) -wtemp = np.where(beam==2,weight,0) -data['birth_rate_T'], temp = np.histogram(rho[:,0],weights=wtemp,bins=[0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]) -wtemp = np.where(beam==3,weight,0) -data['birth_rate_p'], temp = np.histogram(rho[:,0],weights=wtemp,bins=[0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]) -wtemp = np.where(beam==4,weight,0) -data['birth_rate_He3'], temp = np.histogram(rho[:,0],weights=wtemp,bins=[0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]) - +data = {} +[rho,depo]= b3d.calcDepo(ns=16) +data['Birth_He4'] = depo[0,:] +data['Birth_T'] = depo[1,:] +data['Birth_p'] = depo[2,:] +data['Birth_He3'] = depo[3,:] -print('BEAMS3D VERSION: ' + str(data['VERSION'])) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} -varlist['birth_rate_He4']=np.array([5.531974e+17,1.548293e+18,2.260494e+18,2.671512e+18,2.731105e+18, - 2.334851e+18,1.394123e+18,4.132231e+17,3.011013e+16,7.444151e+13]) -varlist['birth_rate_T']=np.array([1.405567e+15,3.948818e+15,5.843987e+15,7.007070e+15,7.375928e+15, - 6.614761e+15,4.276418e+15,1.427369e+15,1.248056e+14,4.142369e+11]) -varlist['birth_rate_p']=np.array([1.405789e+15,3.945669e+15,5.851363e+15,6.997016e+15,7.383014e+15, - 6.607894e+15,4.281632e+15,1.427379e+15,1.249589e+14,4.210743e+11]) -varlist['birth_rate_He3']=np.array([1.469183e+15,4.105819e+15,6.047775e+15,7.267702e+15,7.602216e+15, - 6.774583e+15,4.349915e+15,1.442406e+15,1.245455e+14,4.117774e+11]) +#varlist['Shinethrough']=np.array([34, 18, 10, 1, 0, 0]) +varlist['Birth_He4']=np.array([2.812140e+17,2.751405e+17,2.590578e+17,2.410255e+17,2.184702e+17, \ + 1.950605e+17,1.718746e+17,1.458198e+17,1.168888e+17,8.445555e+16, \ + 5.107926e+16,2.305566e+16,6.613366e+15,8.638698e+14,2.686111e+13, \ + 3.171751e+10]) +varlist['Birth_T']=np.array([7.196400e+14,7.022415e+14,6.655436e+14,6.156879e+14,5.659616e+14, \ + 5.110290e+14,4.560634e+14,3.966889e+14,3.283568e+14,2.468759e+14, \ + 1.577814e+14,7.708903e+13,2.434126e+13,3.671389e+12,1.364800e+11, \ + 2.129394e+08]) +varlist['Birth_p']=np.array([7.207028e+14,7.003268e+14,6.652009e+14,6.173576e+14,5.658323e+14, \ + 5.104955e+14,4.566769e+14,3.965443e+14,3.276335e+14,2.474383e+14, \ + 1.575486e+14,7.711104e+13,2.442342e+13,3.666051e+12,1.374268e+11, \ + 2.163493e+08]) +varlist['Birth_He3']=np.array([7.512938e+14,7.290716e+14,6.912372e+14,6.414480e+14,5.857319e+14, \ + 5.310180e+14,4.701472e+14,4.080294e+14,3.368531e+14,2.525191e+14, \ + 1.600640e+14,7.802688e+13,2.456785e+13,3.648097e+12,1.358381e+11, \ + 2.130947e+08]) for temp in varlist: act = varlist[temp] cal = data[temp] @@ -53,17 +46,19 @@ cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) perct = 100*sum(abs(act-cal)/div) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(round(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) + sys.exit(0) diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_loss.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_loss.py index 17a7b11ff..2be63f7f5 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_loss.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_loss.py @@ -3,45 +3,39 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 failtol = 1.0 filename='beams3d_ORBITS_loss.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) + +# Calc values +data={} +data['end_state'] = b3d.end_state -print('BEAMS3D VERSION: ' + str(data['VERSION'])) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} varlist['end_state']=np.array([0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2]) -#print(data['end_state']) for temp in varlist: act = varlist[temp] cal = data[temp] + #print(np.array2string(cal,precision=6, separator=',')) cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) perct = 100*sum(abs(act-cal)/div) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(round(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) - - - - + sys.exit(0) diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_multiion.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_multiion.py index 0de98aaed..ce284eeed 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_multiion.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_multiion.py @@ -3,47 +3,69 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 -failtol = 5.0 +failtol = 20.0 filename='beams3d_ORBITS_multiion.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) # Calc values +data = {} +[rho,depo]= b3d.calcDepo(ns=16) +data['Deposition_B1E1'] = depo[0,:] +data['Deposition_B1E2'] = depo[1,:] +data['Deposition_B1E3'] = depo[2,:] +data['Deposition_B2E1'] = depo[3,:] +data['Deposition_B2E2'] = depo[4,:] +#data['Deposition_B2E3'] = depo[5,:] -print('BEAMS3D VERSION: ' + str(round(data['VERSION'],2))) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} -varlist['Shinethrough']=np.array([18, 9, 5, 0, 0, 0]) -#print(data['Shinethrough']) +varlist['Deposition_B1E1']=np.array([3.628550e+18,1.291153e+18,7.927005e+17,5.199417e+17,3.713347e+17, \ + 3.248485e+17,2.580924e+17,2.271131e+17,1.955029e+17,1.562149e+17, \ + 1.436643e+17,1.152797e+17,8.797583e+16,8.113917e+16,5.733855e+16, \ + 3.808243e+16]) +varlist['Deposition_B1E2']=np.array([7.995488e+18,2.699743e+18,1.678032e+18,1.212555e+18,9.676878e+17, \ + 7.032958e+17,5.964166e+17,5.138963e+17,4.508982e+17,3.738844e+17, \ + 3.310177e+17,2.764420e+17,2.098081e+17,2.022517e+17,1.479625e+17, \ + 9.705334e+16]) +varlist['Deposition_B1E3']=np.array([1.189420e+19,4.261046e+18,2.594906e+18,1.906508e+18,1.366930e+18, \ + 1.136669e+18,9.516113e+17,8.312717e+17,7.041941e+17,6.424587e+17, \ + 5.336555e+17,4.899983e+17,3.621583e+17,3.108720e+17,2.561323e+17, \ + 1.811121e+17]) +varlist['Deposition_B2E1']=np.array([6.381469e+18,1.467143e+18,7.435923e+17,5.444115e+17,4.284223e+17, \ + 3.993574e+17,3.312299e+17,3.139192e+17,2.810265e+17,2.628457e+17, \ + 2.255120e+17,1.821179e+17,1.655318e+17,1.430314e+17,1.088912e+17, \ + 5.881516e+16]) +varlist['Deposition_B2E2']=np.array([5.168567e+18,1.582075e+18,1.002512e+18,8.891264e+17,7.349174e+17, \ + 7.461785e+17,7.214803e+17,6.348985e+17,6.180024e+17,5.751017e+17, \ + 5.243465e+17,4.874632e+17,4.348598e+17,3.956598e+17,3.168090e+17, \ + 1.766461e+17]) +#varlist['Deposition_B2E3']=np.array([3.947099e+18,1.434560e+18,1.107841e+18,9.501735e+17,9.426179e+17, \ +# 9.863313e+17,9.603728e+17,9.918007e+17,9.765742e+17,9.423943e+17, \ +# 8.477654e+17,8.170676e+17,7.705660e+17,6.813209e+17,5.645839e+17, \ +# 3.219246e+17]) for temp in varlist: act = varlist[temp] cal = data[temp] + #print(np.array2string(cal,precision=6, separator=',')) cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) - perct = max(abs(act-cal)) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(round(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + perct = 100*sum(abs(act-cal)/div) + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) - - - + sys.exit(0) diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_restart.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_restart.py index 9d0bbee57..c0952d8f5 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_restart.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_restart.py @@ -3,46 +3,39 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 -failtol = 5.0 +failtol = 10.0 filename='beams3d_ORBITS_restart.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) + +# Calc values +data={} +data['LOSS_PCT'] = 100*sum(b3d.end_state==2)/b3d.nparticles -print('BEAMS3D VERSION: ' + str(data['VERSION'])) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} -varlist['LOSS_PCT']=np.array([16]) -data['LOSS_PCT'] = 100*sum(data['end_state']==2)/data['nparticles'] -#print(data['LOSS_PCT']) +varlist['LOSS_PCT']=np.array([1]) for temp in varlist: act = varlist[temp] cal = data[temp] + print(np.array2string(cal,precision=6, separator=',')) cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) perct = 100*sum(abs(act-cal)/div) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(int(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) - - - - + sys.exit(0) diff --git a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_slow.py b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_slow.py index 44fe8fd89..efbbc83d1 100755 --- a/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_slow.py +++ b/BENCHMARKS/BEAMS3D_TEST/test_ORBITS_slow.py @@ -3,77 +3,91 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.beams3d import read_beams3d - -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +from libstell.beams3d import BEAMS3D lfail = 0 -failtol = 70.0 +failtol = 5.0 filename='beams3d_ORBITS_slow.h5' -data=read_beams3d(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) +b3d = BEAMS3D() +b3d.read_beams3d(filename) # Calc values -#rho = np.sqrt(data['S_lines']) -#rho_max = np.max(rho,axis=1) -#rho_min = np.min(rho,axis=1) -#data['delta'] = rho_max-rho_min -#x = data['R_lines']-10.0 -#y = data['Z_lines'] -#theta = np.arctan2(y,x) -#theta = np.where(theta > np.pi,theta-pi,theta) -#data['turning'] = np.max(theta,axis=1) -data['R0']=data['R_lines'][:,0] -data['R1']=data['R_lines'][:,1] -data['R100']=data['R_lines'][:,100] -#data['R500']=data['R_lines'][:,500] +data={} +data['vll0']=b3d.vll_lines[:,0] +data['vll100']=b3d.vll_lines[:,100] +data['vll500']=b3d.vll_lines[:,500] +data['vll1000']=b3d.vll_lines[:,1000] +data['epower']=b3d.epower_prof[:,0]*1.0E20 # factor to make values visible in output. +data['ipower']=b3d.ipower_prof[:,0]*1.0E20 +#vperp=b3d.calcVperp() -print('BEAMS3D VERSION: ' + str(data['VERSION'])) +print(f'BEAMS3D VERSION: {b3d.VERSION:4.2f}') print('==== Vectors ====') varlist={} -#varlist['turning']=np.array([0.4270134, 1.30000282, 1.00853362, 0.91105419, 3.13805239, 1.28424185, \ -# 0.63219703, 0.53907533, 1.86587054, 2.2327981, 2.5049937, 2.31536106, \ -# 0.8311377, 0.94574217, 1.57115154, 1.53356953, 2.30289523, 1.51445262, \ -# 1.42795221, 1.80855121, 3.12543453, 1.61452375, 1.85243264, 3.13577233, \ -# 3.13918886, 3.13863239, 3.11512853, 3.138203, 3.13938066, 2.57006529, \ -# 3.13437534, 3.14106569, 3.13746063, 3.14063411, 3.13657694, 3.12631134, \ -# 3.13494179, 3.1363516, 3.13770466, 3.13370024]) -#varlist['delta']= np.array([0.0634609, 0.11510263, 0.08012891, 0.12684286, 0.13316283, 0.13978225, \ -# 0.07209561, 0.09396838, 0.11271003, 0.12254434, 0.13770218, 0.12489736, \ -# 0.09306725, 0.09730119, 0.10413771, 0.10027177, 0.11936921, 0.12905228, \ -# 0.10249505, 0.12127122, 0.12560551, 0.13547327, 0.12276697, 0.1261778, \ -# 0.13144611, 0.11954146, 0.13844897, 0.13060579, 0.1422127, 0.13046484, \ -# 0.12998523, 0.04811766, 0.14725451, 0.04874182, 0.04726258, 0.17453879, \ -# 0.12138846, 0.14027319, 0.04648992, 0.15181176]) -varlist['R0'] = np.array([10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5,\ - 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, \ - 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5]) -varlist['R1'] = np.array([10.499993,10.499976,10.49995 ,10.499913,10.499876,10.499845,10.499784, \ - 10.499725,10.499668,10.499595,10.499498,10.499407,10.499345,10.499216, \ - 10.499128,10.498982,10.498882,10.498773,10.498641,10.498504,10.498285, \ - 10.498209,10.498053,10.497828,10.497679,10.497522,10.497377,10.497145, \ - 10.496948,10.496834,10.496608,10.496386,10.496202,10.496011,10.495805, \ - 10.495634,10.495307,10.495127,10.494906,10.494667]) -varlist['R100'] = np.array([10.511974,10.496885,10.5041 ,10.489401,10.48416 ,10.485559,10.465555, \ - 10.484323,10.36921 ,10.500351,10.464425,10.407678,10.49449 ,10.337584, \ - 10.376809,10.149902,10.373562,10.348876,10.140087,10.168241,10.001694, \ - 10.031635, 9.962286, 9.938457, 9.852885, 9.731119, 9.780712, 9.889805, \ - 10.135317,10.019791,10.115431,10.401325, 9.681586, 9.809915, 9.496002, \ - 10.248991, 9.499636, 9.800984,10.296117, 9.94482 ]) -#varlist['R500'] = np.array([10.54277998, 10.57196712, 10.27044819, 10.37134606, 10.36949525, 10.36275332, \ -# 10.53850064, 10.51174778, 10.06890164, 10.4471823, 10.42614472, 10.48604785, \ -# 10.46567, 10.38794642, 10.00457241, 10.44508214, 10.48880624, 10.41658241, \ -# 10.47249319, 9.96727961, 9.52727141, 10.28322166, 10.58856652, 9.74404286, \ -# 9.70036853, 10.23995058, 9.72115835, 9.49246235, 10.51031916, 10.38976587, \ -# 9.62317718, 10.07464268, 9.67119336, 10.49999564, 9.81744224, 10.04807668, \ -# 9.50293593, 10.06782083, 9.98882236, 9.50144957]) - +varlist['vll0']=np.array([ 294098.92275, 357022.55112, 410409.58524, 457610.04502, 500377.73626, \ + 539767.36155, 576471.79483, 610975.16798, 643631.55728, 674709.20194, \ + 704417.08726, 732921.7956 , 760358.65492, 786839.3799 , 812457.46683, \ + 837292.1002 , 861411.04398, 884872.82269, 907728.39439, 930022.4533 , \ + 975415.77801,1164728.6686 ,1327309.234 ,1472041.689 ,1603765.4646 , \ + 1725462.4299 ,1839124.1199 ,1946158.8989 ,2047606.2588 ,2144259.3879 , \ + 2236739.8717 ,2325545.5672 ,2411082.5611 ,2493687.2394 ,2573641.968 , \ + 2651186.51 ,2726526.516 ,2799839.955 ,2871282.0664 ,2940989.2275 ]) +varlist['vll100']=np.array([ 282717.651171, 357700.917488, 379593.945751, 434166.076274, \ + 507865.30335 , 521342.689166, 577566.810132, 621820.18107 , \ + 643003.611857, 659568.174521, 674367.01576 , 749928.609576, \ + 752505.748557, 788568.628099, 821248.911841, 834088.994623, \ + 864337.251807, 881928.455033, 909963.263199, 926159.912122, \ + 973451.53509 ,1145150.166113,1318729.873677,1470340.479957, \ + 1606267.558802,1705081.231684,1821728.470936,1914405.195584, \ + 2029791.476175,2121185.69061 ,2218471.201794,2311573.222432, \ + 2413974.907352,2495103.171846,2579175.707541,2651703.704753, \ + 2713428.417262,2812501.106634,2863573.391217,2910764.807344]) +varlist['vll500']=np.array([ 0. , 278662.452766, 356773.915775, 387981.778624, \ + 468331.407205, 414237.553553, 514287.031027, 570562.136451, \ + 647772.641444, 615600.605769, 627781.922628, 734665.973358, \ + 740965.579077, 771763.876468, 789889.909124, 812379.926093, \ + 849789.674484, 874140.817338, 909645.186791, 903443.688479, \ + 960216.988538,1140601.028425,1264789.018119,1467102.935318, \ + 1619307.178197,1693263.810759,1813414.468838,1877658.279684, \ + 2039002.02607 ,2101313.256286,2221216.409681,2308800.283536, \ + 2401563.474693,2478106.340042,2558857.753772,2625778.391515, \ + 2689901.138478,2755085.685582,2838375.57485 ,2924055.420625]) +varlist['vll1000']=np.array([ 0. , 0. , 179441.938371, 327090.862784, \ + 416930.315303, 421036.828188, 424266.803897, 537270.081489, \ + 599701.141858, 545779.184686, 448067.03938 , 705512.639114, \ + 701069.245152, 735021.659102, 766634.217227, 777941.764024, \ + 815558.101131, 861501.673424, 902204.642577, 891054.284121, \ + 956684.204114,1098446.645432,1210085.599659,1447928.286859, \ + 1599239.109764,1656478.587166,1774982.083019,1902525.37609 , \ + 2032493.932783,2106728.816122,2189726.095829,2292455.757508, \ + 2396764.577247,2495195.103358,2539959.467151,2609682.787277, \ + 2661314.22395 ,2771151.643546,2860783.124223,2905307.132962]) +varlist['epower']=np.array([0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00, \ + 0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00, \ + 0.000000e+00,2.978817e-19,8.196595e-19,1.479824e-18,1.995152e-18, \ + 2.433991e-18,2.815667e-18,3.174593e-18,3.498285e-18,3.771568e-18, \ + 4.040178e-18,4.285944e-18,4.493051e-18,4.702538e-18,4.878200e-18, \ + 5.059257e-18,5.210403e-18,5.368755e-18,5.500434e-18,5.640376e-18, \ + 5.756385e-18,6.209118e-18,8.945263e-18,1.143963e-17,1.210034e-17, \ + 1.438360e-17,1.690205e-17,1.917533e-17,2.121840e-17,2.338720e-17, \ + 2.501317e-17,2.694854e-17,2.884840e-17,3.022119e-17,3.212499e-17, \ + 3.262013e-17,3.189256e-17,3.298883e-17,3.505542e-17,3.665324e-17, \ + 3.777253e-17,2.438329e-17,1.618972e-17,0.000000e+00,0.000000e+00, \ + 0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00, \ + 0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00])*1.0E20 +varlist['ipower']=np.array([0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00, \ + 0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00, \ + 0.000000e+00,7.242414e-17,1.301933e-16,1.486861e-16,1.229329e-16, \ + 1.046713e-16,9.108159e-17,8.121272e-17,7.316493e-17,6.605360e-17, \ + 6.046818e-17,5.566710e-17,5.126153e-17,4.765085e-17,4.428020e-17, \ + 4.146908e-17,3.881228e-17,3.656547e-17,3.442239e-17,3.258913e-17, \ + 3.082808e-17,2.866890e-17,2.390849e-17,2.052430e-17,1.591652e-17, \ + 1.513289e-17,1.448901e-17,1.361646e-17,1.271008e-17,1.200798e-17, \ + 1.115763e-17,1.057402e-17,1.004923e-17,9.427136e-18,9.043312e-18, \ + 8.330706e-18,7.440458e-18,7.123575e-18,7.042852e-18,6.852692e-18, \ + 6.586161e-18,4.137279e-18,2.634671e-18,0.000000e+00,0.000000e+00, \ + 0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00, \ + 0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00])*1.0E20 for temp in varlist: act = varlist[temp] cal = data[temp] @@ -81,17 +95,19 @@ cal = np.where(act==0,0,cal) div = np.where(act==0,1,act) perct = 100*sum(abs(act-cal)/div) - print(' '+temp+': '+str(cal[0])+' '+str(act[0])+' '+str(round(perct))+'%') - if perct > failtol: - lfail = 1 -print('=================') - + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 + print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') - -sys.exit(0) + sys.exit(0) diff --git a/BENCHMARKS/FIELDLINES_TEST/compare_NCSX_s1.py b/BENCHMARKS/FIELDLINES_TEST/compare_NCSX_s1.py index 83708e4a9..10a2f636f 100755 --- a/BENCHMARKS/FIELDLINES_TEST/compare_NCSX_s1.py +++ b/BENCHMARKS/FIELDLINES_TEST/compare_NCSX_s1.py @@ -3,24 +3,24 @@ sys.path.insert(0, '../../pySTEL/') import numpy as np #For Arrays from math import pi -from libstell.fieldlines import read_fieldlines, calc_iota +from libstell.fieldlines import FIELDLINES -try: - qtCreatorPath=os.environ["STELLOPT_PATH"] -except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) +lfail = 0 failtol = 1.0 filename='fieldlines_NCSX_s1.h5' -data=read_fieldlines(filename) -if not data: - print('ERROR Opening File: '+filename) - sys.exit(0) -else: - print('EXTENSION: '+filename) +fld = FIELDLINES() +fld.read_fieldlines(filename) + +# Calc values +data = {} +data['iota0'] = fld.iota0 +[_,data['iota'],_] = fld.calc_iota() + + +print(f'FIELDLINES VERSION: {fld.VERSION:4.2f}') print('==== Scalars ====') varlist={} -varlist['iota0']=0.2953595750052106 +varlist['iota0']=0.1410238051304572 lfail = 0; for temp in varlist: act = varlist[temp] @@ -31,7 +31,6 @@ lfail = 1 print('==== Vectors ====') varlist={} -iota_data = calc_iota(data) varlist['iota']=np.array([[ 0.14018862], [ 0.1405419 ], [ 0.14089518], [ 0.14146037], [0.14251876], [ 0.14398264], [ 0.14582902], [ 0.14788358], \ [0.15002786], [ 0.1523993 ], [ 0.154785 ], [ 0.15717504], [0.15968754], [ 0.16216067], [ 0.1646967 ], [ 0.1671161 ], \ [0.16968349], [ 0.17208011], [ 0.17447306], [ 0.17686855], [0.17920198], [ 0.18148378], [ 0.18375362], [ 0.18597824], \ @@ -50,218 +49,22 @@ [0.29032239], [ 0.29076937], [ 0.29149768], [ 0.29241877], [0.29296466], [ 0.29421991], [-0.07873187], [-0.13739811]]) for temp in varlist: act = np.squeeze(varlist[temp]) - cal = iota_data[temp] - perct = 100*sum(abs(act-cal)/act) - print(' '+temp+': '+str(cal[64])+' '+str(act[64])+' '+str(int(perct))+'%') - if perct > failtol: - lfail = 1 -print('==== Arrays =====') -varlist={} -varlist['R_lines']=np.array([[1.56479379,1.56548724,1.56618068,1.56687413,1.56756757,1.56826102,1.56895446,1.56964791,1.57034135,1.5710348 ,1.57172824,1.57242169, \ - 1.57311513,1.57380858,1.57450202,1.57519547,1.57588891,1.57658236,1.5772758 ,1.57796925,1.57866269,1.57935614,1.58004958,1.58074303, \ - 1.58143647,1.58212992,1.58282336,1.58351681,1.58421025,1.5849037 ,1.58559714,1.58629059,1.58698403,1.58767748,1.58837092,1.58906437, \ - 1.58975781,1.59045126,1.5911447 ,1.59183815,1.59253159,1.59322504,1.59391848,1.59461193,1.59530537,1.59599882,1.59669226,1.59738571, \ - 1.59807915,1.5987726 ,1.59946604,1.60015949,1.60085293,1.60154638,1.60223982,1.60293327,1.60362671,1.60432016,1.6050136 ,1.60570705, \ - 1.60640049,1.60709394,1.60778738,1.60848083,1.60917427,1.60986772,1.61056116,1.61125461,1.61194805,1.6126415 ,1.61333494,1.61402839, \ - 1.61472183,1.61541528,1.61610872,1.61680217,1.61749561,1.61818906,1.6188825 ,1.61957595,1.62026939,1.62096284,1.62165628,1.62234973, \ - 1.62304317,1.62373662,1.62443006,1.62512351,1.62581695,1.6265104 ,1.62720384,1.62789729,1.62859073,1.62928418,1.62997762,1.63067107, \ - 1.63136451,1.63205796,1.6327514 ,1.63344485,1.63413829,1.63483174,1.63552518,1.63621863,1.63691207,1.63760552,1.63829896,1.63899241, \ - 1.63968585,1.6403793 ,1.64107274,1.64176619,1.64245963,1.64315308,1.64384652,1.64453997,1.64523341,1.64592686,1.6466203 ,1.64731375, \ - 1.64800719,1.64870064,1.64939408,1.65008753,1.65078097,1.65147442,1.65216786,1.65286131], \ - [1.519623 ,1.52043455,1.52124564,1.52205628,1.52286647,1.52367621,1.5244855 ,1.52529433,1.52610273,1.52691069,1.52771819,1.52852529, \ - 1.52933197,1.53013826,1.53094415,1.53174963,1.53255475,1.53335948,1.53416381,1.53496777,1.53577135,1.53657453,1.53737731,1.5381797 , \ - 1.53898168,1.53978324,1.54058441,1.54138515,1.54218549,1.54298542,1.54378496,1.54458406,1.5453828 ,1.54618113,1.5469791 ,1.54777671, \ - 1.54857394,1.54937082,1.55016732,1.55096349,1.55175932,1.55255478,1.55334988,1.55414462,1.55493901,1.55573303,1.55652668,1.55731996, \ - 1.55811285,1.55890537,1.5596975 ,1.56048926,1.56128064,1.56207168,1.56286232,1.56365263,1.56444258,1.56523219,1.56602147,1.56681042, \ - 1.56759904,1.56838733,1.56917531,1.56996297,1.5707503 ,1.57153731,1.57232396,1.57311029,1.57389628,1.57468191,1.57546719,1.57625212, \ - 1.57703669,1.57782091,1.57860479,1.57938835,1.58017155,1.58095443,1.58173699,1.58251922,1.58330116,1.58408279,1.58486412,1.58564516, \ - 1.5864259 ,1.58720635,1.5879865 ,1.58876634,1.58954586,1.59032507,1.59110396,1.59188253,1.59266075,1.59343864,1.5942162 ,1.59499346, \ - 1.59577037,1.59654698,1.59732328,1.59809927,1.59887496,1.59965036,1.60042548,1.60120033,1.60197489,1.60274919,1.60352322,1.60429697, \ - 1.60507044,1.60584362,1.60661651,1.60738909,1.60816137,1.60893335,1.60970501,1.61047635,1.61124739,1.61201812,1.61278855,1.61355869, \ - 1.61432855,1.61509812,1.61586741,1.61663644,1.61740521,1.61817372,1.61894198,1.61970999], \ - [1.31119373,1.30975236,1.30830964,1.30687529,1.30546905,1.30411376,1.30281723,1.30159503,1.30044206,1.29938743,1.29844967,1.29761775, \ - 1.29695056,1.29649436,1.29625812,1.29627424,1.29658118,1.29717818,1.29806602,1.29929191,1.30085632,1.30272127,1.30487971,1.30730142, \ - 1.30999457,1.31290261,1.31600497,1.31928328,1.32269982,1.32620453,1.32976613,1.33335348,1.33695304,1.34054833,1.3441201 ,1.34765227, \ - 1.35113432,1.35454221,1.35787436,1.36112605,1.36427033,1.36731596,1.37025872,1.37309827,1.37585234,1.37851806,1.38108829,1.38358221, \ - 1.3859596 ,1.38826008,1.39047959,1.39260427,1.39463993,1.39660233,1.39848397,1.40027879,1.40201149,1.40368325,1.40528315,1.40680085, \ - 1.40823771,1.40959453,1.41088962,1.41211318,1.41327529,1.41437755,1.41542039,1.41637679,1.41724187,1.41802006,1.41869839,1.41928984, \ - 1.41980506,1.4202465 ,1.42059977,1.42085725,1.42102573,1.42111293,1.42111764,1.42102334,1.42080534,1.42046309,1.42002246,1.41947277, \ - 1.41881289,1.41804651,1.41717108,1.41619537,1.41509745,1.41387028,1.41250931,1.41101145,1.40937111,1.40759448,1.40568569,1.40363879, \ - 1.40144349,1.39909568,1.39661073,1.39400118,1.39126479,1.38837436,1.38531555,1.3821031 ,1.37873045,1.37520486,1.37152988,1.36768256, \ - 1.36367645,1.35950601,1.35512842,1.35057641,1.34589004,1.34100651,1.3358637 ,1.33045164,1.32470368,1.31867392,1.31242068,1.30583853, \ - 1.29893319,1.29159072,1.28359424,1.27501358,1.26570903,1.25558547,1.24464655,1.23273304], \ - [1.56479379,1.56512509,1.56541734,1.56590427,1.56702142,1.56826089,1.56742059,1.56237668,1.55549269,1.55351789,1.55698238,1.55619012, \ - 1.54708889,1.54444855,1.55885552,1.57387487,1.5705082 ,1.54805701,1.5284618 ,1.53434568,1.54990709,1.54508672,1.5218876 ,1.51531587, \ - 1.53849017,1.57146093,1.58251401,1.56360933,1.52495365,1.49489701,1.49908751,1.52749968,1.54410047,1.52827096,1.49310589,1.47369702, \ - 1.49138163,1.53315119,1.57226481,1.59108979,1.58362406,1.55025393,1.50274918,1.46048431,1.44385084,1.46012938,1.49741151,1.52910561, \ - 1.53226983,1.50262662,1.45916879,1.42597759,1.41953625,1.44327197,1.48643671,1.53479752,1.57470279,1.59896613,1.6037444 ,1.58743454, \ - 1.55308081,1.50779294,1.45507229,1.40916941,1.38016848,1.37549933,1.39868832,1.43933028,1.47036062,1.5032115 ,1.52273937,1.50989049, \ - 1.47227097,1.420294 ,1.3745178 ,1.34515215,1.33728836,1.35049705,1.38634205,1.43123745,1.48437452,1.52912936,1.57131092,1.60264214, \ - 1.62067745,1.62201575,1.61099427,1.58279569,1.5425112 ,1.4919418 ,1.43581947,1.3837689 ,1.33204031,1.29318216,1.27585363,1.27831704, \ - 1.30830403,1.37132186,1.44074324,1.47975393,1.50413496,1.50351103,1.47245031,1.41579353,1.35242624,1.29043415,1.25221418,1.22844275, \ - 1.23081665,1.25642846,1.3098978 ,1.37284102,1.44525203,1.52845014,1.56053881,1.58544456,1.63063578,1.64580752,1.6388123 ,1.61342184, \ - 1.5645295 ,1.53307117,1.46197017,1.34730229,1.30972083,1.23106748,1.16042066,1.48825615], \ - [1.56479401,1.56413036,1.56383213,1.56656545,1.56160981,1.56825037,1.55975439,1.55785742,1.55929387,1.558684 ,1.55801377,1.55733304, \ - 1.55583153,1.5531361 ,1.54575333,1.54261174,1.53403754,1.53122883,1.52833474,1.52549615,1.52536076,1.53261897,1.54339847,1.54953304, \ - 1.51023203,1.50826227,1.551126 ,1.58275444,1.52199047,1.50972852,1.50015522,1.51122154,1.58026853,1.48020388,1.53026624,1.53064479, \ - 1.54424555,1.52818304,1.46396724,1.53033525,1.53847023,1.52074664,1.46175802,1.47322856,1.58536634,1.53206436,1.55921223,1.4459823 , \ - 1.46457102,1.44185646,1.52486342,1.44512327,1.41687014,1.45552882,1.41047687,1.42349053,1.43180457,1.40628818,1.4860768 ,1.46029262, \ - 1.59961281,1.49757274,1.52903489,1.37988995,1.37683233,1.53648259,1.50676709,1.44269994,1.47835715,1.51567323,1.60398044,1.3753557 , \ - 1.35111579,1.56953887,1.48951392,1.41612782,1.49480111,1.51815733,1.47831642,1.42854595,1.4984556 ,1.32021978,1.47317011,1.51492128, \ - 1.43178222,1.46631477,1.43129997,1.30756693,1.59334265,1.37119065,1.29220263,1.60100421,1.28183269,1.41588301,1.48429885,1.49300051, \ - 1.30784706,1.62593264,1.26022129,1.40494464,1.49033833,1.49676576,1.48248822,1.26408252,1.63029982,1.33114739,1.25187624,1.63745096, \ - 1.36619037,1.50061522,1.43106733,1.42677742,1.49614556,1.63212405,1.62085688,1.61804228,1.29741162,1.61972056,1.19070798,1.34745784, \ - 1.6415503 ,1.45213051,1.46853344,1.41597709,1.61583772,1.38027756,1.33104693,0. ], \ - [1.56479358,1.56522884,1.56344268,1.56573785,1.56261645,1.56822054,1.56061182,1.55809786,1.56976262,1.57103368,1.57164367,1.57215426, \ - 1.5690399 ,1.56044525,1.54138553,1.53759274,1.5459057 ,1.54391643,1.54136202,1.53870432,1.52586287,1.52332538,1.55487006,1.58021452, \ - 1.52922362,1.54801922,1.5054205 ,1.58035819,1.51610991,1.4942783 ,1.49591925,1.51647217,1.56217453,1.52515342,1.54682286,1.47452549, \ - 1.47426523,1.54908163,1.52355545,1.46032813,1.5894509 ,1.45570722,1.53613761,1.44954446,1.5577756 ,1.58240837,1.47625912,1.43961496, \ - 1.50053842,1.53126104,1.42440177,1.51872438,1.49343047,1.48568001,1.50124208,1.52810488,1.51388652,1.42571928,1.40882147,1.44089666, \ - 1.57857168,1.53176356,1.39754501,1.45469831,1.48820308,1.39883434,1.56285211,1.37174665,1.37674888,1.5967084 ,1.57827966,1.35456646, \ - 1.48252081,1.45299953,1.54727535,1.41776157,1.33725303,1.61617248,1.32989613,1.37599589,1.57803594,1.43040108,1.3179744 ,1.6191686 , \ - 1.33875206,1.30796996,1.45031801,1.49877501,1.50433404,1.34263181,1.35885054,1.53082911,1.40681061,1.42248655,1.27896016,1.2758296 , \ - 1.49698301,1.58236488,1.31954505,1.42530176,1.26204008,1.26425714,1.58397585,1.50073947,1.60085185,1.30590164,1.2521223 ,1.63475008, \ - 1.30219243,1.6293574 ,1.22288768,1.22985515,1.63690376,1.58266029,1.55910886,1.56682895,1.26492166,1.55059536,1.35032953,1.35952491, \ - 1.60013364,1.18119429,1.57376368,1.18177535,1.50280208,1.53674062,0. ,0. ]]) -varlist['Z_lines']=np.array([[4.03047683e-07,3.99874080e-07,3.96700476e-07,3.93526872e-07,3.90353268e-07,3.87179664e-07,3.84006061e-07,3.80832457e-07, \ - 3.77658853e-07,3.74485249e-07,3.71311645e-07,3.68138042e-07,3.64964438e-07,3.61790834e-07,3.58617230e-07,3.55443626e-07, \ - 3.52270023e-07,3.49096419e-07,3.45922815e-07,3.42749211e-07,3.39575607e-07,3.36402003e-07,3.33228400e-07,3.30054796e-07, \ - 3.26881192e-07,3.23707588e-07,3.20533984e-07,3.17360381e-07,3.14186777e-07,3.11013173e-07,3.07839569e-07,3.04665965e-07, \ - 3.01492362e-07,2.98318758e-07,2.95145154e-07,2.91971550e-07,2.88797946e-07,2.85624343e-07,2.82450739e-07,2.79277135e-07, \ - 2.76103531e-07,2.72929927e-07,2.69756324e-07,2.66582720e-07,2.63409116e-07,2.60235512e-07,2.57061908e-07,2.53888305e-07, \ - 2.50714701e-07,2.47541097e-07,2.44367493e-07,2.41193889e-07,2.38020285e-07,2.34846682e-07,2.31673078e-07,2.28499474e-07, \ - 2.25325870e-07,2.22152266e-07,2.18978663e-07,2.15805059e-07,2.12631455e-07,2.09457851e-07,2.06284247e-07,2.03110644e-07, \ - 1.99937040e-07,1.96763436e-07,1.93589832e-07,1.90416228e-07,1.87242625e-07,1.84069021e-07,1.80895417e-07,1.77721813e-07, \ - 1.74548209e-07,1.71374606e-07,1.68201002e-07,1.65027398e-07,1.61853794e-07,1.58680190e-07,1.55506587e-07,1.52332983e-07, \ - 1.49159379e-07,1.45985775e-07,1.42812171e-07,1.39638567e-07,1.36464964e-07,1.33291360e-07,1.30117756e-07,1.26944152e-07, \ - 1.23770548e-07,1.20596945e-07,1.17423341e-07,1.14249737e-07,1.11076133e-07,1.07902529e-07,1.04728926e-07,1.01555322e-07, \ - 9.83817180e-08,9.52081142e-08,9.20345104e-08,8.88609066e-08,8.56873028e-08,8.25136990e-08,7.93400952e-08,7.61664914e-08, \ - 7.29928875e-08,6.98192837e-08,6.66456799e-08,6.34720761e-08,6.02984723e-08,5.71248685e-08,5.39512647e-08,5.07776609e-08, \ - 4.76040571e-08,4.44304533e-08,4.12568495e-08,3.80832457e-08,3.49096419e-08,3.17360381e-08,2.85624343e-08,2.53888305e-08, \ - 2.22152266e-08,1.90416228e-08,1.58680190e-08,1.26944152e-08,9.52081142e-09,6.34720761e-09,3.17360381e-09,0.00000000e+00], \ - [0.05764529,0.05757418,0.057503 ,0.05743174,0.05736042,0.05728902,0.05721756,0.05714604,0.05707446,0.0570028 ,0.05693106,0.05685926, \ - 0.05678737,0.0567154 ,0.05664335,0.05657123,0.05649903,0.05642675,0.0563544 ,0.05628197,0.05620948,0.05613692,0.05606429,0.0559916 , \ - 0.05591885,0.05584604,0.05577318,0.05570027,0.0556273 ,0.05555427,0.0554812 ,0.05540807,0.05533488,0.05526163,0.05518832,0.05511495, \ - 0.05504151,0.05496802,0.05489446,0.05482083,0.05474715,0.05467341,0.05459961,0.05452576,0.05445185,0.0543779 ,0.0543039 ,0.05422986, \ - 0.05415577,0.05408164,0.05400746,0.05393324,0.05385898,0.05378467,0.05371032,0.05363592,0.05356147,0.05348698,0.05341244,0.05333785, \ - 0.05326321,0.05318853,0.05311379,0.05303902,0.05296419,0.05288933,0.05281442,0.05273946,0.05266447,0.05258944,0.05251437,0.05243926, \ - 0.05236411,0.05228893,0.05221372,0.05213847,0.05206319,0.05198787,0.05191251,0.05183712,0.05176169,0.05168623,0.05161074,0.05153521, \ - 0.05145964,0.05138403,0.05130839,0.0512327 ,0.05115698,0.05108122,0.05100543,0.0509296 ,0.05085374,0.05077785,0.05070193,0.05062597, \ - 0.05054999,0.05047398,0.05039795,0.05032188,0.05024579,0.05016967,0.05009353,0.05001736,0.04994117,0.04986495,0.0497887 ,0.04971241, \ - 0.0496361 ,0.04955975,0.04948336,0.04940694,0.04933049,0.04925401,0.0491775 ,0.04910096,0.0490244 ,0.04894781,0.0488712 ,0.04879457, \ - 0.04871791,0.04864123,0.04856452,0.0484878 ,0.04841106,0.0483343 ,0.04825752,0.04818072], \ - [ 6.72736994e-07,-2.84962781e-03,-5.76868549e-03,-8.83055713e-03,-1.22071971e-02,-1.59643229e-02,-2.02036205e-02,-2.48246649e-02, \ - -2.98023196e-02,-3.50023396e-02,-4.04588828e-02,-4.60373349e-02,-5.16779843e-02,-5.72770851e-02,-6.27706087e-02,-6.81221454e-02, \ - -7.31914936e-02,-7.79370112e-02,-8.23694439e-02,-8.63909752e-02,-8.99734788e-02,-9.31472022e-02,-9.57963262e-02,-9.79607953e-02, \ - -9.96450328e-02,-1.00887124e-01,-1.01654199e-01,-1.02000542e-01,-1.01890154e-01,-1.01412835e-01,-1.00532171e-01,-9.93028580e-02, \ - -9.77539900e-02,-9.59169334e-02,-9.38006334e-02,-9.13905912e-02,-8.87549012e-02,-8.58830127e-02,-8.27943451e-02,-7.95253054e-02, \ - -7.60936138e-02,-7.25268143e-02,-6.88418320e-02,-6.50336881e-02,-6.11065487e-02,-5.70692302e-02,-5.29381476e-02,-4.87151071e-02, \ - -4.43970135e-02,-3.99839026e-02,-3.54950759e-02,-3.09595253e-02,-2.63928675e-02,-2.18092602e-02,-1.72108104e-02,-1.25895960e-02, \ - -7.92943904e-03,-3.23617559e-03, 1.47727993e-03, 6.22572364e-03, 1.09909213e-02, 1.57598270e-02, 2.05318653e-02, 2.52976845e-02, \ - 3.00638391e-02, 3.48206408e-02, 3.95848365e-02, 4.43673449e-02, 4.91729394e-02, 5.39775301e-02, 5.87556417e-02, 6.35108736e-02, \ - 6.82755244e-02, 7.30347138e-02, 7.77793681e-02, 8.25073400e-02, 8.72306220e-02, 9.19608484e-02, 9.66991436e-02, 1.01441572e-01, \ - 1.06153815e-01, 1.10843623e-01, 1.15551885e-01, 1.20225746e-01, 1.24891782e-01, 1.29541020e-01, 1.34167822e-01, 1.38812172e-01, \ - 1.43426784e-01, 1.48001041e-01, 1.52537530e-01, 1.57005557e-01, 1.61440564e-01, 1.65827955e-01, 1.70136201e-01, 1.74407018e-01, \ - 1.78687531e-01, 1.82946136e-01, 1.87120623e-01, 1.91228849e-01, 1.95263277e-01, 1.99259152e-01, 2.03250012e-01, 2.07187214e-01, \ - 2.11079105e-01, 2.14904072e-01, 2.18646479e-01, 2.22321515e-01, 2.25923582e-01, 2.29490633e-01, 2.33057461e-01, 2.36572600e-01, \ - 2.39995539e-01, 2.43385532e-01, 2.46787024e-01, 2.50227053e-01, 2.53743466e-01, 2.57269393e-01, 2.60744844e-01, 2.64243944e-01, \ - 2.67750859e-01, 2.71333999e-01, 2.75095352e-01, 2.78965527e-01, 2.83039583e-01, 2.87325943e-01, 2.91760042e-01, 2.96353039e-01], \ - [ 4.28252412e-06,-1.11223182e-02,-2.04469294e-02,-2.58837736e-02,-2.09079110e-02,-3.19984285e-04, 3.72308894e-02, 7.97151975e-02, \ - 1.06638132e-01, 9.60152422e-02, 4.02419809e-02,-4.24205483e-02,-1.24897800e-01,-1.60891291e-01,-1.26909009e-01,-3.76928483e-02, \ - 7.68696258e-02, 1.70678503e-01, 2.06128278e-01, 1.59222789e-01, 4.68412804e-02,-8.83583369e-02,-2.01283157e-01,-2.46581101e-01, \ - -2.13408230e-01,-1.11011295e-01, 1.90696458e-02, 1.51078199e-01, 2.49946070e-01, 2.87428342e-01, 2.51267964e-01, 1.48461304e-01, \ - 7.24693416e-03,-1.38908315e-01,-2.56163172e-01,-3.18742096e-01,-3.16185901e-01,-2.54018709e-01,-1.50715448e-01,-3.02552393e-02, \ - 1.04491803e-01, 2.24469061e-01, 3.14399311e-01, 3.61697642e-01, 3.60614553e-01, 3.11075888e-01, 2.16705481e-01, 8.68920402e-02, \ - -5.52052132e-02,-1.94998854e-01,-3.02222180e-01,-3.72084643e-01,-4.04565969e-01,-3.98597849e-01,-3.57034901e-01,-2.84326012e-01, \ - -1.89976263e-01,-8.29165861e-02, 4.18673898e-02, 1.52591738e-01, 2.55646851e-01, 3.39045150e-01, 4.04240092e-01, 4.41527672e-01, \ - 4.51219958e-01, 4.34517269e-01, 3.85885089e-01, 3.12604010e-01, 2.48490321e-01, 1.53754189e-01, 1.34031839e-02,-1.20354545e-01, \ - -2.37848543e-01,-3.38798275e-01,-4.10519736e-01,-4.58845857e-01,-4.85940671e-01,-4.94454612e-01,-4.81367113e-01,-4.50708737e-01, \ - -3.97654037e-01,-3.35642103e-01,-2.54679198e-01,-1.60895486e-01,-5.59734058e-02, 4.86021683e-02, 1.32425131e-01, 2.35253470e-01, \ - 3.23839624e-01, 3.99721757e-01, 4.60878533e-01, 5.01493266e-01, 5.28331584e-01, 5.39602244e-01, 5.36088300e-01, 5.17478644e-01, \ - 4.65587116e-01, 3.80910770e-01, 2.71572774e-01, 1.78157682e-01, 6.20970178e-02,-6.39831810e-02,-1.94994474e-01,-3.10643489e-01, \ - -3.99139704e-01,-4.72856862e-01,-5.19034690e-01,-5.56169990e-01,-5.68924037e-01,-5.74959289e-01,-5.62859612e-01,-5.32299035e-01, \ - -4.77202149e-01,-3.83171117e-01,-3.31322666e-01,-2.80002372e-01,-1.38016910e-01,-1.44583543e-02, 9.93901226e-02, 2.11767295e-01, \ - 3.33661806e-01, 3.85184627e-01, 4.69159034e-01, 5.59645402e-01, 5.78716615e-01, 5.95909345e-01, 5.92584354e-01, 8.20628627e-02], \ - [ 5.08511687e-06,-5.18601845e-03,-2.71874568e-02,-1.49004189e-02, 3.75337909e-02,-3.05695948e-03,-8.18311497e-02,-6.42346300e-02, \ - -1.06059113e-02,-4.12353820e-04, 3.91836009e-03, 7.79434206e-03,-3.58322375e-02,-6.52920622e-02,-1.20261984e-01,-1.34894930e-01, \ - -1.82388995e-01,-1.90088072e-01,-1.97806528e-01,-2.04670256e-01,-1.96580829e-01,-1.59079896e-01,-9.57142625e-02, 1.28135716e-02, \ - 2.41387731e-01, 2.61043530e-01, 1.87762552e-01,-3.01823499e-02,-2.54942859e-01,-2.19898649e-01, 2.48019414e-01, 2.78934202e-01, \ - -8.96909078e-02,-3.05731526e-01, 1.26203462e-01, 2.54815653e-01,-2.28258055e-01,-1.26926487e-01, 3.37802327e-01,-2.63475817e-01, \ - -3.36383035e-02, 2.84635227e-01,-3.57807945e-01, 2.85052545e-01,-1.10884523e-01,-7.33854854e-02, 2.12225852e-01,-3.38221546e-01, \ - 3.70372253e-01,-3.89854356e-01, 2.93586811e-01,-3.92769486e-01, 3.98631948e-01,-3.88475993e-01, 4.09573562e-01,-4.15434633e-01, \ - 4.13071837e-01,-3.95323034e-01, 3.63931728e-01,-2.83873130e-01, 9.38332413e-02, 1.87425370e-01,-3.06632120e-01, 4.36898151e-01, \ - -4.47585687e-01, 2.98232813e-01,-1.44666174e-01, 4.24574299e-01, 3.87867503e-01,-9.59319145e-02,-1.09106180e-01, 4.15299923e-01, \ - -4.73605808e-01, 2.41565763e-01, 1.89039874e-01,-4.56958352e-01, 3.78836594e-01, 3.62733997e-02,-4.02090027e-01, 4.52994531e-01, \ - -1.47685023e-01,-4.98232345e-01, 4.13099564e-01, 3.91603257e-02,-4.56877809e-01, 4.24707322e-01, 3.03308563e-01,-5.23400853e-01, \ - 2.06899469e-01, 3.92526094e-01,-5.07169276e-01,-1.88273585e-01, 5.26303731e-01,-3.21935967e-01,-4.14574812e-01, 4.04762501e-01, \ - -4.65013423e-01, 9.59770968e-02, 5.29444792e-01,-3.31332478e-01,-4.16773720e-01, 4.09790959e-01, 1.64738647e-01,-5.63267705e-01, \ - 9.49820549e-02, 4.24072142e-01,-5.19450274e-01,-4.92980735e-02, 5.32835732e-01,-5.60843145e-02,-4.87962290e-01, 4.92721466e-01, \ - 8.11604675e-02, 1.22083720e-01, 1.75058535e-01, 1.83656517e-01,-4.50339878e-01,-1.86214657e-01, 5.83048268e-01,-3.90326004e-01, \ - -8.88634594e-02, 4.78117857e-01, 1.82812870e-01,-5.11312786e-01, 2.10275451e-01, 3.46435604e-01,-5.80003734e-01, 0.00000000e+00], \ - [-2.03407063e-07, 9.60087266e-03, 1.46919747e-02,-2.78704934e-02,-5.55028168e-02,-5.92109910e-03,-1.24511765e-02, 9.41906293e-02, \ - 2.27909815e-02, 1.87656902e-04,-9.12035237e-03,-1.62467444e-02, 6.53975432e-02, 1.16805283e-01, 1.71053299e-01, 1.79979657e-01, \ - 1.08001562e-01, 1.16067532e-01, 1.26764868e-01, 1.36994995e-01, 1.94126925e-01, 2.30159335e-01, 1.66123946e-01,-2.53003130e-02, \ - -1.63386189e-01,-2.26404850e-02, 2.68044668e-01,-6.11721969e-02,-2.01202243e-01, 2.86861338e-01,-2.62577552e-01, 1.91316576e-01, \ - -1.69854376e-01, 1.52631309e-01,-2.17737552e-01, 3.10144962e-01,-3.29143295e-01, 2.18885407e-01,-1.44743503e-01,-3.38656382e-01, \ - 6.15680277e-02, 3.37041044e-01,-5.05661979e-02,-3.64623658e-01,-2.11671324e-01, 1.29588555e-01, 3.54664024e-01, 3.53801633e-01, \ - 2.03480813e-01,-5.96668208e-02, 3.90970857e-01,-1.31095023e-01,-2.16361596e-01,-2.35210363e-01,-1.89355430e-01,-5.73606645e-02, \ - 1.39410651e-01, 3.55571038e-01, 3.85974835e-01, 4.12115551e-01, 1.87399880e-01,-3.00017074e-01,-4.44116245e-01,-2.89291715e-01, \ - 2.09431852e-01, 4.51064041e-01, 2.44277232e-01, 4.28041099e-01, 4.21399855e-01, 1.42027194e-01,-2.11577705e-01,-4.58573270e-01, \ - 2.12016138e-01, 4.22479925e-01,-2.92376603e-01,-3.40227074e-01, 4.85567522e-01,-5.11849105e-02,-4.82549097e-01, 3.99548130e-01, \ - 2.33824827e-01, 3.11405650e-01, 4.88339782e-01,-6.44709662e-02,-4.45271793e-01, 4.95443752e-01,-4.42170248e-01, 1.32184830e-01, \ - 3.82405071e-01,-5.19814894e-01, 4.08079191e-01,-3.47692305e-01,-3.37418486e-01, 4.76023294e-01,-5.39411589e-01, 5.42032144e-01, \ - -1.17333356e-01, 2.56690863e-01,-4.47777196e-01, 4.80841658e-01,-5.54976623e-01, 5.58443384e-01,-2.62070522e-01, 7.86469035e-02, \ - 2.20666787e-01,-5.58207869e-01, 5.19196801e-01,-7.71705302e-02, 4.55461139e-01, 1.22176472e-01,-5.51538580e-01, 5.38195050e-01, \ - -8.73504099e-02, 2.85537960e-01, 3.33909562e-01, 3.20953898e-01, 5.83042033e-01,-3.53289078e-01,-3.87760803e-01, 5.48841408e-01, \ - -2.53663131e-01, 5.79632439e-01,-3.17872913e-01,-5.73249692e-01, 4.26543187e-01, 3.85191670e-01, 0.00000000e+00, 0.00000000e+00]]) -for temp in varlist: - act = varlist[temp][0][0:125] - cal = data[temp][0][0:125] - s = str(0) - perct = 100*sum(abs((act-cal)/act)) - print(' '+temp+'['+s+',:]: '+str(cal[64])+' '+str(act[64])+' '+str(int(perct))+'%') - if perct > failtol: - lfail = 1 - act = varlist[temp][1][0:125] - cal = data[temp][1][0:125] - s = str(1) - perct = 100*sum(abs((act-cal)/act)) - print(' '+temp+'['+s+',:]: '+str(cal[64])+' '+str(act[64])+' '+str(int(perct))+'%') - if perct > failtol: - lfail = 1 - act = varlist[temp][2][0:125] - cal = data[temp][100][0:125] - s = str(100) - perct = 100*sum(abs((act-cal)/act)) - print(' '+temp+'['+s+',:]: '+str(cal[64])+' '+str(act[64])+' '+str(int(perct))+'%') - if perct > failtol: - lfail = 1 - act = varlist[temp][3][0:125] - cal = data[temp][1000][0:125] - s = str(1000) - perct = 100*sum(abs((act-cal)/act)) - print(' '+temp+'['+s+',:]: '+str(cal[64])+' '+str(act[64])+' '+str(int(perct))+'%') - if perct > failtol: - lfail = 1 - act = varlist[temp][4][0:125] - cal = data[temp][10000][0:125] - s = str(10000) - perct = 100*sum(abs((act-cal)/act)) - print(' '+temp+'['+s+',:]: '+str(cal[64])+' '+str(act[64])+' '+str(int(perct))+'%') - if perct > failtol: - lfail = 1 - act = varlist[temp][5][0:125] - cal = data[temp][20000][0:125] - s = str(20000) - perct = 100*sum(abs((act-cal)/act)) - print(' '+temp+'['+s+',:]: '+str(cal[64])+' '+str(act[64])+' '+str(int(perct))+'%') - if perct > failtol: - lfail = 1 + cal = data[temp] + cal = np.where(act==0,0,cal) + div = np.where(act==0,1,act) + perct = 100*sum(abs(act-cal)/div) + print(f' Quantity: {temp} -- CODE -- REF. -- %') + for i in range(len(act)): + perct = 100*abs(act[i]-cal[i])/div[i] + print(f' {i} {cal[i]:7.6f} {act[i]:7.6f} {round(perct)}') + if perct > failtol: + lfail = 1 print('=================') if (lfail): print(' STATUS: FAIL!!!!!') + sys.exit(-1) else: print(' STATUS: PASS') + sys.exit(0) -sys.exit(0) diff --git a/BNORM/Sources/bfield_n.f b/BNORM/Sources/bfield_n.f index 0e355ba59..c57de8fe7 100644 --- a/BNORM/Sources/bfield_n.f +++ b/BNORM/Sources/bfield_n.f @@ -37,7 +37,7 @@ program bfield_n ! ! NOTE: nescin has been modified from original format: np added to front end ! - nu=256; nv=256; mf=24; nf=14; md=24; nd=20; + nu=256; nv=256; mf=24; nf=15; md=24; nd=22; ! nu=64; nv=64; mf=12; nf=12; md=18; nd=18; ! diff --git a/BOOTSJ/Sources/datain.f~ b/BOOTSJ/Sources/datain.f~ deleted file mode 100644 index 261cb4e95..000000000 --- a/BOOTSJ/Sources/datain.f~ +++ /dev/null @@ -1,262 +0,0 @@ - - subroutine datain(extension, iunit_in, iunit, ijbs, ians) -c-- -c read and initialize data for BOOTSJ -c-- -C----------------------------------------------- -C M o d u l e s -C----------------------------------------------- - use parambs - use vmec0 - use read_boozer_mod -C use read_namelist_mod - use bootsj_input - implicit none -C----------------------------------------------- -C D u m m y A r g u m e n t s -C----------------------------------------------- - integer :: iunit, ijbs, ians, iunit_in - character*(*) :: extension -C----------------------------------------------- -C L o c a l P a r a m e t e r s -C----------------------------------------------- - real(rprec), parameter :: one = 1, zero = 0 -C----------------------------------------------- -C L o c a l V a r i a b l e s -C----------------------------------------------- - integer :: i, n, m, j, i1, ntheta_min, nzeta_min, - 1 mn, ir, idum - real(rprec) :: temp - real(rprec), dimension(:), allocatable :: work - real(rprec) :: unit, file, status, err, - 1 tempe0, tempi0, pres10, pres0, a, a1, dum - - interface read_namelist - subroutine read_namelist(iunit, io_stat, lc_name) - use vmec_input - use vmec_seq - use bootsj_input - use optim_params - integer iunit, io_stat - character*(*) :: lc_name - end subroutine read_namelist - end interface -C----------------------------------------------- -! -! Read in boozer |B|, iota, phip, pres AND allocate needed arrays -! - call read_boozer(extension) - - jlist = 0 - read (iunit_in, *,iostat=idum) jlist - IF (jlist(1) == 1) jlist(1:) = jlist(2:) - if (idum .gt. 0) stop ' Error reading bootsj input file in DATAIN' - - close (iunit_in) - -! -! -!- Give default values of control data otherwise read from the file 'bootin' -! -! nrho is an obsolete variable that is no longer used. It is set to ns-1 -! where ns is the number of whole mesh points used in vemc. -! -! nrho is an obsolete variable that is no longer used. It is set to ns-1 -! where ns is the number of whole mesh points used in vemc. -! - nrho = 30 !number of rho values to use - mbuse = 6 !number of m (poloidal) terms in B field. - nbuse = 4 !number of nzetah (toroidal) terms in B field. - zeff1 = 1.0_dp !effective ion charge - dens0 = 0.3_dp !central electron density in 10**20 m-3 - teti = 2.0_dp !ratio of Te/Ti for electron to ion - !temperature profiles - tempres = -one !tempe1(i)=pres(ir)**tempres - !if(tempres.eq.-1.0_dp) then - !tempe1(i)=sqrt(pres(i)) - damp = -0.01_dp !superceded by damp_bs - damp_bs = -0.01_dp !damping factor for resonances - isymm0 = 0 !if ne.0 then force a symmetric-device calculation, - tempe1 = one !1 keV default temperature - tempi1 = zero - ate = zero - ati = zero - ate(0) = -one - ati(0) = -one -! -!- Read control data -! - call read_namelist (iunit, i, 'bootin') - if (i .ne. 0 ) stop 'Error reading bootin namelist' - -! If the new damping variable is not read in, set to to the value this gives -! an unchanged damping factor, namely damp_bs**2 = damp. If, in addition, -! damp is not read in, then set damp_bs = 0.001 - - if(damp_bs .lt. zero) then !in this case no damp_bs was read in - if(damp .gt. zero) then - damp_bs = sqrt(damp) - else - damp_bs = 0.001_dp !in this case no damp was read in - endif - endif - teti = abs(teti) - -! -! CHECK DIMENSION SIZE CONSISTENCY -! - if(nboz_b .lt. nbuse) then - if (lscreen) write(*,*) 'nbuse > nbos_b, nbuse = nboz_b' - nbuse = nboz_b - endif - if(mboz_b .lt. mbuse) then - if (lscreen) write(*,*) 'mbuse > mbos_b, mbuse = mboz_b' - mbuse = mboz_b - endif - - nzeta_min = 2*nbuse + 1 - ntheta_min = 2*mbuse + 1 - - do i = 0, 6 - nzetah = 4*2**i - if(nzetah .gt. nzeta_min) exit - nzetah = 2*2**i * 3 - if(nzetah .gt. nzeta_min) exit - enddo - - do i = 0, 6 - nthetah = 4*2**i - if(nthetah .gt. ntheta_min) exit - nthetah = 2*2**i * 3 - if(nthetah .gt. ntheta_min) exit - enddo - - if(lscreen) print *, 'mbuse = ',mbuse,'nbuse = ', - 1 nbuse,'nthetah = ',nthetah, ' nzetah = ',nzetah - - 90 format(5e16.8) - -! convert bmn's to amnfit's (positive m's only to positive n's only) - - amnfit = zero - - lsurf = .false. - status = tiny(a1) - do ir = 1, irup - do mn = 1,mnboz_b - m = ixm_b(mn) - n = ixn_b(mn)/nfp_b - if (m .gt. mboz_b) stop 'boozmn indexing conflict, m' - if (abs(n) .gt. nboz_b) stop 'boozmn indexing conflict, n' - if (n.lt.0) then - m = -m - n = -n - end if - if (m.eq.0 .and. n.eq.0 .and. bmnc_b(mn,ir).gt.status) - 1 lsurf(ir) = .true. - amnfit(ir,m,n) = bmnc_b(mn,ir+1) !!2nd half grid == 1st grid pt. here - end do - end do - - call read_boozer_deallocate - - zeff1 = max(one,zeff1) -c setup s grid. A nonuniform mesh is allowed. - - psimax = maxval(abs(flux)) - -c we need to keep the sign of psimax - if(flux(irup) .lt. zero) psimax = -psimax - -c first normalize the mesh to 1 -c and then shift from the full to half mesh with the first point on 1, not 2 -c also need to calulate the deltas for differencing on the vmec grid -c special values at the ends will be calculated in bongrid - - do ir = 1, irup - rhoar(ir) = 0.5_dp*(flux(ir) + flux(ir+1))/psimax - d_rho(ir) = (flux(ir+1) - flux(ir))/psimax - end do - -c write (ijbs, 130) irup, psimax -c 130 format(' Last flux surface used is number ',i2,' with PSIMAX =',1p -c 1 e11.4,' WB') -c -c- Switch sign of q, if desired. -c - if (iotasign .lt. 0) then - qsafety(:irup) = iotasign*qsafety(:irup) - endif - -c -c !Boozer I/g values - aiogar(:irup) = aipsi(:irup)/(gpsi(:irup)+1.0e-36_dp) -c - call positiv (pres1, irup, 2) !to be sure that arrays are positive - call positiv (betar, irup, 2) -c evaluate electron and ion temperature profiles on vmec mesh - if (any(ate .ne. zero)) then - do ir = 1, irup - tempe1(ir) = temp(rhoar(ir), ate) - end do - end if - if (any(ati .ne. zero)) then - do ir = 1, irup - tempi1(ir) = temp(rhoar(ir), ati) - end do - end if - - tempe0 = tempe1(1) !central electron temperature in keV - tempi0 = tempi1(1) !central ion temperature in keV - pres10 = pres1(1) !central total pressure in Pa - pres0 = 1.6022E4_DP -c if the leading coefficient on either te or ti is negative, the intent is -c to assume a maximum density, and then calcuate the profiles using a -c power law given by abs(tempres). this coefficient must originally be -c be negative and ca not be greater than one. That is to say, the profiles -c are determined by ne(0) and tempres. The ratio of Te to Ti is given by -c teti. - if (tempe0.le.zero .or. tempi0.le.zero) tempres = abs(tempres) - tempres = min(one,tempres) -c - if (tempres .ge. zero) then !in that case, calculate the temperature - teti = teti + 1.E-36_dp - a = one + one/(zeff1*teti) -c !central electron temperature in keV - tempe0 = pres10/(a*pres0*dens0) - tempi0 = tempe0/teti !central ion temperature in keV - tempe1(:irup) = pres1(:irup)**tempres -c !suggested Te and Ti profiles are the same - tempi1(:irup) = tempe1(:irup) - a = tempe0/tempe1(1) - a1 = tempi0/tempi1(1) - tempe1(:irup) = tempe1(:irup)*a - tempi1(:irup) = tempi1(:irup)*a1 - endif -c - call positiv (tempe1, irup, 2) - call positiv (tempi1, irup, 2) - - dense(:irup) = pres1(:irup)/(pres0*(tempe1(:irup)+tempi1(:irup)/ - 1 zeff1)+1.E-36_dp) - allocate(work(irdim)) - call smooth1 (dense, 1, irup, work, zero) - call positiv (dense, irup, 2) - i1 = irup - 1 - a = tempe1(irup) + tempi1(irup)/zeff1 - a1 = tempe1(i1) + tempi1(i1)/zeff1 - dense(irup) = dense(i1)*a1*betar(irup)/(a*betar(i1)+1.E-36_dp) -c the above game is apparently to control the spline derivatives at the -c edge. - densi(:irup) = dense(:irup)/zeff1 - dens0 = dense(1) !central electron density - - -c -c- Echo input data to output file. -c - write (ians, bootin) - - deallocate (work) - - end subroutine datain diff --git a/DIAGNO/DIAGNO.dep b/DIAGNO/DIAGNO.dep index 4062cd02f..62de0db76 100644 --- a/DIAGNO/DIAGNO.dep +++ b/DIAGNO/DIAGNO.dep @@ -1,30 +1,21 @@ # Microsoft Developer Studio Generated Dependency File, included by VMEC2000.mak diagno.o : \ - diagno_runtime.o \ - diagno_input_mod.o - - -diagno_input_mod.o : \ - diagno_runtime.o \ - ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o \ + ../../LIBSTELL/$(LOCTYPE)/diagno_input_mod.o diagno_bench.o : \ ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o \ - diagno_runtime.o \ + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o \ ../../LIBSTELL/$(LOCTYPE)/virtual_casing_mod.o \ ../../LIBSTELL/$(LOCTYPE)/read_wout_mod.o \ ../../LIBSTELL/$(LOCTYPE)/biotsavart.o \ - ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o - - -diagno_runtime.o : \ - ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o - + ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o diagno_init_coil.o : \ - diagno_runtime.o \ + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o \ ../../LIBSTELL/$(LOCTYPE)/vmec_input.o \ ../../LIBSTELL/$(LOCTYPE)/biotsavart.o @@ -33,7 +24,7 @@ diagno_init_vmec.o : \ ../../LIBSTELL/$(LOCTYPE)/read_wout_mod.o \ ../../LIBSTELL/$(LOCTYPE)/vmec_utils.o \ ../../LIBSTELL/$(LOCTYPE)/virtual_casing_mod.o \ - diagno_runtime.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o diagno_init_spec.o : \ @@ -41,7 +32,7 @@ diagno_init_spec.o : \ ../../LIBSTELL/$(LOCTYPE)/vmec_utils.o \ ../../LIBSTELL/$(LOCTYPE)/virtual_casing_mod.o \ ../../LIBSTELL/$(LOCTYPE)/ez_hdf5.o \ - diagno_runtime.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o diagno_afield.o : \ @@ -49,7 +40,7 @@ diagno_afield.o : \ ../../LIBSTELL/$(LOCTYPE)/virtual_casing_mod.o \ ../../LIBSTELL/$(LOCTYPE)/biotsavart.o \ ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ - diagno_runtime.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o diagno_bfield.o : \ @@ -57,14 +48,14 @@ diagno_bfield.o : \ ../../LIBSTELL/$(LOCTYPE)/virtual_casing_mod.o \ ../../LIBSTELL/$(LOCTYPE)/biotsavart.o \ ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ - diagno_runtime.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o diagno_mirnov.o : \ ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o \ ../../LIBSTELL/$(LOCTYPE)/biotsavart.o \ ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ - diagno_runtime.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o diagno_bprobes.o : \ @@ -72,14 +63,14 @@ diagno_bprobes.o : \ ../../LIBSTELL/$(LOCTYPE)/virtual_casing_mod.o \ ../../LIBSTELL/$(LOCTYPE)/biotsavart.o \ ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ - diagno_runtime.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o diagno_rogowski.o : \ ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o \ ../../LIBSTELL/$(LOCTYPE)/biotsavart.o \ ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ - diagno_runtime.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o diagno_flux.o : \ @@ -87,7 +78,7 @@ diagno_flux.o : \ ../../LIBSTELL/$(LOCTYPE)/read_wout_mod.o \ ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ ../../LIBSTELL/$(LOCTYPE)/biotsavart.o \ - diagno_runtime.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o diagno_rogowski_new.o : \ @@ -95,7 +86,7 @@ diagno_rogowski_new.o : \ ../../LIBSTELL/$(LOCTYPE)/read_wout_mod.o \ ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ ../../LIBSTELL/$(LOCTYPE)/biotsavart.o \ - diagno_runtime.o + ../../LIBSTELL/$(LOCTYPE)/diagno_runtime.o dflux_bode.o : \ diff --git a/DIAGNO/ObjectList b/DIAGNO/ObjectList index d7b101d9f..6020f5b07 100644 --- a/DIAGNO/ObjectList +++ b/DIAGNO/ObjectList @@ -4,9 +4,7 @@ diagno_afield.o \ diagno_bfield.o \ db_bode.o \ dflux_midpoint.o \ -diagno_input_mod.o \ diagno_mirnov.o \ -diagno_runtime.o \ diagno_rogowski_new.o \ diagno_init_spec.o \ db_simpson.o \ diff --git a/FIELDLINES/FIELDLINES.dep b/FIELDLINES/FIELDLINES.dep index 0dda8d066..e0e15053e 100644 --- a/FIELDLINES/FIELDLINES.dep +++ b/FIELDLINES/FIELDLINES.dep @@ -18,6 +18,7 @@ fieldlines_write_parhdf5.o: \ fieldlines_runtime.o: \ + ../../LIBSTELL/$(LOCTYPE)/fieldlines_globals.o \ ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o @@ -37,10 +38,10 @@ fieldlines_init.o: \ ../../LIBSTELL/$(LOCTYPE)/mpi_params.o \ ../../LIBSTELL/$(LOCTYPE)/vessel_mod.o \ ../../LIBSTELL/$(LOCTYPE)/read_hint_mod.o \ + ../../LIBSTELL/$(LOCTYPE)/fieldlines_input_mod.o \ random.o \ fieldlines_runtime.o \ fieldlines_grid.o \ - fieldlines_input_mod.o \ fieldlines_lines.o @@ -89,15 +90,8 @@ fieldlines_gridgen.o: \ fieldlines_grid.o: \ + ../../LIBSTELL/$(LOCTYPE)/fieldlines_globals.o \ ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o - - -fieldlines_input_mod.o: \ - ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o \ - ../../LIBSTELL/$(LOCTYPE)/safe_open_mod.o \ - fieldlines_runtime.o \ - fieldlines_lines.o \ - fieldlines_grid.o fieldlines_follow.o: \ @@ -122,6 +116,7 @@ vmec_plasfield.o : \ fieldlines_lines.o: \ + ../../LIBSTELL/$(LOCTYPE)/fieldlines_globals.o \ ../../LIBSTELL/$(LOCTYPE)/stel_kinds.o diff --git a/FIELDLINES/ObjectList b/FIELDLINES/ObjectList index 80080162c..a0e916704 100644 --- a/FIELDLINES/ObjectList +++ b/FIELDLINES/ObjectList @@ -1,48 +1,47 @@ ObjectFiles = \ +backspace_out.o \ +drkhvg.o \ +faxis_nag.o \ +fblin_lsode.o \ +fblin_nag.o \ +fblin_rkh68.o \ +fblin_tanmap_lsode.o \ +fblin_tanmap_nag.o \ +fblin_tanmap_rkh68.o \ +fmap_nag.o \ +fieldlines_calc_surface_fit.o \ +fieldlines_find_axis.o \ +fieldlines_find_hc.o \ +fieldlines_follow.o \ +fieldlines_grid.o \ fieldlines_gridgen.o \ +fieldlines_init.o \ fieldlines_init_backflow.o \ +fieldlines_init_coil.o \ +fieldlines_init_eqdsk.o \ fieldlines_init_errorfield.o \ -fieldlines_init_hint.o \ fieldlines_init_fline.o \ -fieldlines_calc_surface_fit.o \ +fieldlines_init_hint.o \ +fieldlines_init_I.o \ +fieldlines_init_mgrid.o \ +fieldlines_init_nescoil.o \ +fieldlines_init_restart.o \ +fieldlines_init_subgrid.o \ fieldlines_init_vars.o \ -fieldlines_write_parhdf5.o \ -fieldlines_lines.o \ -follow_single.o \ -Map_v.o \ -random.o \ +fieldlines_init_vmec.o \ fieldlines_init_vmec_edgestart.o \ +fieldlines_lines.o \ fieldlines_main.o \ fieldlines_runtime.o \ -fieldlines_init_I.o \ -fieldlines_init_coil.o \ -fieldlines_init_vmec.o \ -fieldlines_init_eqdsk.o \ fieldlines_write.o \ -monit_find_axis.o \ -fieldlines_find_hc.o \ -backspace_out.o \ -fieldlines_follow.o \ -fieldlines_input_mod.o \ fieldlines_write_emc3.o \ -out_fieldlines_nag.o \ -fieldlines_init.o \ -fieldlines_init_restart.o \ -fblin_lsode.o \ -fblin_nag.o \ -fmap_nag.o \ -fieldlines_init_subgrid.o \ -fblin_rkh68.o \ -jacobian_tanmap_lsode.o \ -fieldlines_grid.o \ +fieldlines_write_parhdf5.o \ +follow_single.o \ jacobian_lsode.o \ +jacobian_tanmap_lsode.o \ +Map_v.o \ +monit_find_axis.o \ normal_vector.o \ -fieldlines_find_axis.o \ -fblin_tanmap_lsode.o \ -fblin_tanmap_nag.o \ -fieldlines_init_mgrid.o \ -scaleup_boundary.o \ -fblin_tanmap_rkh68.o \ -fieldlines_init_nescoil.o \ -drkhvg.o \ -faxis_nag.o +out_fieldlines_nag.o \ +random.o \ +scaleup_boundary.o diff --git a/FIELDLINES/Sources/fieldlines_grid.f90 b/FIELDLINES/Sources/fieldlines_grid.f90 index 65d35e731..256c8efdf 100644 --- a/FIELDLINES/Sources/fieldlines_grid.f90 +++ b/FIELDLINES/Sources/fieldlines_grid.f90 @@ -9,6 +9,8 @@ MODULE fieldlines_grid ! Libraries !----------------------------------------------------------------------- USE stel_kinds, ONLY: rprec + USE fieldlines_globals, ONLY: nr, nphi, nz, rmin, rmax, zmin, & + zmax, phimin, phimax, vc_adapt_tol USE EZspline_obj USE EZspline @@ -36,9 +38,7 @@ MODULE fieldlines_grid ! BZ_spl EZSpline Object for B_Z/B_PHI !----------------------------------------------------------------------- IMPLICIT NONE - INTEGER :: nr, nphi, nz - REAL(rprec) :: rmin, rmax, zmin, zmax, phimin, phimax, delta_phi,& - vc_adapt_tol,req_axis, zeq_axis, phiedge_eq, reff_eq + REAL(rprec) :: delta_phi,req_axis, zeq_axis, phiedge_eq, reff_eq INTEGER :: win_raxis, win_phiaxis, win_zaxis, win_B_R, win_B_PHI, win_B_Z, & win_MU, win_BR4D, win_BPHI4D, win_BZ4D, win_MODB4D, win_MU4D, win_PRES REAL(rprec), POINTER :: raxis(:), zaxis(:), phiaxis(:) diff --git a/FIELDLINES/Sources/fieldlines_init.f90 b/FIELDLINES/Sources/fieldlines_init.f90 index 9991f6f9d..921200a62 100644 --- a/FIELDLINES/Sources/fieldlines_init.f90 +++ b/FIELDLINES/Sources/fieldlines_init.f90 @@ -80,24 +80,24 @@ SUBROUTINE fieldlines_init IF (ierr_mpi /= MPI_SUCCESS) CALL handle_err(MPI_BARRIER_ERR,'fieldlines_init:namelist',ierr_mpi) #endif IF (lvmec) THEN - CALL read_fieldlines_input('input.' // TRIM(id_string),ier,myworkid) + CALL read_fieldlines_input('input.' // TRIM(id_string),ier) IF (lverb) WRITE(6,'(A)') ' FILE: input.' // TRIM(id_string) !IF (.not. lvac) CALL read_wout_file(TRIM(id_string),ier) ELSE IF (lpies) THEN - CALL read_fieldlines_input(TRIM(id_string) // '.in',ier,myworkid) + CALL read_fieldlines_input(TRIM(id_string) // '.in',ier) IF (lverb) WRITE(6,'(A)') ' FILE: ' // TRIM(id_string) // '.in' ELSE IF (lspec) THEN - CALL read_fieldlines_input('input.' // TRIM(id_string),ier,myworkid) + CALL read_fieldlines_input('input.' // TRIM(id_string),ier) IF (lverb) WRITE(6,'(A)') ' FILE: input.' // TRIM(id_string) ELSE IF (leqdsk) THEN - CALL read_fieldlines_input('input.' // TRIM(id_string),ier,myworkid) + CALL read_fieldlines_input('input.' // TRIM(id_string),ier) IF (lverb) WRITE(6,'(A)') ' FILE: input.' // TRIM(id_string) CALL read_gfile(eqdsk_string,ier) IF (lverb) WRITE(6,'(A)') ' G-FILE: '// TRIM(eqdsk_string) CALL get_eqdsk_grid(nr,nz,rmin,rmax,zmin,zmax) phimin = 0; phimax=pi2 ELSE IF (lhint) THEN - CALL read_fieldlines_input(TRIM(id_string)//'.input',ier,myworkid) + CALL read_fieldlines_input(TRIM(id_string)//'.input',ier) IF (lverb) WRITE(6,'(A)') ' FILE: ' // TRIM(id_string) // '.input' IF (lverb) WRITE(6,'(A)') ' MAG_FILE: ' // TRIM(id_string) // '.magslice' CALL read_hint_mag(TRIM(id_string)//'.magslice',ier) diff --git a/FIELDLINES/Sources/fieldlines_lines.f90 b/FIELDLINES/Sources/fieldlines_lines.f90 index d290b7835..17046ffc4 100644 --- a/FIELDLINES/Sources/fieldlines_lines.f90 +++ b/FIELDLINES/Sources/fieldlines_lines.f90 @@ -10,6 +10,7 @@ MODULE fieldlines_lines ! Libraries !----------------------------------------------------------------------- USE stel_kinds, ONLY: rprec + USE fieldlines_globals, ONLY: nlines !----------------------------------------------------------------------- ! Module Variables @@ -21,7 +22,7 @@ MODULE fieldlines_lines ! PHI_lines Toroidal locations along field line [radians] !----------------------------------------------------------------------- IMPLICIT NONE - INTEGER :: nlines, nsteps, myline, myldex, myend + INTEGER :: nsteps, myline, myldex, myend REAL(rprec) :: xlast,ylast,zlast ! for storing position REAL(rprec), ALLOCATABLE :: R_lines(:,:),Z_lines(:,:),PHI_lines(:,:),& diff --git a/FIELDLINES/Sources/fieldlines_runtime.f90 b/FIELDLINES/Sources/fieldlines_runtime.f90 index 205b0db8d..8d7a7431e 100644 --- a/FIELDLINES/Sources/fieldlines_runtime.f90 +++ b/FIELDLINES/Sources/fieldlines_runtime.f90 @@ -47,6 +47,10 @@ MODULE fieldlines_runtime !----------------------------------------------------------------------- USE stel_kinds, ONLY: rprec USE EZspline + USE fieldlines_globals, ONLY: MAXLINES, lerror_field, npoinc, & + dphi, follow_tol, num_hcp, delta_hc, mu, errorfield_amp, & + errorfield_phase, r_start, phi_start, z_start, phi_end, r_hc, & + z_hc, phi_hc, int_type, lmu !----------------------------------------------------------------------- ! Module Variables ! lverb Logical to control screen output @@ -119,26 +123,20 @@ MODULE fieldlines_runtime INTEGER, PARAMETER :: runtype_backflow = 329 INTEGER, PARAMETER :: runtype_gridgen = 422 - INTEGER, PARAMETER :: MAXLINES = 2**19 INTEGER, PARAMETER :: NLOCAL = 128 ! Number of local processors LOGICAL :: lverb, lvmec, lpies, lspec, lcoil, lmgrid, & - lmu, lvessel, lvac, lrestart, laxis_i, & + lvessel, lvac, lrestart, laxis_i, & ladvanced, lauto, lplasma_only, lbfield_only,& lreverse, lhitonly, lafield_only, lraw, lemc3, & - lerror_field, lwall_trans, ledge_start, lnescoil,& + lwall_trans, ledge_start, lnescoil,& lmodb, lfield_start, lhint, leqdsk, lpres - INTEGER :: nextcur, npoinc, nruntype, num_hcp, & + INTEGER :: nextcur, nruntype, & nprocs_fieldlines, line_select, ldex_default - REAL(rprec) :: mu, dphi, follow_tol, pi, pi2, mu0, delta_hc, & - iota0 - REAL(rprec), DIMENSION(20) :: errorfield_amp, errorfield_phase - REAL(rprec), DIMENSION(MAXLINES) :: r_start, phi_start, & - z_start, phi_end, & - r_hc, z_hc, phi_hc + REAL(rprec) :: pi, pi2, mu0, iota0 REAL(rprec), ALLOCATABLE :: extcur(:) CHARACTER(256) :: id_string, mgrid_string, coil_string, & - vessel_string, int_type, restart_string, & + vessel_string, restart_string, & nescoil_string, eqdsk_string REAL(rprec), PARAMETER :: FIELDLINES_VERSION = 1.80 diff --git a/LIBSTELL/LIBSTELL.dep b/LIBSTELL/LIBSTELL.dep index a7135e755..3a1660705 100644 --- a/LIBSTELL/LIBSTELL.dep +++ b/LIBSTELL/LIBSTELL.dep @@ -1,4 +1,56 @@ -# Microsoft Developer Studio Generated Dependency File, included by LIBSTELL.mak +# Microsoft Developer Studio Generated Dependency File, included by LIBSTELL.mak + +stellopt_globals.o : \ + stel_kinds.o + +stellopt_vars.o : \ + vparams.o \ + vsvd0.o \ + mpi_inc.o \ + stellopt_globals.o + +stellopt_targets.o : \ + stel_kinds.o \ + stellopt_vars.o \ + stellopt_globals.o + +stellopt_input_mod.o : \ + stel_kinds.o \ + stellopt_vars.o \ + stellopt_targets.o \ + safe_open_mod.o \ + vmec_input.o \ + mpi_params.o \ + stellopt_globals.o + +fieldlines_input_mod.o: \ + stel_kinds.o \ + safe_open_mod.o \ + mpi_params.o \ + mpi_inc.o \ + fieldlines_globals.o + +fieldlines_globals.o : \ + stel_kinds.o + +beams3d_input_mod.o: \ + stel_kinds.o \ + safe_open_mod.o \ + mpi_params.o \ + mpi_inc.o \ + beams3d_globals.o + +beams3d_globals.o : \ + stel_kinds.o + +diagno_runtime.o : \ + ezspline.o \ + stel_kinds.o + +diagno_input_mod.o : \ + diagno_runtime.o \ + safe_open_mod.o + nbcd_okano.o : @@ -1018,11 +1070,6 @@ ipsl_T.o : \ v3_utilities.o -cyl_flux.o : \ - stel_constants.o \ - stel_kinds.o - - sxrch_T.o : \ integration_path.o \ stel_constants.o \ @@ -1187,7 +1234,6 @@ gist_mod.o : \ vmec_utils.o : \ - cyl_flux.o \ read_wout_mod.o \ stel_constants.o \ stel_kinds.o diff --git a/LIBSTELL/ObjectList b/LIBSTELL/ObjectList index da53b8f1d..0ec570471 100644 --- a/LIBSTELL/ObjectList +++ b/LIBSTELL/ObjectList @@ -1,4 +1,14 @@ ObjectFiles = \ +stellopt_targets.o \ +stellopt_vars.o \ +stellopt_input_mod.o \ +stellopt_globals.o \ +fieldlines_input_mod.o \ +fieldlines_globals.o \ +diagno_input_mod.o \ +diagno_runtime.o \ +beams3d_input_mod.o \ +beams3d_globals.o \ mumaterial_mod.o \ nbcd_okano.o \ nclass_mod.o \ @@ -78,7 +88,6 @@ v3post_rfun.o \ read_pies_mod.o \ system_mod.o \ saddle_surface.o \ -cyl_flux.o \ flint_z.o \ optim_params.o \ mddc_cdf.o \ diff --git a/LIBSTELL/Sources/Modules/beams3d_globals.f90 b/LIBSTELL/Sources/Modules/beams3d_globals.f90 new file mode 100644 index 000000000..6862ffe88 --- /dev/null +++ b/LIBSTELL/Sources/Modules/beams3d_globals.f90 @@ -0,0 +1,79 @@ +!----------------------------------------------------------------------- +! Module: beams3d_globals +! Authors: S. Lazerson (samuel.lazerson@gauss-fusion.com) +! Date: 05/17/2024 +! Description: This module contains the BEAMS3D global variables +! needed by the input namelist. +!----------------------------------------------------------------------- + MODULE beams3d_globals +!----------------------------------------------------------------------- +! Libraries +!----------------------------------------------------------------------- + USE stel_kinds, ONLY: rprec + +!----------------------------------------------------------------------- +! Module Variables +!----------------------------------------------------------------------- + IMPLICIT NONE + ! Moved from beams3d_runtime + INTEGER, PARAMETER :: MAXPARTICLES = 2**18 + INTEGER, PARAMETER :: MAXBEAMS = 32 + INTEGER, PARAMETER :: MAXPROFLEN = 512 + INTEGER, PARAMETER :: NION = 4 + LOGICAL :: lverb, lcollision, lrestart_particles, ldebug, & + lfusion, lfusion_alpha, lfusion_He3, lfusion_proton, & + lfusion_tritium, lkick, lgcsim, lbeam, lbbnbi + INTEGER :: npoinc, nbeams, nparticles_start, duplicate_factor + INTEGER, DIMENSION(MAXBEAMS) :: Dex_beams + REAL(rprec) :: follow_tol, pi2, ne_scale, te_scale, ti_scale, & + zeff_scale, fusion_scale, lendt_m, te_col_min + REAL(rprec), DIMENSION(MAXBEAMS) :: Adist_beams, Asize_beams, Div_beams, E_beams, mass_beams, & + charge_beams, Zatom_beams, P_beams + REAL(rprec), DIMENSION(MAXBEAMS, 2) :: r_beams, z_beams, phi_beams + REAL(rprec), DIMENSION(MAXPROFLEN) :: TE_AUX_S, TE_AUX_F, NE_AUX_S, NE_AUX_F, TI_AUX_S, TI_AUX_F,& + POT_AUX_S, POT_AUX_F, ZEFF_AUX_S, ZEFF_AUX_F + INTEGER, DIMENSION(NION) :: NI_AUX_Z + REAL(rprec), DIMENSION(MAXPROFLEN) :: NI_AUX_S + REAL(rprec), DIMENSION(NION,MAXPROFLEN) :: NI_AUX_F + REAL(rprec), DIMENSION(NION) :: NI_AUX_M + REAL(rprec), DIMENSION(MAXPARTICLES) :: r_start_in, phi_start_in, z_start_in, vll_start_in, & + & mu_start_in, charge_in, Zatom_in, mass_in, t_end_in, & + vr_start_in, vphi_start_in, vz_start_in, weight_in + CHARACTER(256) :: id_string, int_type + + ! moved from beams3d_lines + INTEGER :: ns_prof1, ns_prof2, ns_prof3, ns_prof4, ns_prof5, nsh_prof4, nparticles + REAL(rprec) :: partvmax, plasma_Zmean, plasma_mass + + ! moved from beams3d_grid + INTEGER :: nr, nphi, nz, nte, nne, nti, nzeff, npot, nr_fida, nphi_fida, nz_fida, nenergy_fida, npitch_fida, dexionT, dexionD, dexionHe3 + REAL :: rmin_fida, rmax_fida, zmin_fida, zmax_fida, phimin_fida, phimax_fida, emin_fida, pimin_fida + REAL(rprec) :: rmin, rmax, zmin, zmax, phimin, phimax, & + vc_adapt_tol, therm_factor, B_kick_min, & + B_kick_max, E_kick, freq_kick, rho_fullorbit, & + t_fida, s_max,s_max_te, s_max_ne,s_max_zeff,s_max_ti, s_max_pot + + CONTAINS + + ! These expose the global variables through ctypes + INTEGER FUNCTION getmaxparticles() + IMPLICIT NONE + getmaxparticles = MAXPARTICLES + END FUNCTION getmaxparticles + + INTEGER FUNCTION getMAXBEAMS() + IMPLICIT NONE + getMAXBEAMS = MAXBEAMS + END FUNCTION getMAXBEAMS + + INTEGER FUNCTION getMAXPROFLEN() + IMPLICIT NONE + getMAXPROFLEN = MAXPROFLEN + END FUNCTION getMAXPROFLEN + + INTEGER FUNCTION getNION() + IMPLICIT NONE + getNION =NION + END FUNCTION getNION + + END MODULE beams3d_globals diff --git a/BEAMS3D/Sources/beams3d_input_mod.f90 b/LIBSTELL/Sources/Modules/beams3d_input_mod.f90 similarity index 83% rename from BEAMS3D/Sources/beams3d_input_mod.f90 rename to LIBSTELL/Sources/Modules/beams3d_input_mod.f90 index 547defe41..03fc8b83e 100644 --- a/BEAMS3D/Sources/beams3d_input_mod.f90 +++ b/LIBSTELL/Sources/Modules/beams3d_input_mod.f90 @@ -11,20 +11,7 @@ MODULE beams3d_input_mod ! Libraries !----------------------------------------------------------------------- USE stel_kinds, ONLY: rprec - USE beams3d_runtime - USE beams3d_lines, ONLY: nparticles, ns_prof1, ns_prof2, ns_prof3, & - ns_prof4, ns_prof5, partvmax - USE beams3d_grid, ONLY: nr, nphi, nz, rmin, rmax, zmin, zmax, & - phimin, phimax, vc_adapt_tol, nte, nne, nti,& - nzeff, npot, plasma_mass, & - plasma_Zmean, therm_factor, & - B_kick_min, B_kick_max, freq_kick, E_kick, & - rho_fullorbit, & - rmin_fida, rmax_fida, zmin_fida, zmax_fida, phimin_fida, phimax_fida, & - raxis_fida, zaxis_fida, phiaxis_fida, nr_fida, nphi_fida, nz_fida, & - nenergy_fida, npitch_fida, energy_fida, pitch_fida, t_fida, & - dexionT, dexionD,dexionHe3, & - s_max,s_max_te, s_max_ne,s_max_zeff,s_max_ti, s_max_pot + USE beams3d_globals USE safe_open_mod, ONLY: safe_open USE mpi_params USE mpi_inc @@ -112,6 +99,7 @@ MODULE beams3d_input_mod SUBROUTINE init_beams3d_input IMPLICIT NONE + pi2 = 8.0 * ATAN(1.0) nr = 101 nphi = 360 nz = 101 @@ -227,7 +215,7 @@ SUBROUTINE read_beams3d_input(filename, istat) CHARACTER(*), INTENT(in) :: filename INTEGER, INTENT(out) :: istat LOGICAL :: lexist - INTEGER :: iunit, local_master, i1 + INTEGER :: iunit, local_master, i1, ik CHARACTER(LEN=1000) :: line ! Initializations local_master = 0 @@ -240,13 +228,19 @@ SUBROUTINE read_beams3d_input(filename, istat) INQUIRE(FILE=TRIM(filename),EXIST=lexist) IF (.not.lexist) stop 'Could not find input file' CALL safe_open(iunit,istat,TRIM(filename),'old','formatted') - IF (istat /= 0) CALL handle_err(NAMELIST_READ_ERR,'beams3d_input in: '//TRIM(filename),istat) + IF (istat /= 0) THEN + WRITE(6,'(A)') 'ERROR opening file: ',TRIM(filename) + CALL FLUSH(6) + STOP + END IF READ(iunit,NML=beams3d_input,IOSTAT=istat) IF (istat /= 0) THEN + WRITE(6,'(A)') 'ERROR reading namelist BEAMS3D_INPUT from file: ',TRIM(filename) backspace(iunit) read(iunit,fmt='(A)') line write(6,'(A)') 'Invalid line in namelist: '//TRIM(line) - CALL handle_err(NAMELIST_READ_ERR,'beams3d_input in: '//TRIM(filename),istat) + CALL FLUSH(6) + STOP END IF CLOSE(iunit) END IF @@ -270,15 +264,20 @@ SUBROUTINE read_beams3d_input(filename, istat) IF (lbeam) lcollision = .true. IF (B_kick_min >=0 ) lkick = .true. nbeams = 0 - DO WHILE ((Asize_beams(nbeams+1) >= 0.0).and.(nbeams= 0.0) nbeams = nbeams + 1 END DO IF (lbbnbi) THEN nbeams = 0 - DO WHILE ((Dex_beams(nbeams+1) > 0).and.(nbeams 0) nbeams = nbeams + 1 END DO - IF (nbeams == 0) CALL handle_err(BAD_BEAMDEX_ERR,'beams3d_input in: input.'//TRIM(id_string),nbeams) + IF (nbeams == 0) THEN + WRITE(6,'(A)') 'BEAMLET beam model requested but nbeams==0' + WRITE(6,'(A)') ' Check DEX_BEAMS is set in BEAMS3D_INPUT' + CALL FLUSH(6) + STOP + END IF END IF IF (lfusion) THEN r_start_in = -1 @@ -289,54 +288,54 @@ SUBROUTINE read_beams3d_input(filename, istat) IF (lfusion_He3) nbeams = nbeams + 1 END IF nte = 0 - DO WHILE ((TE_AUX_S(nte+1) >= 0.0).and.(nte= 0.0) nte = nte+1 END DO + IF (nte > 0) s_max_te = TE_AUX_S(nte) nne = 0 - DO WHILE ((NE_AUX_S(nne+1) >= 0.0).and.(nne= 0.0) nne = nne+1 END DO + IF (nne > 0) s_max_ne = NE_AUX_S(nne) nti = 0 - DO WHILE ((TI_AUX_S(nti+1) >= 0.0).and.(nti= 0.0) nti = nti+1 END DO + IF (nti > 0) s_max_ti = NE_AUX_S(nti) nzeff = 0 - DO WHILE ((ZEFF_AUX_S(nzeff+1) >= 0.0).and.(nzeff= 0.0) nzeff = nzeff+1 END DO + IF (nzeff > 0) s_max_zeff=ZEFF_AUX_S(nzeff) npot = 0 - DO WHILE ((POT_AUX_S(npot+1) >= 0.0).and.(npot= 0.0) npot = npot+1 END DO - + IF (npot > 0) s_max_pot = POT_AUX_S(npot) ! Handle multiple ion species IF (ANY(NI_AUX_S >0)) THEN nzeff = 0 - DO WHILE ((NI_AUX_S(nzeff+1) >= 0.0).and.(nzeff= 0.0) nzeff = nzeff+1 END DO + IF (nzeff > 0) s_max_zeff=ZEFF_AUX_S(nzeff) ! Now calc Zeff(1) - DO i1 = 1, nzeff - ZEFF_AUX_S(i1) = NI_AUX_S(i1) - temp = SUM(NI_AUX_F(:,i1)*NI_AUX_Z(:)) + DO ik = 1, nzeff + ZEFF_AUX_S(ik) = NI_AUX_S(ik) + temp = SUM(NI_AUX_F(:,ik)*NI_AUX_Z(:)) IF (temp > 0) THEN - ZEFF_AUX_F(i1) = MAX(SUM(NI_AUX_F(:,i1)*NI_AUX_Z(:)*NI_AUX_Z(:))/temp,1.0) + ZEFF_AUX_F(ik) = MAX(SUM(NI_AUX_F(:,ik)*NI_AUX_Z(:)*NI_AUX_Z(:))/temp,1.0) ELSE - ZEFF_AUX_F(i1) = 1 + ZEFF_AUX_F(ik) = 1 END IF END DO plasma_mass = SUM(NI_AUX_F(:,1)*NI_AUX_M*NI_AUX_M)/(SUM(NI_AUX_F(:,1)*NI_AUX_M)) plasma_Zmean = SUM(NI_AUX_F(:,1)*NI_AUX_Z*NI_AUX_Z*plasma_mass/NI_AUX_M,DIM=1,MASK=(NI_AUX_M>1E-27))/(SUM(NI_AUX_F(:,1)*NI_AUX_Z)) ! Set indices for T and D - DO i1 = 1, NION - IF ((NI_AUX_Z(i1) == 1) .and. (NINT(NI_AUX_M(i1)*6.02214076208E+26) == 3)) dexionT = i1 - IF ((NI_AUX_Z(i1) == 1) .and. (NINT(NI_AUX_M(i1)*6.02214076208E+26) == 2)) dexionD = i1 - IF ((NI_AUX_Z(i1) == 2) .and. (NINT(NI_AUX_M(i1)*6.02214076208E+26) == 3)) dexionHe3 = i1 + DO ik = 1, NION + IF ((NI_AUX_Z(ik) == 1) .and. (NINT(NI_AUX_M(ik)*6.02214076208E+26) == 3)) dexionT = ik + IF ((NI_AUX_Z(ik) == 1) .and. (NINT(NI_AUX_M(ik)*6.02214076208E+26) == 2)) dexionD = ik + IF ((NI_AUX_Z(ik) == 2) .and. (NINT(NI_AUX_M(ik)*6.02214076208E+26) == 3)) dexionHe3 = ik END DO !WRITE(6,*) ' Tritium index: ',dexionT !WRITE(6,*) ' Deuturium index: ',dexionD @@ -349,13 +348,13 @@ SUBROUTINE read_beams3d_input(filename, istat) NI_AUX_M(1) = 3.3435837724E-27; NI_AUX_Z(1) = 1 NI_AUX_M(2) = 5.008267217094E-27; NI_AUX_Z(2) = 1 ! Now calc Zeff(1) - DO i1 = 1, nzeff - ZEFF_AUX_S(i1) = NI_AUX_S(i1) - temp = SUM(NI_AUX_F(:,i1)*NI_AUX_Z(:)) + DO ik = 1, nzeff + ZEFF_AUX_S(ik) = NI_AUX_S(ik) + temp = SUM(NI_AUX_F(:,ik)*NI_AUX_Z(:)) IF (temp > 0) THEN - ZEFF_AUX_F(i1) = MAX(SUM(NI_AUX_F(:,i1)*NI_AUX_Z(:)*NI_AUX_Z(:))/temp,1.0) + ZEFF_AUX_F(ik) = MAX(SUM(NI_AUX_F(:,ik)*NI_AUX_Z(:)*NI_AUX_Z(:))/temp,1.0) ELSE - ZEFF_AUX_F(i1) = 1 + ZEFF_AUX_F(ik) = 1 END IF END DO plasma_mass = SUM(NI_AUX_F(:,1)*NI_AUX_M*NI_AUX_M)/(SUM(NI_AUX_F(:,1)*NI_AUX_M)) @@ -385,10 +384,9 @@ SUBROUTINE read_beams3d_input(filename, istat) s_max_zeff=ZEFF_AUX_S(nzeff) nparticles = 0 - DO WHILE ((r_start_in(nparticles+1) >= 0.0).and.(nparticles= 0.0) nparticles = nparticles + 1 END DO -! END IF #if !defined(NAG) IF (int_type=='NAG') THEN @@ -407,9 +405,9 @@ SUBROUTINE read_beams3d_input(filename, istat) ! Makes sure that NPARTICLES is divisible by the number of processes ! Needed for HDF5 parallel writes. IF (lbeam .or. lfusion) THEN - i1 = nparticles_start/nprocs_beams - IF (i1*nprocs_beams .ne. nparticles_start) THEN - nparticles_start = (i1+1)*nprocs_beams + ik = nparticles_start/nprocs_beams + IF (ik*nprocs_beams .ne. nparticles_start) THEN + nparticles_start = (ik+1)*nprocs_beams END IF END IF #endif @@ -474,23 +472,42 @@ SUBROUTINE write_beams3d_namelist(iunit_out, istat) WRITE(iunit_out,outflt) 'TI_SCALE',TI_SCALE WRITE(iunit_out,outflt) 'ZEFF_SCALE',ZEFF_SCALE WRITE(iunit_out,outflt) 'THERM_FACTOR',therm_factor - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'NE_AUX_S',(ne_aux_s(n), n=1,nne) - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'NE_AUX_F',(ne_aux_f(n), n=1,nne) - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'TE_AUX_S',(te_aux_s(n), n=1,nte) - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'TE_AUX_F',(te_aux_f(n), n=1,nte) - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'TI_AUX_S',(ti_aux_s(n), n=1,nti) - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'TI_AUX_F',(ti_aux_f(n), n=1,nti) - ik = COUNT(NI_AUX_S .ge. 0) - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'NI_AUX_S',(ni_aux_s(n), n=1,ik) - DO n = 1, NION - IF (ANY(NI_AUX_F(n,:)>0)) THEN - WRITE(iunit_out,"(2X,A,'(',I1.1,',:) =',4(1X,ES22.12E3))") 'TI_AUX_F',n,(ni_aux_f(n,l), l=1,ik) - END IF - END DO - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'ZEFF_AUX_S',(zeff_aux_s(n), n=1,nzeff) - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'ZEFF_AUX_F',(zeff_aux_f(n), n=1,nzeff) - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'POT_AUX_S',(zeff_aux_s(n), n=1,npot) - WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'POT_AUX_F',(zeff_aux_f(n), n=1,npot) + ik = COUNT(ne_aux_s >= 0) + IF (ik > 0) THEN + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'NE_AUX_S',(ne_aux_s(n), n=1,ik) + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'NE_AUX_F',(ne_aux_f(n), n=1,ik) + END IF + ik = COUNT(te_aux_s >= 0) + IF (ik > 0) THEN + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'TE_AUX_S',(te_aux_s(n), n=1,ik) + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'TE_AUX_F',(te_aux_f(n), n=1,ik) + END IF + ik = COUNT(ti_aux_s >= 0) + IF (ik > 0) THEN + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'TI_AUX_S',(ti_aux_s(n), n=1,ik) + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'TI_AUX_F',(ti_aux_f(n), n=1,ik) + END IF + ik = COUNT(ni_aux_s >= 0) + IF (ik > 0) THEN + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'NI_AUX_M',(ni_aux_m(n), n=1,NION) + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,I0))") 'NI_AUX_Z',(ni_aux_z(n), n=1,NION) + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'NI_AUX_S',(ni_aux_s(n), n=1,ik) + DO n = 1, NION + IF (ANY(NI_AUX_F(n,:)>0)) THEN + WRITE(iunit_out,"(2X,A,'(',I1.1,',:) =',4(1X,ES22.12E3))") 'NI_AUX_F',n,(ni_aux_f(n,l), l=1,ik) + END IF + END DO + END IF + ik = COUNT(zeff_aux_s >= 0) + IF (ik > 0) THEN + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'ZEFF_AUX_S',(zeff_aux_s(n), n=1,ik) + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'ZEFF_AUX_F',(zeff_aux_f(n), n=1,ik) + END IF + ik = COUNT(pot_aux_s >= 0) + IF (ik > 0) THEN + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'POT_AUX_S',(pot_aux_s(n), n=1,ik) + WRITE(iunit_out,"(2X,A,1X,'=',4(1X,ES22.12E3))") 'POT_AUX_F',(pot_aux_f(n), n=1,ik) + END IF IF (lbeam) THEN DO n = 1, nbeams WRITE(iunit_out,"(A,I2.2)") '!---- BEAM #',n @@ -531,6 +548,26 @@ SUBROUTINE write_beams3d_namelist(iunit_out, istat) END SUBROUTINE write_beams3d_namelist + SUBROUTINE write_beams3d_namelist_byfile(filename) + CHARACTER(LEN=*), INTENT(in) :: filename + INTEGER :: iunit, istat + LOGICAL :: lexists + + iunit = 100 + istat = 0 + INQUIRE(FILE=TRIM(filename),exist=lexists) + IF (lexists) THEN + OPEN(unit=iunit, file=TRIM(filename), iostat=istat, status="old", position="append") + ELSE + OPEN(unit=iunit, file=TRIM(filename), iostat=istat, status="new") + END IF + IF (istat .ne. 0) RETURN + CALL write_beams3d_namelist(iunit,istat) + CLOSE(iunit) + + RETURN + END SUBROUTINE write_beams3d_namelist_byfile + SUBROUTINE BCAST_BEAMS3D_INPUT(local_master,comm,istat) USE mpi_inc IMPLICIT NONE diff --git a/LIBSTELL/Sources/Modules/bootsj_input.f b/LIBSTELL/Sources/Modules/bootsj_input.f index dab4cd6d8..995a3a4e0 100644 --- a/LIBSTELL/Sources/Modules/bootsj_input.f +++ b/LIBSTELL/Sources/Modules/bootsj_input.f @@ -37,6 +37,20 @@ SUBROUTINE read_boot_namelist (iunit, istat) READ (iunit, nml=bootin, iostat=istat) END SUBROUTINE read_boot_namelist + + SUBROUTINE read_boot_namelist_byfile (filename) + CHARACTER(LEN=*), INTENT(in) :: filename + INTEGER :: iunit, istat + + iunit = 100 + istat = 0 + OPEN(unit=iunit, file=TRIM(filename), iostat=istat) + IF (istat .ne. 0) RETURN + CALL read_boot_namelist(iunit,istat) + CLOSE(iunit) + + RETURN + END SUBROUTINE read_boot_namelist_byfile SUBROUTINE write_bootsj_input(iunit,istat) INTEGER, INTENT(in) :: iunit @@ -59,6 +73,21 @@ SUBROUTINE write_bootsj_input(iunit,istat) WRITE(iunit,'(A)') '/' END SUBROUTINE write_bootsj_input + SUBROUTINE write_boot_namelist_byfile (filename) + CHARACTER(LEN=*), INTENT(in) :: filename + INTEGER :: iunit, istat + + iunit = 100 + istat = 0 + OPEN(unit=iunit, file=TRIM(filename), iostat=istat) + IF (istat .ne. 0) RETURN + CALL FSEEK(iunit, 0, 2, istat) ! Go to end + CALL write_bootsj_input(iunit,istat) + CLOSE(iunit) + + RETURN + END SUBROUTINE write_boot_namelist_byfile + SUBROUTINE BCAST_BOOTSJ_INPUT(local_master,comm,istat) !DEC$ IF DEFINED (MPI_OPT) USE mpi diff --git a/LIBSTELL/Sources/Modules/cyl_flux.f b/LIBSTELL/Sources/Modules/cyl_flux.f deleted file mode 100644 index 133d1a5de..000000000 --- a/LIBSTELL/Sources/Modules/cyl_flux.f +++ /dev/null @@ -1,669 +0,0 @@ - MODULE cyl_flux - USE stel_kinds - USE stel_constants, ONLY: twopi, one, zero - IMPLICIT NONE - -!------------------------------------------------------------------------------- -! Module for coordinate conversion, cylindrical <- -> VMEC flux -! CONTAINS two subroutines: -! flx2cyl - convert from VMEC flux to cylindrical - inverse Fourier Transform -! cyl2flx - convert from cylindrical to VMEC flux - Root find using flx2cyl -! -! cyl2flx CONTAINS two subroutines: -! newt2d - implements a 2 dimensional Newton rootfind -! get_flxcoord - interface with fewer arguments to flx2cyl -! Note - since newt2d and get_flxcoord are CONTAINed in cyl2flx, they have -! access to all the variables in cyl2flx. -! -! 2011-09-06 JDH -! Split this module from vmec_utils, to clarify interfaces and dependencies -!------------------------------------------------------------------------------- - - CONTAINS - -!******************************************************************************* -!------------------------------------------------------------------------------- -! Convert from flux to cylindrical cooridnates -!------------------------------------------------------------------------------- - SUBROUTINE flx2cyl(rzl_array, c_flux, r_cyl, ns, ntor, - 1 mpol, ntmax, lthreed, lasym, iflag, - 2 mscale, nscale, Ru, Rv, Zu, Zv) - IMPLICIT NONE -C----------------------------------------------- -C D u m m y A r g u m e n t s -C----------------------------------------------- - INTEGER, INTENT(out) :: iflag - INTEGER, INTENT(in) :: ns, ntmax, mpol, ntor - LOGICAL :: lthreed, lasym - REAL(rprec), DIMENSION(ns,0:ntor,0:mpol-1,3*ntmax), - 1 INTENT(in) :: rzl_array - REAL(rprec), INTENT(in) :: c_flux(3) - REAL(rprec), INTENT(out) :: r_cyl(3) - REAL(rprec), INTENT(in), OPTIONAL :: - 1 mscale(0:mpol-1), nscale(0:ntor) - REAL(rprec), INTENT(out), OPTIONAL :: Ru, Rv, Zu, Zv -C----------------------------------------------- -C L o c a l P a r a m e t e r s -C----------------------------------------------- - INTEGER, PARAMETER :: rcc = 1 -C----------------------------------------------- -C L o c a l V a r i a b l e s -C----------------------------------------------- - INTEGER :: rss, rsc, rcs, zsc, zcs, zcc, zss - INTEGER :: istat, jslo, jshi, mpol1, m, n - REAL(rprec), DIMENSION(0:ntor,0:mpol-1) :: - 1 rmncc, rmnss, zmncs, zmnsc, - 2 rmncs, rmnsc, zmncc, zmnss - REAL(rprec) :: wlo, whi, wlo_odd, whi_odd, hs1, - 1 si, ui, vi, r11, z11 - REAL(rprec) :: wmins(0:ntor,0:mpol-1), - 1 wplus(0:ntor,0:mpol-1) - REAL(rprec) :: cosu, sinu, cosv, sinv, - 1 cosmu(0:mpol-1), sinmu(0:mpol-1), - 2 cosnv(0:ntor), sinnv(0:ntor), - 3 cosnvn(0:ntor), sinnvn(0:ntor) - REAL(rprec) :: work1(0:mpol-1,12) - LOGICAL :: lru, lrv, lzu, lzv -!-------------------------------------------------------------------------------! -! COMPUTES THE CYLINDRICAL COORDINATES R11 and Z11 -! AT A FIXED FLUX COORDINATE POINT si, ui(theta), vi(N*phi) -! WHERE phi = geometric toroidal angle (0 to 2pi), N = no. field periods -! -! INPUT: -! c_flux: array of (si,ui,vi) values to convert to cylindrical coordinates -! rzl_array: array of (r, z, lambda) Fourier coefficients for all radial, m, n values -! ns, mpol,ntor, ntmax: radial, poloidal, toroidal, type (r,z,l) dimensions of rzl_array -! mscale, nscale: option scale factors. Use ONLY if rzl_array comes from within VMEC. -! If arising from WOUT file, mscale, nscale => 1 are not passed -! -! OUTPUT: -! r_cyl : R = r_cyl(1); N*PHI = r_cyl(2); Z = r_cyl(3) -! -! OPTIONAL OUTPUT -! Ru = dR/du; Rv = dR/dv = dR/dphi / N -! Zu = dZ/du; Zv = dZ/dv = dZ/dphi / N -! -! NOTE: User is responsible for multiplying Rv, Zv by N to get phi derivatives -! -!------------------------------------------------------------------------------- - - iflag = -1 - si = c_flux(1); ui = c_flux(2); vi = c_flux(3) - r_cyl(2) = vi - -! IF (si.lt.zero .or. si.gt.one) THEN - IF (si .lt. zero) THEN - WRITE(6, *)' In flx2cyl, s(flux) must be > 0' - RETURN - END IF - - lru = PRESENT(ru); lrv = PRESENT(rv) - lzu = PRESENT(zu); lzv = PRESENT(zv) - IF (lrv .and. .not. lthreed) rv = 0 - IF (lzv .and. .not. lthreed) zv = 0 - -! -! FIND INTERPOLATED s VALUE AND COMPUTE INTERPOLATION WEIGHTS wlo, whi (for even m modes) -! AND wlo_odd, whi_odd (for odd m modes). -! FOR si <= 1, POINT IS INSIDE PLASMA; -! FOR si > 1, TRY EXTRAPOLATION (WITH CONTINUOUS s, u DERIVATIVES INTO "vacuum" REGION -! - hs1 = one/(ns-1) - IF (si .le. one) THEN - - jslo = 1 + si/hs1 - jshi = jslo+1 - wlo = (hs1*(jshi-1) - si)/hs1 - whi = 1 - wlo - IF (jslo .eq. ns) jshi = jslo - -! -! USE Rmn, Zmn ~ SQRT(s) FOR ODD-m MODES, SO INTERPOLATE Xmn/SQRT(s) -! - whi_odd = whi*SQRT(si/(hs1*(jshi-1))) - IF (jslo .ne. 1) THEN - wlo_odd = wlo*SQRT(si/(hs1*(jslo-1))) - ELSE - wlo_odd = 0 - whi_odd = SQRT(si/(hs1*(jshi-1))) - END IF - - ELSE - - jshi = ns - jslo = ns-1 - wlo = -(si - 1)/hs1; wlo_odd = wlo - whi = 1 - wlo; whi_odd = whi - - ENDIF - - - mpol1 = mpol-1 - - wmins(:,0:mpol1:2) = wlo - wplus(:,0:mpol1:2) = whi - wmins(:,1:mpol1:2) = wlo_odd - wplus(:,1:mpol1:2) = whi_odd - - - - IF (.not.lasym) THEN - IF (lthreed) THEN - IF (ntmax .ne. 2) STOP 'ntmax != 2 in flx2cyl!' - rss = 2; zcs = 2 - ELSE - IF (ntmax .ne. 1) STOP 'ntmax != 1 in flx2cyl!' - END IF - ELSE - IF (lthreed) THEN - IF (ntmax .ne. 4) STOP 'ntmax != 4 in flx2cyl!' - rss = 2; rsc = 3; rcs = 4 - zcs = 2; zcc = 3; zss = 4 - ELSE - IF (ntmax .ne. 2) STOP 'ntmax != 2 in flx2cyl!' - rsc = 2; zcc = 2 - END IF - END IF - - zsc = 1+ntmax; zcs = zcs+ntmax; zcc = zcc+ntmax; zss = zss+ntmax - - rmncc = wmins*rzl_array(jslo,:,:,rcc) - 1 + wplus*rzl_array(jshi,:,:,rcc) !!COS(mu) COS(nv) - zmnsc = wmins*rzl_array(jslo,:,:,zsc) - 1 + wplus*rzl_array(jshi,:,:,zsc) !!SIN(mu) COS(nv) - - IF (lthreed) THEN - rmnss = wmins*rzl_array(jslo,:,:,rss) - 1 + wplus*rzl_array(jshi,:,:,rss) !!SIN(mu) SIN(nv) - zmncs = wmins*rzl_array(jslo,:,:,zcs) - 1 + wplus*rzl_array(jshi,:,:,zcs) !!COS(mu) SIN(nv) - END IF - -! -! SETUP TRIG ARRAYS -! - cosu = COS(ui); sinu = SIN(ui) - cosv = COS(vi); sinv = SIN(vi) - - cosmu(0) = 1; sinmu(0) = 0 - cosnv(0) = 1; sinnv(0) = 0 - DO m = 1, mpol1 - cosmu(m) = cosmu(m-1)*cosu - sinmu(m-1)*sinu - sinmu(m) = sinmu(m-1)*cosu + cosmu(m-1)*sinu - END DO - - IF (PRESENT(mscale)) THEN - cosmu = cosmu*mscale; sinmu = sinmu*mscale - END IF - - DO n = 1, ntor - cosnv(n) = cosnv(n-1)*cosv - sinnv(n-1)*sinv - sinnv(n) = sinnv(n-1)*cosv + cosnv(n-1)*sinv - END DO - - IF (PRESENT(nscale)) THEN - cosnv = cosnv*nscale; sinnv = sinnv*nscale - END IF - - IF (lrv .or. lzv) THEN - DO n = 0, ntor - cosnvn(n) = n*cosnv(n) - sinnvn(n) =-n*sinnv(n) - END DO - END IF - - iflag = 0 - -! -! COMPUTE R11, Z11 IN REAL SPACE -! -! FIRST, INVERSE TRANSFORM IN N-V SPACE, FOR FIXED M -! - DO m = 0, mpol1 - - work1(m,1) = SUM(rmncc(:,m)*cosnv(:)) - work1(m,2) = SUM(zmnsc(:,m)*cosnv(:)) - IF (lru) work1(m,3) =-m*work1(m,1) - IF (lzu) work1(m,4) = m*work1(m,2) - IF (lthreed) THEN - IF (lrv) work1(m,5) = SUM(rmncc(:,m)*sinnvn(:)) - IF (lzv) work1(m,6) = SUM(zmnsc(:,m)*sinnvn(:)) - work1(m,7) = SUM(rmnss(:,m)*sinnv(:)) - work1(m,8) = SUM(zmncs(:,m)*sinnv(:)) - IF (lru) work1(m,9) = m*work1(m,7) - IF (lzu) work1(m,10) =-m*work1(m,8) - IF (lrv) work1(m,11) = SUM(rmnss(:,m)*cosnvn(:)) - IF (lzv) work1(m,12) = SUM(zmncs(:,m)*cosnvn(:)) - END IF - - END DO - -! -! NEXT, INVERSE TRANSFORM IN M-U SPACE -! - IF (lthreed) THEN - r11 = SUM(work1(:,1)*cosmu(:) + work1(:,7)*sinmu(:)) - z11 = SUM(work1(:,2)*sinmu(:) + work1(:,8)*cosmu(:)) - IF (lru) ru = SUM(work1(:,3)*sinmu(:) + work1(:,9)*cosmu(:)) - IF (lzu) zu = SUM(work1(:,4)*cosmu(:) + work1(:,10)*sinmu(:)) - IF (lrv) rv = SUM(work1(:,5)*cosmu(:) + work1(:,11)*sinmu(:)) - IF (lzv) zv = SUM(work1(:,6)*sinmu(:) + work1(:,12)*cosmu(:)) - ELSE - r11 = SUM(work1(:,1)*cosmu(:)) - z11 = SUM(work1(:,2)*sinmu(:)) - IF (lru) ru = SUM(work1(:,3)*sinmu(:)) - IF (lzu) zu = SUM(work1(:,4)*cosmu(:)) - END IF - - - IF (.not.lasym) GOTO 1000 - - rmnsc = wmins*rzl_array(jslo,:,:,rsc) - 1 + wplus*rzl_array(jshi,:,:,rsc) !!SIN(mu) COS(nv) - zmncc = wmins*rzl_array(jslo,:,:,zcc) - 1 + wplus*rzl_array(jshi,:,:,zcc) !!COS(mu) COS(nv) - - IF (lthreed) THEN - rmncs = wmins*rzl_array(jslo,:,:,rcs) - 1 + wplus*rzl_array(jshi,:,:,rcs) !!COS(mu) SIN(nv) - zmnss = wmins*rzl_array(jslo,:,:,zss) - 1 + wplus*rzl_array(jshi,:,:,zss) !!SIN(mu) SIN(nv) - END IF - -! -! COMPUTE R11, Z11 IN REAL SPACE -! -! FIRST, INVERSE TRANSFORM IN N-V SPACE, FOR FIXED M -! - DO m = 0, mpol1 - - work1(m,1) = SUM(rmnsc(:,m)*cosnv(:)) - work1(m,2) = SUM(zmncc(:,m)*cosnv(:)) - IF (lru) work1(m,3) = m*work1(m,1) - IF (lzu) work1(m,4) =-m*work1(m,2) - - IF (lthreed) THEN - IF (lrv) work1(m,5) = SUM(rmnsc(:,m)*sinnvn(:)) - IF (lzv) work1(m,6) = SUM(zmncc(:,m)*sinnvn(:)) - work1(m,7) = SUM(rmncs(:,m)*sinnv(:)) - work1(m,8) = SUM(zmnss(:,m)*sinnv(:)) - IF (lru) work1(m,9) =-m*work1(m,7) - IF (lzu) work1(m,10) = m*work1(m,8) - IF (lrv) work1(m,11) = SUM(rmncs(:,m)*cosnvn(:)) - IF (lzv) work1(m,12) = SUM(zmnss(:,m)*cosnvn(:)) - END IF - - END DO - -! -! NEXT, INVERSE TRANSFORM IN M-U SPACE -! - IF (lthreed) THEN - r11 = r11 + SUM(work1(:,1)*sinmu(:) + work1(:,7)*cosmu(:)) - z11 = z11 + SUM(work1(:,2)*cosmu(:) + work1(:,8)*sinmu(:)) - IF (lru) ru = ru + - 1 SUM(work1(:,3)*cosmu(:) + work1(:,9)*sinmu(:)) - IF (lzu) zu = zu + - 1 SUM(work1(:,4)*sinmu(:) + work1(:,10)*cosmu(:)) - IF (lrv) rv = rv + - 1 SUM(work1(:,5)*sinmu(:) + work1(:,11)*cosmu(:)) - IF (lzv) zv = zv + - 1 SUM(work1(:,6)*cosmu(:) + work1(:,12)*sinmu(:)) - ELSE - r11 = r11 + SUM(work1(:,1)*sinmu(:)) - z11 = z11 + SUM(work1(:,2)*cosmu(:)) - IF (lru) ru = ru + SUM(work1(:,3)*cosmu(:)) - IF (lzu) zu = zu + SUM(work1(:,4)*sinmu(:)) - END IF - - 1000 CONTINUE - - r_cyl(1) = r11; r_cyl(3) = z11 - - END SUBROUTINE flx2cyl - -!******************************************************************************* -!------------------------------------------------------------------------------- -! convert from cylindrical to flux coordinates -!------------------------------------------------------------------------------- - SUBROUTINE cyl2flx(rzl_in, r_cyl, c_flx, ns_in, ntor_in, mpol_in, - 1 ntmax_in, lthreed_in, lasym_in, info, nfe, fmin, - 1 mscale, nscale, ru, zu, rv, zv) - IMPLICIT NONE -C----------------------------------------------- -C D u m m y A r g u m e n t s -C----------------------------------------------- - INTEGER, INTENT(out) :: info, nfe - INTEGER, INTENT(in) :: ns_in, ntor_in, mpol_in, ntmax_in - REAL(rprec), INTENT(in) :: r_cyl(3) - REAL(rprec), INTENT(inout) :: c_flx(3) - REAL(rprec), INTENT(in), TARGET :: - 1 rzl_in(ns_in,0:ntor_in,0:mpol_in-1,3*ntmax_in) - REAL(rprec), TARGET, OPTIONAL :: - 1 mscale(0:mpol_in-1), nscale(0:ntor_in) - REAL(rprec), INTENT(out), OPTIONAL :: ru, zu, rv, zv - REAL(rprec), INTENT(out) :: fmin - LOGICAL, INTENT(in) :: lthreed_in, lasym_in -C----------------------------------------------- -C L o c a l P a r a m e t e r s -C----------------------------------------------- - INTEGER, PARAMETER :: nvar = 2 - REAL(rprec), PARAMETER :: ftol = 1.e-16_dp -C----------------------------------------------- -C L o c a l V a r i a b l e s -C----------------------------------------------- - REAL(rprec) :: xc_opt(nvar), r_cyl_out(3), fmin0 - INTEGER :: iflag, itry, nfe_out - -C----------------------------------------------- -C Variables to communicate with internal subroutines newt2d and get_flxcoord -C----------------------------------------------- - INTEGER :: ns_loc, ntmax_loc, mpol_loc, ntor_loc - REAL(rprec) :: r_target, phi_target, z_target, fnorm - REAL(rprec), POINTER :: rzl_array(:,:,:,:) - REAL(rprec), POINTER :: mscale_loc(:), nscale_loc(:) - LOGICAL :: lthreed_loc, lasym_loc, lscale - -C----------------------------------------------- -! LOCAL PARAMETERS: -! ftol : nominally, set to 1.E-16. Gives a maximum (relative) -! error in matching R and Z of sqrt(ftol), or 1.E-8. -! To increase accuracy, ftol should be lowered, but this -! may require more Newton iterations (slows code). -! -! INPUT: -! rzl_in : 4D array with r,z (lambda) Fourier coefficients vs. radius -! -! r_cyl : vector specifying cylindrical point to match, R = r_cyl(1), -! N*phi = r_cyl(2), Z = r_cyl(3) -! NOTE: N*phi (N=no. field periods) is input, NOT phi! -! ns_in : number of radial nodes in input array rzl_in -! ntmax_in: number of different types of modes (cos-cos, sin-sin, etc) -! mpol_in : number of poloidal modes (0:mpol_in-1) -! ntor_in : number of toroidal modes = ntor_in+1 (0:ntor) -! lthreed_in :true if this is a 3D plasma -! lasym_in: true if this is an asymmetric plasma -! mscale (nscale) : -! optional scaling arrays for cos, sin arrays. Used -! only if this routine is called from within VMEC. -! -! OUTPUT: -! nfe : number of function evaluations -! info : = 0, no errors, -1, fmin > ftol (tolerance exceeded on output) -! = -3, s > 1 outside plasma, probably -! fmin : minimum value of f = (r - Rin)**2 + (z - Zin)**2 at c_flx - -! INPUT/OUTPUT: -! c_flx : array of flux coordinates (s = c_flx(1), u=theta= c_flx(2), -! v = N*phi= c_flx(3)) -! on input, initial guess (recommend magnetic axis if "cold" start) -! on output, s, u values corresponding to r_cyl -C----------------------------------------------- -! Initialize global variables - rzl_array => rzl_in - lthreed_loc = lthreed_in; lasym_loc = lasym_in - mpol_loc = mpol_in; ntor_loc = ntor_in - ns_loc = ns_in; ntmax_loc = ntmax_in - lscale = PRESENT(mscale) - IF (lscale) THEN - mscale_loc => mscale; nscale_loc => nscale - END IF - r_target = r_cyl(1); phi_target = r_cyl(2); z_target = r_cyl(3) - -! Initialize local variables - xc_opt(1) = c_flx(1); xc_opt(2) = c_flx(2) - -! Avoid exact magnetic axis, which is singular point - IF (c_flx(1) .eq. zero) xc_opt(1) = one/(ns_loc-1) - - fnorm = r_target**2 + z_target**2 - IF (fnorm .lt. EPSILON(fnorm)) fnorm = 1 - fnorm = one/fnorm - - - nfe = 0 - fmin0 = 1 - - DO itry = 1, 4 - - CALL newt2d(xc_opt, fmin, ftol, nfe_out, nvar, info) - nfe = nfe + nfe_out - - IF (fmin.le.ftol .or. info.eq.-3) EXIT -! -! JOG POINT (BY ROTATING ANGLE) TO IMPROVE CONVERGENCE -! - IF (fmin .gt. 1.E-3*fmin0) THEN - xc_opt(2) = xc_opt(2) + twopi/20 - ELSE - xc_opt(2) = xc_opt(2) + twopi/40 - END IF - - fmin0 = MIN(fmin, fmin0) -! PRINT *,' ITRY = ', itry+1,' FMIN = ', fmin - - END DO - - c_flx(1) = xc_opt(1); c_flx(2) = xc_opt(2); c_flx(3) = phi_target -!SPH IF (info.eq.0 .and. c_flx(1).gt.one) c_flx(1) = one - - c_flx(2) = MOD(c_flx(2), twopi) - DO WHILE (c_flx(2) .lt. zero) - c_flx(2) = c_flx(2) + twopi - END DO - -! -! COMPUTE Ru, Zu, Rv, Zv IF REQUIRED -! -! IF ((PRESENT(ru) .or. PRESENT(zu) .or. -! 1 PRESENT(rv) .or. PRESENT(zv)) .and. info.eq.0) -! 2 CALL flx2cyl(rzl_in, c_flx, r_cyl_out, ns_loc, ntor_loc, -! 3 mpol_loc, ntmax_loc, lthreed_loc, lasym_loc, -! 4 iflag, MSCALE=mscale, NSCALE=nscale, -! 5 RU=ru, ZU=zu, RV=rv, ZV=zv) - - IF (PRESENT(ru) .or. PRESENT(zu) .or. PRESENT(rv) .or. & - & PRESENT(zv)) THEN - IF (info .eq. 0) THEN - CALL flx2cyl(rzl_in, c_flx, r_cyl_out, ns_loc, ntor_loc, & - & mpol_loc, ntmax_loc, lthreed_loc, lasym_loc, & - & iflag, MSCALE=mscale, NSCALE=nscale, & - & RU=ru, ZU=zu, RV=rv, ZV=zv) - ELSE ! insure that optional arguments are assigned. JDH 2014-03-11 - IF (PRESENT(ru)) ru = 0 - IF (PRESENT(zu)) zu = 0 - IF (PRESENT(rv)) rv = 0 - IF (PRESENT(zv)) zv = 0 - ENDIF - ENDIF - - CONTAINS ! internal subprograms newt2d and get_flxcoord - -!------------------------------------------------------------------------------- -!------------------------------------------------------------------------------- - SUBROUTINE newt2d(xc_opt, fmin, ftol, nfe, nvar, iflag) - IMPLICIT NONE -C----------------------------------------------- -C D u m m y A r g u m e n t s -C----------------------------------------------- - INTEGER, INTENT(in) :: nvar - INTEGER, INTENT(out) :: nfe, iflag - REAL(rprec), INTENT(inout) :: xc_opt(nvar) - REAL(rprec), INTENT(in) :: ftol - REAL(rprec), INTENT(out) :: fmin -C----------------------------------------------- -C L o c a l V a r i a b l e s -C----------------------------------------------- - INTEGER, PARAMETER :: niter = 50 - INTEGER :: ieval, isgt1 - REAL(rprec) :: c_flx(3), r_cyl_out(3), fvec(nvar), sflux, - 1 uflux, eps0, eps, epu, xc_min(2), factor - REAL(rprec) :: x0(3), xs(3), xu(3), dels, delu, tau, fmin0, - 1 ru1, zu1, edge_value, snew -!------------------------------------------------------------------------------- -! INPUT/OUTPUT: -! xc_opt: sflux = xc_opt(1), uflux = xc_opt(2) are the toroidal flux -! coordinate and poloidal angle coordinate, respectively -! iflag: = 0, successfully find s,u point -! =-1, did not converge -! =-3, sflux > 1, probably -! -! LOCAL VARIABLES: -! tau: d(R,Z)/d(s,u) (Jacobian) -! isgt1: counter for number of times s>1 - -! FIND FLUX COORDINATES (s,u) WHICH CORRESPOND TO ZERO OF TARGET FUNCTION -! -! F == (R - R_TARGET)**2 + (Z - Z_TARGET)**2 -! -! FOR A GIVEN CYLINDRICAL COORDINATE POINT (R_TARGET, N*PHI=PHI_TARGET, Z_TARGET) -! -! Reference: S.E.Attenberger, W.A.Houlberg, S.P.Hirshman, J. Comp Phys 72 (1987) 435. -! -! The algorithm used here modifies this slightly to improve "faltering" convergence -! by choosing a steepest-descent path when the step size has been decreased sufficiently -! without yielding a lower value of F. -! -!------------------------------------------------------------------------------- - - iflag = -1 - eps0 = SQRT(EPSILON(eps)) - xc_min = xc_opt - - c_flx(3) = phi_target - fmin0 = 1.E10_dp - factor = 1 - nfe = 0 - edge_value = one + one/(ns_loc-1) - isgt1 = 0 - - DO ieval = 1, niter - nfe = nfe + 1 - - sflux = MAX(xc_opt(1), zero) -! sflux = MIN(MAX(xc_opt(1), zero), one) - uflux = xc_opt(2) - c_flx(1) = sflux; c_flx(2) = uflux - -! COMPUTE R,Z, Ru, Zu - CALL get_flxcoord(x0, c_flx, ru=ru1, zu=zu1) - xu(1) = ru1; xu(3) = zu1 - -! MAKE SURE sflux IS LARGE ENOUGH -! TO COMPUTE d(sqrt(s))/ds ACCURATELY NEAR ORIGIN - IF (sflux .ge. 1000*eps0) THEN - eps = eps0 - ELSE - eps = eps0*sflux - END IF - -! COMPUTE Rs, Zs NUMERICALLY - eps = ABS(eps) - IF (sflux .ge. 1-eps) eps = -eps - c_flx(1) = sflux + eps - CALL get_flxcoord(r_cyl_out, c_flx) - xs = (r_cyl_out - x0)/eps - c_flx(1) = sflux - - x0(1) = x0(1) - r_target - x0(3) = x0(3) - z_target - fmin = (x0(1)**2 + x0(3)**2)*fnorm - - IF (fmin .gt. fmin0) THEN - factor = (2*factor)/3 - xc_opt = xc_min -! REDIRECT ALONG STEEPEST-DESCENT PATH - IF (6*factor .lt. one) THEN - dels =-(x0(1)*xs(1) + x0(3)*xs(3))/(xs(1)**2 + xs(3)**2) - delu =-(x0(1)*xu(1) + x0(3)*xu(3))/(xu(1)**2 + xu(3)**2) - END IF - ELSE - fmin0 = fmin - factor = 1 - xc_min = xc_opt - -! NEWTON STEP - tau = xu(1)*xs(3) - xu(3)*xs(1) - IF (ABS(tau) .le. ABS(eps)*r_target**2) THEN - iflag = -2 - EXIT - END IF - dels = ( x0(1)*xu(3) - x0(3)*xu(1))/tau - delu = (-x0(1)*xs(3) + x0(3)*xs(1))/tau - IF (fmin .gt. 1.E-3_dp) THEN - dels = dels/2; delu = delu/2 - END IF - - END IF - - IF (fmin .le. ftol) EXIT - - IF (ABS(dels) .gt. one) dels = SIGN(one, dels) -! IF (ABS(delu) .gt. twopi/2) delu = SIGN(twopi/2, delu) - - snew = xc_opt(1) + dels*factor - IF (snew .lt. zero) THEN - xc_opt(1) = -snew/2 !Prevents oscillations around origin s=0 - xc_opt(2) = xc_opt(2) + twopi/2 - delu = -delu -! factor = (-snew/2-xc_opt(1))/dels -! xc_opt(1) = -snew/2 - ELSE - xc_opt(1) = snew - END IF - xc_opt(2) = xc_opt(2) + delu*factor - - IF (xc_opt(1) .gt. edge_value) THEN - isgt1 = isgt1+1 - IF (xc_opt(1) .gt. 2._dp) isgt1 = isgt1+1 - IF (isgt1 .gt. 5) EXIT - END IF - - END DO - - IF (isgt1.gt.5) THEN - iflag = -3 - xc_min = xc_opt - ELSE IF (xc_min(1) .gt. edge_value) THEN - iflag = -3 - ELSE IF (fmin0 .le. ftol) THEN - iflag = 0 - ELSE - iflag = -1 - END IF - - fmin = fmin0 - xc_opt = xc_min - xc_opt(2) = MOD(xc_opt(2), twopi) - - END SUBROUTINE newt2d ! Internal subroutine to cyl2flx - -!------------------------------------------------------------------------------- -!------------------------------------------------------------------------------- - SUBROUTINE get_flxcoord(x1, c_flx, ru, zu) ! Internal subroutine to cyl2flx -C----------------------------------------------- -C D u m m y A r g u m e n t s -C----------------------------------------------- - REAL(rprec), INTENT(out) :: x1(3) - REAL(rprec), INTENT(in) :: c_flx(3) - REAL(rprec), INTENT(out), OPTIONAL :: ru, zu -C----------------------------------------------- -C L o c a l V a r i a b l e s -C----------------------------------------------- - INTEGER :: iflag -C----------------------------------------------- - IF (lscale) THEN - CALL flx2cyl(rzl_array, c_flx, x1, ns_loc, ntor_loc, mpol_loc, - 1 ntmax_loc, lthreed_loc, lasym_loc, iflag, - 2 MSCALE=mscale_loc, NSCALE=nscale_loc, RU=ru, ZU=zu) - ELSE - CALL flx2cyl(rzl_array, c_flx, x1, ns_loc, ntor_loc, mpol_loc, - 1 ntmax_loc, lthreed_loc, lasym_loc, iflag, - 2 RU=ru, ZU=zu) - END IF - - END SUBROUTINE get_flxcoord ! Internal subroutine to cyl2flx - - END SUBROUTINE cyl2flx - - END MODULE cyl_flux diff --git a/DIAGNO/Sources/diagno_input_mod.f90 b/LIBSTELL/Sources/Modules/diagno_input_mod.f90 similarity index 89% rename from DIAGNO/Sources/diagno_input_mod.f90 rename to LIBSTELL/Sources/Modules/diagno_input_mod.f90 index bbe38d256..0661506cd 100644 --- a/DIAGNO/Sources/diagno_input_mod.f90 +++ b/LIBSTELL/Sources/Modules/diagno_input_mod.f90 @@ -80,13 +80,13 @@ SUBROUTINE read_diagno_input(filename, istat) segrog_turns = 1.0_rprec units = 1.0_rprec int_type = 'simpson' - int_step = 2.0_rprec + int_step = 2 lrphiz = .FALSE. luse_mut = .FALSE. vc_adapt_tol = 1.0E-06_rprec vc_adapt_rel = 1.0E-04_rprec lvc_field = .TRUE. - luse_extcur(:) = .TRUE. ! Do this so we default to using the whole coil if the user forgets + luse_extcur = .TRUE. ! Do this so we default to using the whole coil if the user forgets lapoints_accurate_output = .false. ! default for backward compatibility lbpoints_accurate_output = .false. ! default for backward compatibility ! Read namelist @@ -180,9 +180,9 @@ SUBROUTINE write_diagno_input(iunit,istat) WRITE(iunit,'(A)') '&DIAGNO_IN' WRITE(iunit,"(2X,A,1X,'=',1X,I0)") 'NU',nu WRITE(iunit,"(2X,A,1X,'=',1X,I0)") 'NV',nv - WRITE(iunit,"(2X,A,1X,'=',1X,E22.14)") 'UNITS',units - WRITE(iunit,"(2X,A,1X,'=',1X,E22.14)") 'VC_ADAPT_TOL',vc_adapt_tol - WRITE(iunit,"(2X,A,1X,'=',1X,E22.14)") 'VC_ADAPT_REL',vc_adapt_rel + WRITE(iunit,"(2X,A,1X,'=',1X,ES22.14)") 'UNITS',units + WRITE(iunit,"(2X,A,1X,'=',1X,ES22.14)") 'VC_ADAPT_TOL',vc_adapt_tol + WRITE(iunit,"(2X,A,1X,'=',1X,ES22.14)") 'VC_ADAPT_REL',vc_adapt_rel WRITE(iunit,outstr) 'INT_TYPE',TRIM(int_type) WRITE(iunit,"(2X,A,1X,'=',1X,I0)") 'INT_STEP',int_step WRITE(iunit,outstr) 'AFIELD_POINTS_FILE',TRIM(afield_points_file) @@ -192,9 +192,10 @@ SUBROUTINE write_diagno_input(iunit,istat) WRITE(iunit,outstr) 'SEG_ROG_FILE',TRIM(seg_rog_file) WRITE(iunit,outstr) 'FLUX_DIAG_FILE',TRIM(flux_diag_file) WRITE(iunit,outstr) 'FLUX_MUT_FILE',TRIM(flux_mut_file) - WRITE(iunit,"(2X,A,1X,'=',10(1X,E22.14))") 'BPROBE_TURNS',(bprobe_turns(n), n=1,256) - WRITE(iunit,"(2X,A,1X,'=',10(1X,E22.14))") 'FLUX_TURNS',(flux_turns(n), n=1,256) - WRITE(iunit,"(2X,A,1X,'=',10(1X,E22.14))") 'SEGROG_TURNS',(segrog_turns(n), n=1,256) + IF (ANY(bprobe_turns /= 1.0)) WRITE(iunit,"(2X,A,1X,'=',10(1X,ES22.14))") 'BPROBE_TURNS',(bprobe_turns(n), n=1,256) + IF (ANY(flux_turns /= 1.0)) WRITE(iunit,"(2X,A,1X,'=',10(1X,ES22.14))") 'FLUX_TURNS',(flux_turns(n), n=1,256) + IF (ANY(segrog_turns /= 1.0)) WRITE(iunit,"(2X,A,1X,'=',10(1X,ES22.14))") 'SEGROG_TURNS',(segrog_turns(n), n=1,256) + IF (ANY( .not. luse_extcur)) WRITE(iunit,"(2X,A,1X,'=',10(1X,L1))") 'luse_extcur',(luse_extcur(n), n=1,256) WRITE(iunit,"(2X,A,1X,'=',1X,L1)") 'LRPHIZ',lrphiz WRITE(iunit,"(2X,A,1X,'=',1X,L1)") 'LVC_FIELD',lvc_field WRITE(iunit,"(2X,A,1X,'=',1X,L1)") 'LAPOINTS_ACCURATE_OUTPUT',lapoints_accurate_output @@ -203,6 +204,26 @@ SUBROUTINE write_diagno_input(iunit,istat) CALL FLUSH(iunit) END SUBROUTINE write_diagno_input + SUBROUTINE write_diagno_input_byfile(filename) + CHARACTER(LEN=*), INTENT(in) :: filename + INTEGER :: iunit, istat + LOGICAL :: lexists + + iunit = 100 + istat = 0 + INQUIRE(FILE=TRIM(filename),exist=lexists) + IF (lexists) THEN + OPEN(unit=iunit, file=TRIM(filename), iostat=istat, status="old", position="append") + ELSE + OPEN(unit=iunit, file=TRIM(filename), iostat=istat, status="new") + END IF + IF (istat .ne. 0) RETURN + CALL write_diagno_input(iunit,istat) + CLOSE(iunit) + + RETURN + END SUBROUTINE write_diagno_input_byfile + SUBROUTINE BCAST_DIAGNO_INPUT(local_master,comm,istat) !DEC$ IF DEFINED (MPI_OPT) USE mpi diff --git a/DIAGNO/Sources/diagno_runtime.f90 b/LIBSTELL/Sources/Modules/diagno_runtime.f90 similarity index 100% rename from DIAGNO/Sources/diagno_runtime.f90 rename to LIBSTELL/Sources/Modules/diagno_runtime.f90 diff --git a/LIBSTELL/Sources/Modules/fieldlines_globals.f90 b/LIBSTELL/Sources/Modules/fieldlines_globals.f90 new file mode 100644 index 000000000..1b03db26c --- /dev/null +++ b/LIBSTELL/Sources/Modules/fieldlines_globals.f90 @@ -0,0 +1,47 @@ +!----------------------------------------------------------------------- +! Module: fieldlines_globals +! Authors: S. Lazerson (samuel.lazerson@gauss-fusion.com) +! Date: 05/28/2024 +! Description: This module contains the FIELDLINES global +! variables needed by the input namelist. +!----------------------------------------------------------------------- + MODULE fieldlines_globals +!----------------------------------------------------------------------- +! Libraries +!----------------------------------------------------------------------- + USE stel_kinds, ONLY: rprec + +!----------------------------------------------------------------------- +! Module Variables +!----------------------------------------------------------------------- + IMPLICIT NONE + + ! From fiellines_runtime + INTEGER, PARAMETER :: MAXLINES = 2**19 + LOGICAL :: lerror_field, lmu + INTEGER :: npoinc, num_hcp + REAL(rprec) :: dphi, follow_tol, delta_hc, mu + REAL(rprec), DIMENSION(20) :: errorfield_amp, errorfield_phase + REAL(rprec), DIMENSION(MAXLINES) :: r_start, phi_start, & + z_start, phi_end, & + r_hc, z_hc, phi_hc + CHARACTER(256) :: int_type + + + ! From fieldlines_lines + INTEGER :: nlines + ! From fieldlines_grid + INTEGER :: nr, nphi, nz + REAL(rprec) :: rmin, rmax, zmin, zmax, phimin, phimax, & + vc_adapt_tol + + + CONTAINS + + ! These expose the global variables through ctypes + INTEGER FUNCTION getmaxlines() + IMPLICIT NONE + getmaxlines = MAXLINES + END FUNCTION getmaxlines + + END MODULE fieldlines_globals diff --git a/FIELDLINES/Sources/fieldlines_input_mod.f90 b/LIBSTELL/Sources/Modules/fieldlines_input_mod.f90 similarity index 64% rename from FIELDLINES/Sources/fieldlines_input_mod.f90 rename to LIBSTELL/Sources/Modules/fieldlines_input_mod.f90 index 4892f2c9e..d7fb525d9 100644 --- a/FIELDLINES/Sources/fieldlines_input_mod.f90 +++ b/LIBSTELL/Sources/Modules/fieldlines_input_mod.f90 @@ -11,10 +11,7 @@ MODULE fieldlines_input_mod ! Libraries !----------------------------------------------------------------------- USE stel_kinds, ONLY: rprec - USE fieldlines_runtime - USE fieldlines_lines, ONLY: nlines - USE fieldlines_grid, ONLY: nr, nphi, nz, rmin, rmax, zmin, zmax, & - phimin, phimax, vc_adapt_tol + USE fieldlines_globals USE safe_open_mod, ONLY: safe_open USE mpi_params USE mpi_inc @@ -73,10 +70,9 @@ MODULE fieldlines_input_mod !----------------------------------------------------------------------- CONTAINS - SUBROUTINE read_fieldlines_input(filename, istat, ithread) + SUBROUTINE read_fieldlines_input(filename, istat) CHARACTER(*), INTENT(in) :: filename INTEGER, INTENT(out) :: istat - INTEGER, INTENT(in) :: ithread LOGICAL :: lexist INTEGER :: i, iunit, local_master CHARACTER(LEN=1000) :: line @@ -90,7 +86,7 @@ SUBROUTINE read_fieldlines_input(filename, istat, ithread) zmin = -1.0_rprec zmax = 1.0_rprec phimin = 0.0_rprec - phimax = pi2 + phimax = 8.0 * ATAN(1.0) mu = 0.0_rprec r_start = -1 z_start = -1 @@ -102,7 +98,7 @@ SUBROUTINE read_fieldlines_input(filename, istat, ithread) num_hcp = 50 delta_hc = 5.0E-5 npoinc = 1 - dphi = pi2/360 + dphi = 8.0 * ATAN(1.0)/360 follow_tol = 1.0E-7 vc_adapt_tol = 1.0E-5 lerror_field = .false. @@ -110,20 +106,24 @@ SUBROUTINE read_fieldlines_input(filename, istat, ithread) errorfield_phase = 0 int_type = "NAG" ! Read namelist - IF (ithread == local_master) THEN istat=0 iunit=12 INQUIRE(FILE=TRIM(filename),EXIST=lexist) IF (.not.lexist) stop 'Could not find input file' CALL safe_open(iunit,istat,TRIM(filename),'old','formatted') - !OPEN(UNIT=iunit,FILE=TRIM(filename),STATUS='old',FORM='formatted') - IF (istat /= 0) CALL handle_err(FILE_OPEN_ERR,'fieldlines_input in: input.'//TRIM(id_string),istat) + IF (istat /= 0) THEN + WRITE(6,'(A)') 'ERROR opening file: ',TRIM(filename) + CALL FLUSH(6) + STOP + END IF READ(iunit,NML=fieldlines_input,IOSTAT=istat) IF (istat /= 0) THEN + WRITE(6,'(A)') 'ERROR reading namelist BEAMS3D_INPUT from file: ',TRIM(filename) backspace(iunit) read(iunit,fmt='(A)') line write(6,'(A)') 'Invalid line in namelist: '//TRIM(line) - IF (istat /= 0) CALL handle_err(NAMELIST_READ_ERR,'fieldlines_input in: input.'//TRIM(id_string),istat) + CALL FLUSH(6) + STOP END IF CLOSE(iunit) nlines = 0 @@ -134,15 +134,101 @@ SUBROUTINE read_fieldlines_input(filename, istat, ithread) END DO IF (ALL(PHI_END .lt. 0)) THEN WRITE(6,*) '!!!!!!!!!!!!!!!!!!!!PHI_END NOT SET!!!!!!!!!!!!!!!!!!!!' - istat = -1 - IF (istat /= 0) CALL handle_err(NAMELIST_READ_ERR,'fieldlines_input in: input.'//TRIM(id_string),istat) + CALL FLUSH(6) + STOP END IF IF (ANY(errorfield_amp .ne. 0)) THEN lerror_field = .true. END IF - END IF int_type = TRIM(int_type) int_type = ADJUSTL(int_type) + IF (mu > 0.0) lmu=.true. + END SUBROUTINE read_fieldlines_input + + SUBROUTINE write_fieldlines_namelist(iunit_out, istat) + INTEGER, INTENT(in) :: iunit_out + INTEGER, INTENT(out) :: istat + INTEGER :: ik, n, l + CHARACTER(LEN=*), PARAMETER :: outboo = "(2X,A,1X,'=',1X,L1)" + CHARACTER(LEN=*), PARAMETER :: outint = "(2X,A,1X,'=',1X,I0)" + CHARACTER(LEN=*), PARAMETER :: outflt = "(2X,A,1X,'=',1X,ES22.12E3)" + CHARACTER(LEN=*), PARAMETER :: outexp = "(2X,A,1X,'=',1X,ES22.12E3)" + CHARACTER(LEN=*), PARAMETER :: outcmp = "(2x,A,1X,'=','(',i3,',',i3,')')" + CHARACTER(LEN=*), PARAMETER :: outstr = "(2X,A,1X,'=',1X,'''',A,'''')" + CHARACTER(LEN=*), PARAMETER :: onevar = "(2X,A,1X,'=',1X,L1,2(2X,A,1X,'=',1X,ES22.12E3))" + CHARACTER(LEN=*), PARAMETER :: vecvar = "(2X,A,'(',I3.3,')',1X,'=',1X,ES22.12E3)" + CHARACTER(LEN=*), PARAMETER :: vecvar2 = "(2X,A,'(',I3.3,',',I3.3,')',1X,'=',1X,ES22.12E3)" + istat = 0 + WRITE(iunit_out,'(A)') '&FIELDLINES_INPUT' + WRITE(iunit_out,'(A)') '!---------- Background Grid Parameters ------------' + WRITE(iunit_out,outint) 'NR',nr + WRITE(iunit_out,outint) 'NZ',nz + WRITE(iunit_out,outint) 'NPHI',nphi + WRITE(iunit_out,outflt) 'RMIN',rmin + WRITE(iunit_out,outflt) 'RMAX',rmax + WRITE(iunit_out,outflt) 'ZMIN',zmin + WRITE(iunit_out,outflt) 'ZMAX',zmax + WRITE(iunit_out,outflt) 'PHIMIN',phimin + WRITE(iunit_out,outflt) 'PHIMAX',phimax + WRITE(iunit_out,outflt) 'VC_ADAPT_TOL',vc_adapt_tol + WRITE(iunit_out,'(A)') '!---------- Marker Tracking Parameters ------------' + WRITE(iunit_out,outstr) 'INT_TYPE',TRIM(int_type) + WRITE(iunit_out,outflt) 'FOLLOW_TOL',follow_tol + WRITE(iunit_out,outint) 'NPOINC',npoinc + WRITE(iunit_out,outflt) 'MU',mu + n = COUNT(r_start > 0) + WRITE(iunit_out,"(2X,A,1X,'=',10(1X,ES22.12E3))") 'R_START',(r_start(ik), ik=1,n) + WRITE(iunit_out,"(2X,A,1X,'=',10(1X,ES22.12E3))") 'Z_START',(z_start(ik), ik=1,n) + WRITE(iunit_out,"(2X,A,1X,'=',10(1X,ES22.12E3))") 'PHI_START',(phi_start(ik), ik=1,n) + WRITE(iunit_out,"(2X,A,1X,'=',10(1X,ES22.12E3))") 'PHI_END',(phi_end(ik), ik=1,n) + n = COUNT(r_hc > 0) + IF (n > 0) THEN + WRITE(iunit_out,'(A)') '!---------- Periodic Orbits (-full) ------------' + WRITE(iunit_out,outint) 'NUM_HCP',num_hcp + WRITE(iunit_out,outflt) 'DELTA_HC',delta_hc + WRITE(iunit_out,"(2X,A,1X,'=',10(1X,ES22.12E3))") 'R_HC',(r_hc(ik), ik=1,n) + WRITE(iunit_out,"(2X,A,1X,'=',10(1X,ES22.12E3))") 'Z_HC',(z_hc(ik), ik=1,n) + WRITE(iunit_out,"(2X,A,1X,'=',10(1X,ES22.12E3))") 'PHI_HC',(phi_HC(ik), ik=1,n) + WRITE(iunit_out,'(A)') '/' + ENDIF + n = COUNT(errorfield_amp > 0) + IF (n > 0) THEN + WRITE(iunit_out,'(A)') '!---------- Error Fields ------------' + WRITE(iunit_out,"(2X,A,1X,'=',10(1X,ES22.12E3))") 'ERRORFIELD_AMP',(errorfield_amp(ik), ik=1,n) + WRITE(iunit_out,"(2X,A,1X,'=',10(1X,ES22.12E3))") 'ERRORFIELD_PHASE',(errorfield_phase(ik), ik=1,n) + ENDIF + WRITE(iunit_out,'(A)') '/' + + END SUBROUTINE write_fieldlines_namelist + + SUBROUTINE write_fieldlines_namelist_byfile(filename) + CHARACTER(LEN=*), INTENT(in) :: filename + INTEGER :: iunit, istat + LOGICAL :: lexists + + iunit = 100 + istat = 0 + INQUIRE(FILE=TRIM(filename),exist=lexists) + IF (lexists) THEN + OPEN(unit=iunit, file=TRIM(filename), iostat=istat, status="old", position="append") + ELSE + OPEN(unit=iunit, file=TRIM(filename), iostat=istat, status="new") + END IF + IF (istat .ne. 0) RETURN + CALL write_fieldlines_namelist(iunit,istat) + CLOSE(iunit) + + RETURN + END SUBROUTINE write_fieldlines_namelist_byfile + + SUBROUTINE BCAST_FIELDLINES_INPUT(local_master,comm,istat) + USE mpi_inc + IMPLICIT NONE + + INTEGER, INTENT(inout) :: comm + INTEGER, INTENT(in) :: local_master + INTEGER, INTENT(inout) :: istat + IF (istat .ne. 0) RETURN #if defined(MPI_OPT) CALL MPI_BARRIER(MPI_COMM_FIELDLINES,istat) CALL MPI_BCAST(nr,1,MPI_INTEGER, local_master, MPI_COMM_FIELDLINES,istat) @@ -174,7 +260,6 @@ SUBROUTINE read_fieldlines_input(filename, istat, ithread) CALL MPI_BCAST(errorfield_amp,20,MPI_REAL8, local_master, MPI_COMM_FIELDLINES,istat) CALL MPI_BCAST(errorfield_phase,20,MPI_REAL8, local_master, MPI_COMM_FIELDLINES,istat) #endif - IF (mu > 0.0) lmu=.true. - END SUBROUTINE read_fieldlines_input + END SUBROUTINE BCAST_FIELDLINES_INPUT END MODULE fieldlines_input_mod diff --git a/LIBSTELL/Sources/Modules/vmec_input.f b/LIBSTELL/Sources/Modules/vmec_input.f index dfe6a182c..83fd85a73 100644 --- a/LIBSTELL/Sources/Modules/vmec_input.f +++ b/LIBSTELL/Sources/Modules/vmec_input.f @@ -212,6 +212,34 @@ SUBROUTINE read_mse_namelist (iunit, istat) READ (iunit, nml=mseprofile, iostat=istat) END SUBROUTINE read_mse_namelist + + SUBROUTINE read_indata_namelist_byfile (filename) + CHARACTER(LEN=*), INTENT(in) :: filename + INTEGER :: iunit, istat + + iunit = 100 + istat = 0 + OPEN(unit=iunit, file=TRIM(filename), iostat=istat) + IF (istat .ne. 0) RETURN + CALL read_indata_namelist(iunit,istat) + CLOSE(iunit) + + RETURN + END SUBROUTINE read_indata_namelist_byfile + + SUBROUTINE write_indata_namelist_byfile (filename) + CHARACTER(LEN=*), INTENT(in) :: filename + INTEGER :: iunit, istat + + iunit = 100 + istat = 0 + OPEN(unit=iunit, file=TRIM(filename), iostat=istat) + IF (istat .ne. 0) RETURN + CALL write_indata_namelist(iunit,istat) + CLOSE(iunit) + + RETURN + END SUBROUTINE write_indata_namelist_byfile SUBROUTINE write_indata_namelist (iunit, istat) IMPLICIT NONE diff --git a/LIBSTELL/Sources/Modules/vparams.f b/LIBSTELL/Sources/Modules/vparams.f index 7164cee86..83192294b 100644 --- a/LIBSTELL/Sources/Modules/vparams.f +++ b/LIBSTELL/Sources/Modules/vparams.f @@ -50,4 +50,26 @@ MODULE vparams real(rprec), parameter :: dmu0 = 2.0e-7_dp*twopi !SAL 09/26/11 for COBRA + CONTAINS + + INTEGER FUNCTION getndatafmax() + IMPLICIT NONE + getndatafmax = ndatafmax + END FUNCTION getndatafmax + + INTEGER FUNCTION getmpol1d() + IMPLICIT NONE + getmpol1d = mpol1d + END FUNCTION getmpol1d + + INTEGER FUNCTION getntord() + IMPLICIT NONE + getntord = ntord + END FUNCTION getntord + + INTEGER FUNCTION getnsd() + IMPLICIT NONE + getnsd = nsd + END FUNCTION getnsd + END MODULE vparams diff --git a/LIBSTELL/Sources/Modules/vsvd0.f b/LIBSTELL/Sources/Modules/vsvd0.f index 06d1d958c..60f2c8516 100644 --- a/LIBSTELL/Sources/Modules/vsvd0.f +++ b/LIBSTELL/Sources/Modules/vsvd0.f @@ -32,4 +32,13 @@ MODULE vsvd0 INTEGER, PARAMETER :: npfcoil = 40 !number of filaments in pf coil pack (for plotting) INTEGER, PARAMETER :: nigroup = 300 !number of external current groups INTEGER, PARAMETER :: ipedsvd = 8 + + CONTAINS + + ! These expose the global variables through ctypes + INTEGER FUNCTION getnigroup() + IMPLICIT NONE + getnigroup = nigroup + END FUNCTION getnigroup + END MODULE vsvd0 diff --git a/LIBSTELL/Sources/STELLOPT/stellopt_globals.f90 b/LIBSTELL/Sources/STELLOPT/stellopt_globals.f90 new file mode 100644 index 000000000..1a4fc2ece --- /dev/null +++ b/LIBSTELL/Sources/STELLOPT/stellopt_globals.f90 @@ -0,0 +1,38 @@ +!----------------------------------------------------------------------- +! Module: stellopt_globals +! Authors: S. Lazerson (samuel.lazerson@gauss-fusion.com) +! Date: 05/31/2024 +! Description: This module contains the STELLOPT global variables +! needed by the input namelist. +!----------------------------------------------------------------------- + MODULE stellopt_globals +!----------------------------------------------------------------------- +! Libraries +!----------------------------------------------------------------------- + USE stel_kinds, ONLY: rprec + +!----------------------------------------------------------------------- +! Module Variables +!----------------------------------------------------------------------- + IMPLICIT NONE + ! Moved from stellopt_runtime + INTEGER, PARAMETER :: maxwindsurf=32 + REAL(rprec), PARAMETER :: bigno = 1.0E+10 + LOGICAL :: lcentered_differences, lkeep_mins, lrefit, lcoil_geom, lno_restart, ltriangulate + INTEGER :: cr_strategy, npopulation, noptimizers, mode, rho_exp + REAL(rprec) :: ftol, xtol, gtol, epsfcn, factor, refit_param + CHARACTER(256) :: opt_type, axis_init_option + + CONTAINS + + INTEGER FUNCTION getmaxwindsurf() + IMPLICIT NONE + getmaxwindsurf = maxwindsurf + END FUNCTION getmaxwindsurf + + REAL(rprec) FUNCTION getbigno() + IMPLICIT NONE + getbigno = bigno + END FUNCTION getbigno + + END MODULE stellopt_globals \ No newline at end of file diff --git a/STELLOPTV2/Sources/Modules/stellopt_input_mod.f90 b/LIBSTELL/Sources/STELLOPT/stellopt_input_mod.f90 similarity index 84% rename from STELLOPTV2/Sources/Modules/stellopt_input_mod.f90 rename to LIBSTELL/Sources/STELLOPT/stellopt_input_mod.f90 index 5fd3a26a8..0f1ce4dce 100644 --- a/STELLOPTV2/Sources/Modules/stellopt_input_mod.f90 +++ b/LIBSTELL/Sources/STELLOPT/stellopt_input_mod.f90 @@ -11,34 +11,22 @@ MODULE stellopt_input_mod ! Libraries !----------------------------------------------------------------------- USE stel_kinds, ONLY: rprec - USE stellopt_runtime + USE stellopt_globals, ONLY: axis_init_option, cr_strategy, & + epsfcn, factor, ftol, gtol, lcentered_differences, lkeep_mins, & + lrefit, mode, noptimizers, npopulation, opt_type, refit_param, & + rho_exp, xtol, bigno, lcoil_geom, lno_restart, ltriangulate USE stellopt_vars - USE equil_utils, ONLY: profile_norm - USE windingsurface USE stellopt_targets USE safe_open_mod, ONLY: safe_open - USE diagno_runtime, ONLY: DIAGNO_VERSION - USE vmec0, ONLY: version_ USE vmec_input, ONLY: lasym_local => lasym, am, am_aux_s, am_aux_f, pmass_type, & ac, ac_aux_s, ac_aux_f, pcurr_type, & ai, ai_aux_s, ai_aux_f, piota_type, & ah, ah_aux_s, ah_aux_f, ph_type, & at, at_aux_s, at_aux_f, pt_type, & aphi - USE vmec_params, ONLY: version_vmec=> version_ USE mpi_params ! MPI -!DEC$ IF DEFINED (GENE) - !USE par_other, ONLY: svn_gene => svn_rev, release_gene => release !OLD SVN Version - USE par_other, ONLY: svn_gene => git_master, release_gene => git_branch -!DEC$ ENDIF -!DEC$ IF DEFINED (BEAMS3D_OPT) - USE beams3d_runtime, ONLY: BEAMS3D_VERSION -!DEC$ ENDIF !DEC$ IF DEFINED (REGCOIL) USE regcoil_variables, ONLY: rc_nfp => nfp, rmnc_coil, rmns_coil, zmns_coil, zmnc_coil, mnmax_coil, xm_coil, xn_coil, verbose, regcoil_nml - !USE regcoil_variables, ONLY: rc_rmnc_stellopt, rc_rmns_stellopt, & - ! rc_zmnc_stellopt, rc_zmns_stellopt, & - ! rc_nfp => nfp !DEC$ ENDIF !----------------------------------------------------------------------- @@ -430,17 +418,8 @@ MODULE stellopt_input_mod !----------------------------------------------------------------------- CONTAINS - SUBROUTINE read_stellopt_input(filename, istat, ithread) - CHARACTER(*), INTENT(in) :: filename - INTEGER, INTENT(out) :: istat - INTEGER, INTENT(in) :: ithread - LOGICAL :: lexist - INTEGER :: i, ierr, iunit, local_master, isurf - CHARACTER(LEN=1000) :: line - - ! Variables used in regcoil section to parse nescin spectrum - INTEGER :: imn, m, n - + SUBROUTINE init_stellopt_input + IMPLICIT NONE ! Initializations to default values nfunc_max = 5000 opt_type = 'LMDIF' @@ -693,8 +672,8 @@ SUBROUTINE read_stellopt_input(filename, istat, ithread) coil_type(:) = 'U' ! Default to "unknown" coil_surf(:) = 1 ! Default to 1st winding surface for back-compat windsurfname(:) = '' - windsurf(:)%mmax = -1 - windsurf(:)%nmax = -1 + !windsurf(:)%mmax = -1 + !windsurf(:)%nmax = -1 fixedcoilname = '' mboz = 64 nboz = 64 @@ -951,7 +930,7 @@ SUBROUTINE read_stellopt_input(filename, istat, ithread) nz_txport = 128 nalpha_txport = 1 alpha_start_txport= 0.0 - alpha_end_txport = pi2/2 + alpha_end_txport = 8.0 * ATAN(1.0)/2 target_txport = 0.0 sigma_txport = bigno s_txport = -1.0 @@ -1035,21 +1014,40 @@ SUBROUTINE read_stellopt_input(filename, istat, ithread) sigma_curvature_P2 = bigno target_gamma_c = 0.0 sigma_gamma_c = bigno + END SUBROUTINE init_stellopt_input + + SUBROUTINE read_stellopt_input(filename, istat) + CHARACTER(*), INTENT(in) :: filename + INTEGER, INTENT(out) :: istat + LOGICAL :: lexist + INTEGER :: i, ierr, iunit, local_master, isurf + CHARACTER(LEN=1000) :: line + + ! Variables used in regcoil section to parse nescin spectrum + INTEGER :: imn, m, n + + ! Read name list lexist = .false. istat=0 iunit=12 INQUIRE(FILE=TRIM(filename),EXIST=lexist) - IF (.not.lexist) CALL handle_err(FILE_EXIST_ERR,TRIM(filename),istat) + IF (.not.lexist) stop 'Could not find input file' CALL safe_open(iunit,istat,TRIM(filename),'old','formatted') - IF (istat /= 0) CALL handle_err(FILE_OPEN_ERR,TRIM(filename),istat) + IF (istat /= 0) THEN + WRITE(6,'(A)') 'ERROR opening file: ',TRIM(filename) + CALL FLUSH(6) + STOP + END IF READ(iunit,NML=optimum,IOSTAT=istat) IF (istat /= 0) THEN + WRITE(6,'(A)') 'ERROR reading namelist OPTIMUM from file: ',TRIM(filename) backspace(iunit) read(iunit,fmt='(A)') line write(6,'(A)') 'Invalid line in namelist: '//TRIM(line) - CALL handle_err(NAMELIST_READ_ERR,'OPTIMUM in: '//TRIM(filename),istat) + CALL FLUSH(6) + STOP END IF CALL FLUSH(iunit) CLOSE(iunit) @@ -1071,118 +1069,6 @@ SUBROUTINE read_stellopt_input(filename, istat, ithread) bootj_type = ADJUSTL(bootj_type) bootcalc_type = ADJUSTL(bootcalc_type) - ! Coil Optimization - IF (ANY(ANY(lcoil_spline,2),1)) THEN - lcoil_geom = .true. - - DO isurf=1,maxwindsurf - IF (LEN_TRIM(windsurfname(isurf)).gt.0) THEN - CALL read_winding_surface(windsurfname(isurf), isurf, ierr) - IF (ierr.ne.0) CALL handle_err(CWS_READ_ERR, & - windsurfname(isurf), ierr) - lwindsurf(isurf) = .TRUE. - ENDIF - ENDDO !isurf - - ! Count knots, error check - DO i=1,nigroup - n = COUNT(coil_splinesx(i,:) >= 0.0) - coil_nctrl(i) = n - 4 - IF ((n > 0).AND.(n < 4)) & - CALL handle_err(KNOT_DEF_ERR, 'read_stellopt_input', n) - IF (COUNT(coil_splinesy(i,:) >= 0.0) - 4 .NE. coil_nctrl(i)) & - CALL handle_err(KNOT_MISMATCH_ERR, 'read_stellopt_input', coil_nctrl(i)) - IF ((.NOT.lwindsurf(coil_surf(i))) .AND. (COUNT(coil_splinesz(i,:) >= 0.0) - 4 .NE. coil_nctrl(i))) & - CALL handle_err(KNOT_MISMATCH_ERR, 'read_stellopt_input', coil_nctrl(i)) - IF (ANY(lcoil_spline(i,MAX(coil_nctrl(i)+1,1):maxcoilctrl))) & - CALL handle_err(KNOT_MISMATCH_ERR, 'read_stellopt_input', coil_nctrl(i)) - IF (n.GE.4) THEN - DO m=2,n - IF (coil_splinesx(i,m).LT.coil_splinesx(i,m-1)) & - CALL handle_err(KNOT_ORDER_ERR, 'read_stellopt_input', m) - IF (coil_splinesy(i,m).LT.coil_splinesy(i,m-1)) & - CALL handle_err(KNOT_ORDER_ERR, 'read_stellopt_input', m) - ENDDO - IF ((coil_splinesx(i,2).NE.coil_splinesx(i,1)) .OR. & - (coil_splinesx(i,3).NE.coil_splinesx(i,1)) .OR. & - (coil_splinesx(i,4).NE.coil_splinesx(i,1))) & - CALL handle_err(KNOT_CONST_ERR, 'read_stellopt_input', i) - IF ((coil_splinesx(i,n-1).NE.coil_splinesx(i,n)) .OR. & - (coil_splinesx(i,n-2).NE.coil_splinesx(i,n)) .OR. & - (coil_splinesx(i,n-3).NE.coil_splinesx(i,n))) & - CALL handle_err(KNOT_CONST_ERR, 'read_stellopt_input', i) - IF ((coil_splinesy(i,2).NE.coil_splinesy(i,1)) .OR. & - (coil_splinesy(i,3).NE.coil_splinesy(i,1)) .OR. & - (coil_splinesy(i,4).NE.coil_splinesy(i,1))) & - CALL handle_err(KNOT_CONST_ERR, 'read_stellopt_input', i) - IF ((coil_splinesy(i,n-1).NE.coil_splinesy(i,n)) .OR. & - (coil_splinesy(i,n-2).NE.coil_splinesy(i,n)) .OR. & - (coil_splinesy(i,n-3).NE.coil_splinesy(i,n))) & - CALL handle_err(KNOT_CONST_ERR, 'read_stellopt_input', i) - ENDIF !n ge 4 - END DO !i - ENDIF !lcoil_spline - - ! REGCOIL winding surface optimization - ! If targeting chi2_b on the plasma boundary AND varying the winding - ! surface Fourier series, then load the nescin file from the regcoil - ! namelist - -!DEC$ IF DEFINED (REGCOIL) - IF ( ANY(sigma_regcoil_chi2_b < bigno) .and. & - ( ANY(lregcoil_rcws_rbound_c_opt) .or. ANY(lregcoil_rcws_rbound_s_opt) .or. & - ANY(lregcoil_rcws_zbound_c_opt) .or. ANY(lregcoil_rcws_zbound_s_opt) ) ) THEN - rc_nfp = regcoil_num_field_periods - regcoil_rcws_rbound_c = 0 - regcoil_rcws_rbound_s = 0 - regcoil_rcws_zbound_c = 0 - regcoil_rcws_zbound_s = 0 - IF (myid == master) THEN - WRITE(6,*) '<----REGCOIL: Reading NESCIN Spectrum from file' - end if - !call regcoil_read_nescin_spectrum(regcoil_nescin_filename, (myid == master)) - verbose = (myid == master) - ! We need to read geometry_option_coil and nescin_filename from the input namelist before the coil surface can be loaded. - CALL safe_open(iunit, istat, TRIM(filename), 'old', 'formatted') - READ(iunit, nml=regcoil_nml, iostat=istat) - CLOSE(iunit) - call regcoil_init_coil_surface() - IF (myid == master) THEN - WRITE(6,*) '<----REGCOIL: Initializing winding surface with NESCIN Spectrum' - end if - !call regcoil_initupdate_nescin_coil_surface((myid == master)) - ! parse the rc_(r/z)mn(c/s)_stellopt arrays and populate the regcoil_rcws_(r/z)bound_(c/s) 2D arrays - !do ii = -mpol_rcws,mpol_rcws - ! do jj = -ntor_rcws,ntor_rcws - ! regcoil_rcws_rbound_c(ii, jj) = rc_rmnc_stellopt(ii,jj) - ! regcoil_rcws_rbound_s(ii, jj) = rc_rmns_stellopt(ii,jj) - ! regcoil_rcws_zbound_c(ii, jj) = rc_zmnc_stellopt(ii,jj) - ! regcoil_rcws_zbound_s(ii, jj) = rc_zmns_stellopt(ii,jj) - ! end do - !end do - do imn = 1, mnmax_coil - m = xm_coil(imn) - n = xn_coil(imn)/(-regcoil_num_field_periods) ! Convert from regcoil/vmec to nescin convention - IF (m < -mpol_rcws .or. m > mpol_rcws .or. n < -ntor_rcws .or. n > ntor_rcws) THEN - WRITE(6,*) "Error! (m,n) values in nescin file exceed mpol_rcws or ntor_rcws." - WRITE(6,*) "mpol_rcws=",mpol_rcws," ntor_rcws=",ntor_rcws - WRITE(6,*) "m=",m," n=",n - STOP - END IF - regcoil_rcws_rbound_c(m, n) = rmnc_coil(imn) - regcoil_rcws_rbound_s(m, n) = rmns_coil(imn) - regcoil_rcws_zbound_c(m, n) = zmnc_coil(imn) - regcoil_rcws_zbound_s(m, n) = zmns_coil(imn) - end do - - if (myid==master) then - WRITE(6,*) '<----STELLOPT_INPUT_MOD: Finished parsing nescoil data and', & - ' assigning stellopt variables' - end if - END IF -!DEC$ ENDIF - ! End of REGCOIL winding surface optimization initializion steps - ! If fixed boundary optimization or mapping turn off restart IF (ANY(ANY(lbound_opt,2),1) .or. opt_type=='map') lno_restart = .true. ! Test for proper normalization on ne profile @@ -1201,283 +1087,6 @@ SUBROUTINE read_stellopt_input(filename, istat, ithread) ne_opt = ne_opt / ne_norm ne_aux_f = ne_aux_f / ne_norm END IF - - ! Print code messages - CALL tolower(equil_type) - IF ((myid == master) .and. (TRIM(equil_type(1:4)) == 'vmec') ) THEN - WRITE(6,*) " Equilibrium calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A)") "========= Parallel Variational Moments Equilibrium Code (v "//TRIM(version_vmec)//") =========" - WRITE(6,"(2X,A)") "========= (S. Hirshman, J. Whitson) =========" - WRITE(6,"(2X,A)") "========= http://vmecwiki.pppl.wikispaces.net/VMEC =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ IF DEFINED (BEAMS3D_OPT) - IF (myid == master .and. ANY(sigma_orbit < bigno) ) THEN - WRITE(6,*) " Energetic Particle calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A,F5.2,A)") "========= BEAMS3D (v",BEAMS3D_VERSION,") =========" - WRITE(6,"(2X,A)") "========= (M. McMillan, S. Lazerson) =========" - WRITE(6,"(2X,A)") "========= lazerson@pppl.gov =========" - WRITE(6,"(2X,A)") "========= http://vmecwiki.pppl.wikispaces.net/BEAMS3D =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ ELSE - IF (ANY(sigma_orbit < bigno)) THEN - sigma_orbit = bigno - IF (myid == master) THEN - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' STELLOPT has not been linked to the BEAMS3D code. ' - WRITE(6,*) ' Optimization of particle orbits not possible.' - WRITE(6,*) ' Disabling energetic particle targets.' - END IF - END IF -!DEC$ ENDIF - IF (myid == master .and. ANY(sigma_bootstrap < bigno)) THEN - WRITE(6,*) " Bootstrap calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A,A,A)") "========= BOOTSJ (v",version_,") =========" - WRITE(6,"(2X,A)") "========= (J. Tolliver, K. Shaing, P. Moroz) =========" - WRITE(6,"(2X,A)") "========= http://vmecwiki.pppl.wikispaces.net/BOOTSJ =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF - IF (myid == master .and. ANY(sigma_balloon < bigno)) THEN - WRITE(6,*) " Ballooning stability calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A,F5.2,A)") "========= COBRAVMEC (v",4.10,") =========" - WRITE(6,"(2X,A)") "========= (R. Sanchez, S. Hirshman) =========" - WRITE(6,"(2X,A)") "========= raul.sanchez@uc3m.es =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ IF DEFINED (TERPSICHORE) - IF (myid == master .and. ANY(sigma_kink < bigno)) THEN - WRITE(6,*) " Kink stability calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A,F5.2,A)") "========= TERPSICHORE (v2016) =========" - WRITE(6,"(2X,A)") "========= (D. V. ANDERSON, W. A. COOPER, R. GRUBER AND U. SCHWENN) =========" - WRITE(6,"(2X,A)") "========= wilfred.cooper@epfl.ch =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ ELSE - IF (ANY(sigma_kink < bigno)) THEN - sigma_kink(:) = bigno - IF (myid == master) THEN - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' STELLOPT has not been linked to the TERPSICHORE code. ' - WRITE(6,*) ' Optimization of kink stability not possible.' - WRITE(6,*) ' Disabling kink stability targets.' - END IF - END IF -!DEC$ ENDIF -!DEC$ IF DEFINED (TRAVIS) - IF (myid == master .and. ANY(sigma_ece < bigno)) THEN - WRITE(6,*) " ECE Radiation calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - CALL printversion_sopt_f77 - !WRITE(6,"(2X,A,F5.2,A)") "========= TRAVIS =========" - WRITE(6,"(2X,A)") "========= (N. Marushchenko) =========" - WRITE(6,"(2X,A)") "========= nikolai.marushchenko@ipp.mpg.de =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ ELSE - IF (ANY(sigma_ece < bigno)) THEN - sigma_ece = bigno - IF (myid == master) THEN - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' STELLOPT has not been linked to the TRAVIS code. ' - WRITE(6,*) ' Optimization of ECE Radiation not possible.' - WRITE(6,*) ' Disabling ECE Radiation targets.' - END IF - END IF -!DEC$ ENDIF -!DEC$ IF DEFINED (COILOPTPP) - IF (myid == master .and. (sigma_coil_bnorm < bigno)) THEN - WRITE(6,*) " Stellarator Coil Optimization provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A)") "========= COILOPT++ =========" - WRITE(6,"(2X,A)") "========= (J. Breslau, S. Lazerson) =========" - WRITE(6,"(2X,A)") "========= jbreslau@pppl.gov =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ ELSE - IF (sigma_coil_bnorm < bigno) THEN - sigma_coil_bnorm = bigno - IF (myid == master) THEN - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' Coil optimization with the COILOPT++' - WRITE(6,*) ' code has been disabled. Coil optimziation' - WRITE(6,*) ' has been turned off. Contact your vendor for' - WRITE(6,*) ' further information.' - END IF - END IF -!DEC$ ENDIF -!DEC$ IF DEFINED (REGCOIL) - IF (myid == master .and. (ANY(sigma_regcoil_chi2_b < bigno) .or. & - (sigma_regcoil_current_density < bigno) )) THEN - WRITE(6,*) " Stellarator REGCOIL Optimization provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A)") "========= REGCOIL =========" - WRITE(6,"(2X,A)") "========= (M. Landreman) =========" - WRITE(6,"(2X,A)") "========= Matt dot Landreman at gmail dot com =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ ELSE - IF (myid == master .and. (ANY(sigma_regcoil_chi2_b < bigno) .or. & - (sigma_regcoil_current_density < bigno) ) ) THEN - sigma_regcoil_chi2_b = bigno - sigma_regcoil_current_density = bigno - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' Coil optimization with the REGCOIL' - WRITE(6,*) ' code has been disabled. Coil optimziation' - WRITE(6,*) ' has been turned off. Contact your vendor for' - WRITE(6,*) ' further information.' - END IF -!DEC$ ENDIF -!DEC$ IF DEFINED (DKES_OPT) - IF (myid == master .and. ( ANY(sigma_dkes < bigno) .or. & - ANY(sigma_dkes_Erdiff < bigno) .or. & - ANY(sigma_dkes_alpha < bigno) ) ) THEN - WRITE(6,*) " Drift-Kinetic Equation Solver (DKES) provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A)") "========= Drift Kinetic Equation Solver, Variational =========" - WRITE(6,"(2X,A)") "========= (S.Hirshman, W. van Rij) =========" - WRITE(6,"(2X,A)") "========= hirshmansp@ornl.gov =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ ELSE - IF (ANY(sigma_dkes < bigno) .or. ANY(sigma_dkes_Erdiff < bigno) .or. ANY(sigma_dkes_alpha < bigno)) THEN - sigma_dkes(:) = bigno - sigma_dkes_Erdiff(:) = bigno - sigma_dkes_alpha(:) = bigno - IF (myid == master) THEN - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' Drift-kinetic optimization with the DKES' - WRITE(6,*) ' code has been disabled. Drift-kinetic optimziation' - WRITE(6,*) ' has been turned off. Contact your vendor for' - WRITE(6,*) ' further information.' - END IF - END IF -!DEC$ ENDIF - IF (myid == master .and. (ANY(sigma_fluxloop < bigno) .or. ANY(sigma_bprobe < bigno) .or. ANY(sigma_segrog < bigno) )) THEN - WRITE(6,*) " Magnetic Diagnostic calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A,F5.2,A)") "========= DIAGNO (v",DIAGNO_VERSION,") =========" - WRITE(6,"(2X,A)") "========= (S.Lazerson, H Gardner, J. Geiger) =========" - WRITE(6,"(2X,A)") "========= lazerson@pppl.gov =========" - WRITE(6,"(2X,A)") "========= http://vmecwiki.pppl.wikispaces.net/DIAGNO =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ IF DEFINED (NEO_OPT) - IF (myid == master .and. ANY(sigma_neo < bigno)) THEN - WRITE(6,*) " Neoclassical Transport calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A)") "========= NEO (v3.02) =========" - WRITE(6,"(2X,A)") "========= (W.Kernbichler and S.Kasilov) =========" - WRITE(6,"(2X,A)") "========= kernbichler@itp.tu-graz.ac.at =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ ELSE - IF (ANY(sigma_neo < bigno)) THEN - sigma_neo(:) = bigno - IF (myid == master) THEN - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' Neoclassical transport optimization with the NEO' - WRITE(6,*) ' code has been disabled. Neoclassical optimziation' - WRITE(6,*) ' has been turned off. Contact your vendor for' - WRITE(6,*) ' further information.' - END IF - END IF -!DEC$ ENDIF -!DEC$ IF DEFINED (TXPORT_OPT) - IF (myid == master .and. ANY(sigma_txport < bigno)) THEN - WRITE(6,*) " Geometry Interface to Turbulent Transport provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A)") "========= Geometry Interface for Stellarators and Tokamaks =========" - WRITE(6,"(2X,A)") "========= (P.Xanthopoulos, W.A.Cooper, and Yu.Turkin) =========" - WRITE(6,"(2X,A)") "========= pax@ipp.mpg.de http://www.ipp.mpg.de/~pax/ =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - WRITE(6,"(2X,A)") " NOTICE: New TXPORT variables now used to control execution COORDINATES," - WRITE(6,"(2X,A)") " IN_OUT, and SETUP namelists are ignored. LGLOBAL_TXPORT," - WRITE(6,"(2X,A)") " NZ_TXPORT, NALPHA_TXPORT, ALPHA0_TXPORT have been added to the" - WRITE(6,"(2X,A)") " OPTIMUM namelist." - WRITE(6,*) " " - END IF -!DEC$ ELSE - IF (ANY(sigma_txport < bigno)) THEN - sigma_txport(:) = bigno - IF (myid == master) THEN - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' Turbulent transport optimization with the GIST/TXPORT' - WRITE(6,*) ' code has been disabled. Turbulent optimziation' - WRITE(6,*) ' has been turned off. Contact your vendor for' - WRITE(6,*) ' further information.' - END IF - END IF -!DEC$ ENDIF -!DEC$ IF DEFINED (AEOPT) - CALL tolower(txport_proxy) - IF (myid == master .and. ANY(sigma_txport < bigno) .and. (TRIM(txport_proxy(1:11)) == 'availenergy') ) THEN - WRITE(6,*) " Turbulent Transport calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A)") "========= Trapped Particle Available Energy Code =========" - WRITE(6,"(2X,A)") "========= (R. Mackenbach, S. Lazerson, J. Proll) =========" - WRITE(6,"(2X,A)") "========= https://github.com/RalfMackenbach/STELLOPT_AE =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ ELSE - CALL tolower(txport_proxy) - IF (ANY(sigma_txport < bigno) .and. (TRIM(txport_proxy(1:11)) == 'availenergy')) THEN - txport_proxy = 'prox1d' - IF (myid == master) THEN - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' STELLOPT has not been linked to the Available Energy code. ' - WRITE(6,*) ' Optimization with Available Energy for turblent' - WRITE(6,*) ' transport not possible. Defaulting to proxy function' - WRITE(6,*) ' txport_proxy = prox1d' - WRITE(6,*) ' Code Available at:' - WRITE(6,*) ' https://github.com/RalfMackenbach/STELLOPT_AE' - END IF - END IF -!DEC$ ENDIF -!DEC$ IF DEFINED (GENE) - CALL tolower(txport_proxy) - IF (myid == master .and. ANY(sigma_txport < bigno) .and. (TRIM(txport_proxy(1:4)) == 'gene') ) THEN - WRITE(6,*) " Turbulent Transport calculation provided by: " - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,"(2X,A)") "========= Gyrokinetic Electromagnetic Numerical Experiment =========" - WRITE(6,"(2X,A)") "========= (F. Jenko, P. Xanthopoulos) =========" - WRITE(6,"(2X,A)") "========= http://www2.ipp.mpg.de/~fsj/gene/ =========" - WRITE(6,"(2X,A)") "========= GENE11 (git-branch "//release_gene//") =========" - WRITE(6,"(2X,A)") "========= (git-master: "//svn_gene//") =========" - WRITE(6,"(2X,A)") "=================================================================================" - WRITE(6,*) " " - END IF -!DEC$ ELSE - CALL tolower(txport_proxy) - IF (ANY(sigma_txport < bigno) .and. (TRIM(txport_proxy(1:4)) == 'gene')) THEN - txport_proxy = 'prox1d' - IF (myid == master) THEN - WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' - WRITE(6,*) ' STELLOPT has not been linked to the GENE code. ' - WRITE(6,*) ' Optimization with linear GENE for turblent' - WRITE(6,*) ' transport not possible. Defaulting to proxy function' - WRITE(6,*) ' txport_proxy = prox1d' - END IF - END IF -!DEC$ ENDIF ! Force some behavior lbooz(1) = .FALSE. target_balloon(1) = 0.0; sigma_balloon(1) = bigno @@ -2963,6 +2572,26 @@ SUBROUTINE write_optimum_namelist(iunit,istat) RETURN END SUBROUTINE write_optimum_namelist + SUBROUTINE write_optimum_namelist_byfile(filename) + CHARACTER(LEN=*), INTENT(in) :: filename + INTEGER :: iunit, istat + LOGICAL :: lexists + + iunit = 100 + istat = 0 + INQUIRE(FILE=TRIM(filename),exist=lexists) + IF (lexists) THEN + OPEN(unit=iunit, file=TRIM(filename), iostat=istat, status="old", position="append") + ELSE + OPEN(unit=iunit, file=TRIM(filename), iostat=istat, status="new") + END IF + IF (istat .ne. 0) RETURN + CALL write_optimum_namelist(iunit,istat) + CLOSE(iunit) + + RETURN + END SUBROUTINE write_optimum_namelist_byfile + SUBROUTINE write_stel_lvar_vec(iunit,lvar,var_min,var_max,dvar,str_name,n1,n2) IMPLICIT NONE INTEGER, INTENT(in) :: iunit, n1, n2 diff --git a/STELLOPTV2/Sources/Modules/stellopt_targets.f90 b/LIBSTELL/Sources/STELLOPT/stellopt_targets.f90 similarity index 100% rename from STELLOPTV2/Sources/Modules/stellopt_targets.f90 rename to LIBSTELL/Sources/STELLOPT/stellopt_targets.f90 diff --git a/STELLOPTV2/Sources/Modules/stellopt_vars.f90 b/LIBSTELL/Sources/STELLOPT/stellopt_vars.f90 similarity index 99% rename from STELLOPTV2/Sources/Modules/stellopt_vars.f90 rename to LIBSTELL/Sources/STELLOPT/stellopt_vars.f90 index ebb82b8e8..ba6c2f9f6 100644 --- a/STELLOPTV2/Sources/Modules/stellopt_vars.f90 +++ b/LIBSTELL/Sources/STELLOPT/stellopt_vars.f90 @@ -14,7 +14,7 @@ MODULE stellopt_vars !----------------------------------------------------------------------- USE vparams, ONLY: ndatafmax, mpol1d, ntord USE vsvd0 - USE windingsurface, ONLY : maxwindsurf + USE stellopt_globals, ONLY : maxwindsurf !----------------------------------------------------------------------- ! Module Variables ! nfunc_max Maximum number of function evaluations @@ -239,8 +239,6 @@ MODULE stellopt_vars CHARACTER, DIMENSION(nigroup) :: coil_type ! Specifies coil topology INTEGER, DIMENSION(nigroup) :: coil_surf ! Assoc. winding surf index - - REAL(rprec) :: phiedge_old ! For keeping track of phiedge INTEGER, PARAMETER :: norm_dex = -5 diff --git a/LIBSTELL/makelibstell b/LIBSTELL/makelibstell index 3ccb226ab..36c3a9a34 100644 --- a/LIBSTELL/makelibstell +++ b/LIBSTELL/makelibstell @@ -8,7 +8,7 @@ SPATH = ../Sources #Contains list of source files (.o) and dependencies DEPLIST = ../LIBSTELL.dep OBJLIST = ../ObjectList -VPATH = $(SPATH):$(SPATH)/Coils:$(SPATH)/Ezcdf:$(SPATH)/FFTpack:$(SPATH)/GMRes:$(SPATH)/Lsode:$(SPATH)/Miscel:$(SPATH)/Modules:$(SPATH)/NumerMeth:$(SPATH)/Optimization:$(SPATH)/Pspline:$(SPATH)/NCLASS +VPATH = $(SPATH):$(SPATH)/Coils:$(SPATH)/Ezcdf:$(SPATH)/FFTpack:$(SPATH)/GMRes:$(SPATH)/Lsode:$(SPATH)/Miscel:$(SPATH)/Modules:$(SPATH)/NumerMeth:$(SPATH)/Optimization:$(SPATH)/Pspline:$(SPATH)/NCLASS:$(SPATH)/STELLOPT #Includes source files and dependency list include $(DEPLIST) diff --git a/STELLOPTV2/ObjectList b/STELLOPTV2/ObjectList index b320995a2..b2b460980 100644 --- a/STELLOPTV2/ObjectList +++ b/STELLOPTV2/ObjectList @@ -1,4 +1,6 @@ ObjectFiles = \ +stellopt_read_cws.o \ +stellopt_write_header.o \ chisq_dkes_alpha.o \ chisq_dkes_erdiff.o \ chisq_line_visbrem.o \ @@ -121,10 +123,7 @@ stellopt_dkes.o \ stellopt_prof_refit.o \ stellopt_travis.o \ stellopt_load_equil.o \ -stellopt_vars.o \ equil_utils.o \ -stellopt_input_mod.o \ equil_vals.o \ stellopt_runtime.o \ -stellopt_targets.o \ stellopt_mango.o diff --git a/STELLOPTV2/STELLOPTV2.dep b/STELLOPTV2/STELLOPTV2.dep index a4ab0153c..0cf028067 100644 --- a/STELLOPTV2/STELLOPTV2.dep +++ b/STELLOPTV2/STELLOPTV2.dep @@ -1,37 +1,52 @@ # Microsoft Developer Studio Generated Dependency File, included by STELLOPT.mak -stellopt_vars.o : \ - stellopt_winding_surface.o +stellopt_read_cws.o : \ + stellopt_runtime.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + stellopt_winding_surface.o \ + $(LIB_DIR)/$(LOCTYPE)/stel_kinds.o \ + $(LIB_DIR)/$(LOCTYPE)/mpi_params.o + +stellopt_write_header.o : \ + stellopt_runtime.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/mpi_params.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_runtime.o \ + $(BEAMS3D_DIR)/$(LOCTYPE)/beams3d_runtime.o \ + $(VMEC_DIR)/$(LOCTYPE)/vmec_params.o \ + $(BOOTSJ_DIR)/$(LOCTYPE)/vmec0.o stellopt_write_auxfiles.o : \ stellopt_runtime.o \ equil_utils.o \ - stellopt_input_mod.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o stellopt_write_eqfile.o : \ - stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ stellopt_runtime.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_inc.o \ $(LIB_DIR)/$(LOCTYPE)/read_wout_mod.o stellopt_write_inputfile.o : \ - stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ stellopt_runtime.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_input_mod.o \ $(LIB_DIR)/$(LOCTYPE)/bootsj_input.o \ $(NEO_DIR)/$(LOCTYPE)/neo_input_mod.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o stellopt_init_mpi.o : \ - stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ stellopt_runtime.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_params.o stellopt_renorm.o : \ - stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ stellopt_runtime.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_params.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_inc.o @@ -43,97 +58,97 @@ stellopt_vmec_bcast.o : \ chisq_orbit.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_gamma_c.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ equil_vals.o \ - stellopt_input_mod.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o chisq_kappa.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ $(LIB_DIR)/$(LOCTYPE)/stel_tools.o \ equil_utils.o chisq_kappa_box.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ $(LIB_DIR)/$(LOCTYPE)/stel_tools.o \ equil_utils.o chisq_kappa_avg.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ $(LIB_DIR)/$(LOCTYPE)/stel_tools.o \ equil_utils.o chisq_kink.o : \ stellopt_runtime.o \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o chisq_aspect.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_aspect_max.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_balloon.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_beta.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_betapol.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_betator.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_bmax.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/read_boozer_mod.o chisq_bmin.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/read_boozer_mod.o chisq_coil_bnorm.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_params.o @@ -141,53 +156,53 @@ chisq_coil_bnorm.o : \ chisq_regcoil_chi2_b.o : \ stellopt_runtime.o \ - stellopt_targets.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_vals.o chisq_rosenbrock.o : \ stellopt_runtime.o \ - stellopt_targets.o \ - stellopt_input_mod.o \ - stellopt_vars.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o chisq_rbtor.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_b0.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_r0.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_z0.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_curvature.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ equil_vals.o chisq_bootstrap.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(BOOTSJ_DIR)/$(LOCTYPE)/parambs.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o @@ -195,7 +210,7 @@ chisq_bootstrap.o : \ chisq_txport.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ $(LIB_DIR)/$(LOCTYPE)/gist_mod.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o @@ -203,312 +218,312 @@ chisq_txport.o : \ chisq_jdotb.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_jcurv.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_magwell.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_bprobes.o : \ stellopt_runtime.o \ - stellopt_targets.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_input_mod.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o chisq_curtor.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_curtor_max.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_extcur.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_fluxloops.o : \ stellopt_runtime.o \ - stellopt_targets.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_input_mod.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o chisq_helicity.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ $(LIB_DIR)/$(LOCTYPE)/read_boozer_mod.o chisq_helicity_ornl.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ $(LIB_DIR)/$(LOCTYPE)/read_boozer_mod.o chisq_resjac.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/read_boozer_mod.o chisq_iota.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ equil_vals.o chisq_vaciota.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ equil_vals.o chisq_jstar.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/read_boozer_mod.o chisq_line_ne.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_line_zeff.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_line_visbrem.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_ece.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_line_te.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_line_ti.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_xics.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_xics_bright.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_xics_w3.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_xics_v.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_faraday.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_mse.o : \ stellopt_runtime.o \ - stellopt_targets.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/biotsavart.o chisq_neo.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_dkes.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ $(DKES_DIR)/$(LOCTYPE)/dkes_realspace.o chisq_dkes_erdiff.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ $(DKES_DIR)/$(LOCTYPE)/dkes_realspace.o chisq_dkes_alpha.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ $(DKES_DIR)/$(LOCTYPE)/dkes_realspace.o chisq_ne.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_te.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_ti.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_vphi.o : \ stellopt_runtime.o \ - stellopt_targets.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_utils.o chisq_phiedge.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_pmin.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_press.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_pressprime.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_gradp_max.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_segrog.o : \ stellopt_runtime.o \ - stellopt_targets.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_input_mod.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o chisq_separatrix.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_sxr.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_limiter.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o chisq_vessel.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/vessel_mod.o chisq_volume.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_wp.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o chisq_curvature_p2.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ $(LIB_DIR)/$(LOCTYPE)/read_wout_mod.o stellopt_balloon.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ $(COBRA_DIR)/$(LOCTYPE)/readin_data.o \ $(COBRA_DIR)/$(LOCTYPE)/ballooning_data.o stellopt_bootsj.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(BOOZ_DIR)/$(LOCTYPE)/booz_persistent.o \ $(LIB_DIR)/$(LOCTYPE)/bootsj_input.o \ @@ -520,9 +535,9 @@ stellopt_bootsj.o : \ stellopt_sfincs.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(BOOZ_DIR)/$(LOCTYPE)/booz_persistent.o \ $(LIB_DIR)/$(LOCTYPE)/bootsj_input.o \ @@ -534,9 +549,9 @@ stellopt_sfincs.o : \ stellopt_txport.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ equil_utils.o \ $(BOOZ_DIR)/$(LOCTYPE)/booz_persistent.o \ @@ -546,9 +561,9 @@ stellopt_txport.o : \ stellopt_prof_to_vmec.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/stel_kinds.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o @@ -556,12 +571,12 @@ stellopt_prof_to_vmec.o : \ stellopt_magdiags.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_input_mod.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_runtime.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_runtime.o \ $(LIB_DIR)/$(LOCTYPE)/virtual_casing_mod.o \ $(LIB_DIR)/$(LOCTYPE)/biotsavart.o \ $(LIB_DIR)/$(LOCTYPE)/read_wout_mod.o \ @@ -578,9 +593,9 @@ stellopt_fieldlines.o : \ stellopt_fcn.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/stel_kinds.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o \ @@ -590,25 +605,15 @@ stellopt_fcn.o : \ stellopt_main.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ $(LIB_DIR)/$(LOCTYPE)/mgrid_mod.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_params.o -stellopt_input_mod.o : \ - stellopt_winding_surface.o \ - equil_utils.o \ - stellopt_runtime.o \ - stellopt_vars.o \ - stellopt_targets.o \ - $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o \ - $(LIB_DIR)/$(LOCTYPE)/stel_kinds.o - - stellopt_init.o : \ stellopt_runtime.o \ - stellopt_vars.o \ - stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o \ @@ -617,8 +622,8 @@ stellopt_init.o : \ stellopt_kink.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_vals.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o \ $(LIB_DIR)/$(LOCTYPE)/read_wout_mod.o \ @@ -627,27 +632,22 @@ stellopt_kink.o : \ stellopt_neo.o : \ stellopt_runtime.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_vals.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ $(LIB_DIR)/$(LOCTYPE)/read_boozer_mod.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o stellopt_runtime.o : \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_globals.o \ $(LIB_DIR)/$(LOCTYPE)/stel_kinds.o -stellopt_targets.o : \ - $(LIB_DIR)/$(LOCTYPE)/stel_kinds.o \ - stellopt_vars.o \ - $(LIB_DIR)/$(LOCTYPE)/vparams.o - - stellopt_travis.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_utils.o @@ -657,8 +657,8 @@ equil_vals.o : \ stellopt_toboozer.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_vals.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o \ @@ -667,7 +667,7 @@ stellopt_toboozer.o : \ stellopt_vboot.o : \ stellopt_runtime.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o \ $(LIB_DIR)/$(LOCTYPE)/read_wout_mod.o \ @@ -676,23 +676,23 @@ stellopt_vboot.o : \ stellopt_dkes.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o stellopt_cas3d.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o stellopt_load_equil.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_vals.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/read_wout_mod.o \ @@ -703,29 +703,29 @@ stellopt_load_equil.o : \ stellopt_load_targets.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o stellopt_init.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_vals.o \ equil_utils.o stellopt_optimize.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o \ $(LIB_DIR)/$(LOCTYPE)/de_mod.o stellopt_paraexe.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_vals.o \ $(VMEC_DIR)/$(LOCTYPE)/vmec_params.o \ $(LIB_DIR)/$(LOCTYPE)/wall_mod.o \ @@ -734,26 +734,26 @@ stellopt_paraexe.o : \ stellopt_prof_refit.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o \ $(LIB_DIR)/$(LOCTYPE)/read_wout_mod.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_input_mod.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_runtime.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_runtime.o \ $(LIB_DIR)/$(LOCTYPE)/biotsavart.o stellopt_clean_up.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o \ $(VMEC_DIR)/$(LOCTYPE)/vmec_params.o \ $(BOOZ_DIR)/$(LOCTYPE)/booz_params.o \ $(LIB_DIR)/$(LOCTYPE)/read_wout_mod.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_input_mod.o \ $(LIB_DIR)/$(LOCTYPE)/gist_mod.o \ $(LIB_DIR)/$(LOCTYPE)/bootsj_input.o \ $(LIB_DIR)/$(LOCTYPE)/fdjac_mod.o \ @@ -762,8 +762,8 @@ stellopt_clean_up.o : \ stellopt_regcoil_chi2_b.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_utils.o @@ -778,7 +778,7 @@ stellopt_reinit_vmec.o : \ stellopt_triangulate.o : \ stellopt_runtime.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o @@ -787,8 +787,8 @@ equil_utils.o : \ $(LIB_DIR)/$(LOCTYPE)/stel_kinds.o \ equil_vals.o \ stellopt_runtime.o \ - stellopt_vars.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_utils.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o \ $(LIB_DIR)/$(LOCTYPE)/vparams.o \ @@ -800,14 +800,14 @@ equil_utils.o : \ stellopt_bnorm.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_params.o stellopt_coiloptpp.o : \ stellopt_runtime.o \ - stellopt_input_mod.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_params.o @@ -817,13 +817,13 @@ equil_vals.o : \ stellopt_orbits.o : \ stellopt_runtime.o \ - stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_params.o stellopt_spline_to_coil.o : \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ equil_utils.o \ $(LIB_DIR)/$(LOCTYPE)/vmec_input.o \ $(LIB_DIR)/$(LOCTYPE)/safe_open_mod.o \ @@ -831,7 +831,7 @@ stellopt_spline_to_coil.o : \ stellopt_coil_to_vac.o : \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ stellopt_runtime.o \ $(MGRID_DIR)/$(LOCTYPE)/write_mgrid.o \ $(MGRID_DIR)/$(LOCTYPE)/makegrid_global.o @@ -852,40 +852,40 @@ stellopt_write_mgrid.o : \ chisq_x.o : \ stellopt_runtime.o \ - stellopt_targets.o \ - stellopt_vars.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o chisq_y.o : \ stellopt_runtime.o \ - stellopt_targets.o \ - stellopt_vars.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o stellopt_mango.o : \ stellopt_runtime.o \ - stellopt_vars.o \ + $(LIB_DIR)/$(LOCTYPE)/stellopt_vars.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_params.o chisq_template.o : \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o chisq_jinvariant.o : \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o chisq_coillen.o : \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o chisq_coilsep.o : \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o chisq_coilcrv.o : \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o chisq_coilself.o : \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o chisq_coiltorvar.o : \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o chisq_coilrect.o : \ - stellopt_targets.o + $(LIB_DIR)/$(LOCTYPE)/stellopt_targets.o diff --git a/STELLOPTV2/Sources/General/stellopt_init.f90 b/STELLOPTV2/Sources/General/stellopt_init.f90 index cc0594a0a..59cdcf4b3 100644 --- a/STELLOPTV2/Sources/General/stellopt_init.f90 +++ b/STELLOPTV2/Sources/General/stellopt_init.f90 @@ -54,7 +54,10 @@ SUBROUTINE stellopt_init ier = 0 ! Read the OPTIMUM Namelist - CALL read_stellopt_input(TRIM(id_string),ier,myid) + CALL init_stellopt_input + CALL read_stellopt_input(TRIM(id_string),ier) + CALL stellopt_read_cws + CALL stellopt_write_header !CALL bcast_vars(master,MPI_COMM_STEL,ierr_mpi) !IF (ierr_mpi /= MPI_SUCCESS) CALL handle_err(MPI_BCAST_ERR,'stellot_init:bcast_vars',ierr_mpi) @@ -267,7 +270,6 @@ SUBROUTINE stellopt_init SELECT CASE (TRIM(equil_type)) CASE('vmec2000','animec','flow','satire','paravmec','parvmec','vboot','vmec2000_oneeq') ! Set some defaults - phiedge_old = phiedge IF (ncurr /= 0 .and. ANY(lai_opt)) lai_opt(:) = .false. IF (ncurr /= 0 .and. ANY(lai_f_opt)) lai_f_opt(:) = .false. IF (ncurr /= 1 .and. lcurtor_opt) lcurtor_opt = .false. diff --git a/STELLOPTV2/Sources/General/stellopt_main.f90 b/STELLOPTV2/Sources/General/stellopt_main.f90 index bedaf4371..26a751244 100644 --- a/STELLOPTV2/Sources/General/stellopt_main.f90 +++ b/STELLOPTV2/Sources/General/stellopt_main.f90 @@ -198,7 +198,10 @@ PROGRAM STELLOPT CALL MPI_FILE_OPEN(MPI_COMM_STEL, TRIM(id_string), & MPI_MODE_RDONLY, MPI_INFO_NULL, key, ierr_mpi ) CALL MPI_FILE_CLOSE(key,ier) - CALL read_stellopt_input(TRIM(id_string),ier,myid) + CALL init_stellopt_input + CALL read_stellopt_input(TRIM(id_string),ier) + CALL stellopt_read_cws + !CALL stellopt_write_header ! Now fix a couple things before we re-run the optimizer id_string = id_string(7:LEN(id_string)) diff --git a/STELLOPTV2/Sources/General/stellopt_paraexe.f90 b/STELLOPTV2/Sources/General/stellopt_paraexe.f90 index 270bb84ea..66ec399fd 100644 --- a/STELLOPTV2/Sources/General/stellopt_paraexe.f90 +++ b/STELLOPTV2/Sources/General/stellopt_paraexe.f90 @@ -78,7 +78,8 @@ SUBROUTINE stellopt_paraexe(in_parameter_1,in_parameter_2,lscreen) NI_AUX_Z_BEAMS => NI_AUX_Z, NI_AUX_M_BEAMS => NI_AUX_Z, & NION_BEAMS => NION, & TI_AUX_S_BEAMS => TI_AUX_S, TI_AUX_F_BEAMS => TI_AUX_F, nprocs_beams, & - ZEFF_AUX_S_BEAMS => ZEFF_AUX_S, ZEFF_AUX_F_BEAMS => ZEFF_AUX_F + ZEFF_AUX_S_BEAMS => ZEFF_AUX_S, ZEFF_AUX_F_BEAMS => ZEFF_AUX_F, & + BEAMS3D_VERSION USE beams3d_lines, ONLY: nparticles_beams => nparticles, R_lines, Z_lines,& PHI_lines, vll_lines, moment_lines, neut_lines USE beams3d_grid, ONLY: nte, nne, nti, B_R, B_PHI, B_Z, raxis, zaxis, phiaxis,& diff --git a/STELLOPTV2/Sources/General/stellopt_read_cws.f90 b/STELLOPTV2/Sources/General/stellopt_read_cws.f90 new file mode 100644 index 000000000..9d72c8542 --- /dev/null +++ b/STELLOPTV2/Sources/General/stellopt_read_cws.f90 @@ -0,0 +1,133 @@ +!----------------------------------------------------------------------- +! Subroutine: stellopt_read_cws +! Authors: S. Lazerson (samuel.lazerson@gauss-fusion.com) +! Date: 05/31/2024 +! Description: This subroutine reads/handles the COILOP++ and +! Regcoil initializations. +!----------------------------------------------------------------------- + SUBROUTINE stellopt_read_cws + USE stel_kinds, ONLY: rprec + USE stellopt_runtime, ONLY: CWS_READ_ERR, KNOT_CONST_ERR, & + KNOT_DEF_ERR, KNOT_MISMATCH_ERR, KNOT_ORDER_ERR, lcoil_geom + USE stellopt_vars + USE stellopt_targets + USE windingsurface + USE mpi_params ! MPI +!DEC$ IF DEFINED (REGCOIL) + USE regcoil_variables, ONLY: rc_nfp => nfp, rmnc_coil, rmns_coil, zmns_coil, zmnc_coil, mnmax_coil, xm_coil, xn_coil, verbose, regcoil_nml +!DEC$ ENDIF + IMPLICIT NONE + INTEGER :: isurf, n, m, imn, i, ierr + + ! Coil Optimization + IF (ANY(ANY(lcoil_spline,2),1)) THEN + lcoil_geom = .true. + + DO isurf=1,maxwindsurf + IF (LEN_TRIM(windsurfname(isurf)).gt.0) THEN + CALL read_winding_surface(windsurfname(isurf), isurf, ierr) + IF (ierr.ne.0) CALL handle_err(CWS_READ_ERR, & + windsurfname(isurf), ierr) + lwindsurf(isurf) = .TRUE. + ENDIF + ENDDO !isurf + + ! Count knots, error check + DO i=1,nigroup + n = COUNT(coil_splinesx(i,:) >= 0.0) + coil_nctrl(i) = n - 4 + IF ((n > 0).AND.(n < 4)) & + CALL handle_err(KNOT_DEF_ERR, 'read_stellopt_input', n) + IF (COUNT(coil_splinesy(i,:) >= 0.0) - 4 .NE. coil_nctrl(i)) & + CALL handle_err(KNOT_MISMATCH_ERR, 'read_stellopt_input', coil_nctrl(i)) + IF ((.NOT.lwindsurf(coil_surf(i))) .AND. (COUNT(coil_splinesz(i,:) >= 0.0) - 4 .NE. coil_nctrl(i))) & + CALL handle_err(KNOT_MISMATCH_ERR, 'read_stellopt_input', coil_nctrl(i)) + IF (ANY(lcoil_spline(i,MAX(coil_nctrl(i)+1,1):maxcoilctrl))) & + CALL handle_err(KNOT_MISMATCH_ERR, 'read_stellopt_input', coil_nctrl(i)) + IF (n.GE.4) THEN + DO m=2,n + IF (coil_splinesx(i,m).LT.coil_splinesx(i,m-1)) & + CALL handle_err(KNOT_ORDER_ERR, 'read_stellopt_input', m) + IF (coil_splinesy(i,m).LT.coil_splinesy(i,m-1)) & + CALL handle_err(KNOT_ORDER_ERR, 'read_stellopt_input', m) + ENDDO + IF ((coil_splinesx(i,2).NE.coil_splinesx(i,1)) .OR. & + (coil_splinesx(i,3).NE.coil_splinesx(i,1)) .OR. & + (coil_splinesx(i,4).NE.coil_splinesx(i,1))) & + CALL handle_err(KNOT_CONST_ERR, 'read_stellopt_input', i) + IF ((coil_splinesx(i,n-1).NE.coil_splinesx(i,n)) .OR. & + (coil_splinesx(i,n-2).NE.coil_splinesx(i,n)) .OR. & + (coil_splinesx(i,n-3).NE.coil_splinesx(i,n))) & + CALL handle_err(KNOT_CONST_ERR, 'read_stellopt_input', i) + IF ((coil_splinesy(i,2).NE.coil_splinesy(i,1)) .OR. & + (coil_splinesy(i,3).NE.coil_splinesy(i,1)) .OR. & + (coil_splinesy(i,4).NE.coil_splinesy(i,1))) & + CALL handle_err(KNOT_CONST_ERR, 'read_stellopt_input', i) + IF ((coil_splinesy(i,n-1).NE.coil_splinesy(i,n)) .OR. & + (coil_splinesy(i,n-2).NE.coil_splinesy(i,n)) .OR. & + (coil_splinesy(i,n-3).NE.coil_splinesy(i,n))) & + CALL handle_err(KNOT_CONST_ERR, 'read_stellopt_input', i) + ENDIF !n ge 4 + END DO !i + ENDIF !lcoil_spline + + ! REGCOIL winding surface optimization + ! If targeting chi2_b on the plasma boundary AND varying the winding + ! surface Fourier series, then load the nescin file from the regcoil + ! namelist + +!DEC$ IF DEFINED (REGCOIL) + IF ( ANY(sigma_regcoil_chi2_b < bigno) .and. & + ( ANY(lregcoil_rcws_rbound_c_opt) .or. ANY(lregcoil_rcws_rbound_s_opt) .or. & + ANY(lregcoil_rcws_zbound_c_opt) .or. ANY(lregcoil_rcws_zbound_s_opt) ) ) THEN + rc_nfp = regcoil_num_field_periods + regcoil_rcws_rbound_c = 0 + regcoil_rcws_rbound_s = 0 + regcoil_rcws_zbound_c = 0 + regcoil_rcws_zbound_s = 0 + IF (myid == master) THEN + WRITE(6,*) '<----REGCOIL: Reading NESCIN Spectrum from file' + end if + !call regcoil_read_nescin_spectrum(regcoil_nescin_filename, (myid == master)) + verbose = (myid == master) + ! We need to read geometry_option_coil and nescin_filename from the input namelist before the coil surface can be loaded. + CALL safe_open(iunit, istat, TRIM(filename), 'old', 'formatted') + READ(iunit, nml=regcoil_nml, iostat=istat) + CLOSE(iunit) + call regcoil_init_coil_surface() + IF (myid == master) THEN + WRITE(6,*) '<----REGCOIL: Initializing winding surface with NESCIN Spectrum' + end if + !call regcoil_initupdate_nescin_coil_surface((myid == master)) + ! parse the rc_(r/z)mn(c/s)_stellopt arrays and populate the regcoil_rcws_(r/z)bound_(c/s) 2D arrays + !do ii = -mpol_rcws,mpol_rcws + ! do jj = -ntor_rcws,ntor_rcws + ! regcoil_rcws_rbound_c(ii, jj) = rc_rmnc_stellopt(ii,jj) + ! regcoil_rcws_rbound_s(ii, jj) = rc_rmns_stellopt(ii,jj) + ! regcoil_rcws_zbound_c(ii, jj) = rc_zmnc_stellopt(ii,jj) + ! regcoil_rcws_zbound_s(ii, jj) = rc_zmns_stellopt(ii,jj) + ! end do + !end do + do imn = 1, mnmax_coil + m = xm_coil(imn) + n = xn_coil(imn)/(-regcoil_num_field_periods) ! Convert from regcoil/vmec to nescin convention + IF (m < -mpol_rcws .or. m > mpol_rcws .or. n < -ntor_rcws .or. n > ntor_rcws) THEN + WRITE(6,*) "Error! (m,n) values in nescin file exceed mpol_rcws or ntor_rcws." + WRITE(6,*) "mpol_rcws=",mpol_rcws," ntor_rcws=",ntor_rcws + WRITE(6,*) "m=",m," n=",n + STOP + END IF + regcoil_rcws_rbound_c(m, n) = rmnc_coil(imn) + regcoil_rcws_rbound_s(m, n) = rmns_coil(imn) + regcoil_rcws_zbound_c(m, n) = zmnc_coil(imn) + regcoil_rcws_zbound_s(m, n) = zmns_coil(imn) + end do + + if (myid==master) then + WRITE(6,*) '<----STELLOPT_INPUT_MOD: Finished parsing nescoil data and', & + ' assigning stellopt variables' + end if + END IF +!DEC$ ENDIF + ! End of REGCOIL winding surface optimization initializion steps + END SUBROUTINE \ No newline at end of file diff --git a/STELLOPTV2/Sources/General/stellopt_write_header.f90 b/STELLOPTV2/Sources/General/stellopt_write_header.f90 new file mode 100644 index 000000000..0d9e448f7 --- /dev/null +++ b/STELLOPTV2/Sources/General/stellopt_write_header.f90 @@ -0,0 +1,302 @@ +!----------------------------------------------------------------------- +! Subroutine: stellopt_write_header +! Authors: S. Lazerson (samuel.lazerson@gauss-fusion.com) +! Date: 05/31/2024 +! Description: This subroutine writest the STELLOPT header +! information. +!----------------------------------------------------------------------- + SUBROUTINE stellopt_write_header + USE stellopt_runtime, ONLY: bigno + USE stellopt_vars, ONLY: equil_type + USE stellopt_targets, ONLY: txport_proxy, sigma_orbit, & + sigma_bootstrap, sigma_balloon, sigma_kink, sigma_ece, & + sigma_coil_bnorm, sigma_regcoil_chi2_b, sigma_dkes, & + sigma_dkes_Erdiff, sigma_dkes_alpha, sigma_fluxloop, & + sigma_bprobe, sigma_segrog, sigma_neo, sigma_txport, & + sigma_regcoil_current_density + USE mpi_params + USE diagno_runtime, ONLY: DIAGNO_VERSION + USE beams3d_runtime, ONLY: BEAMS3D_VERSION + USE vmec_params, ONLY: version_vmec=> version_ + USE vmec0, ONLY: version_bootsj => version_ +!DEC$ IF DEFINED (GENE) + USE par_other, ONLY: svn_gene => git_master, release_gene => git_branch +!DEC$ ENDIF + IMPLICIT NONE + ! Print code messages + CALL tolower(equil_type) + IF ((myid == master) .and. (TRIM(equil_type(1:4)) == 'vmec') ) THEN + WRITE(6,*) " Equilibrium calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A)") "========= Parallel Variational Moments Equilibrium Code (v "//TRIM(version_vmec)//") =========" + WRITE(6,"(2X,A)") "========= (S. Hirshman, J. Whitson) =========" + WRITE(6,"(2X,A)") "========= http://vmecwiki.pppl.wikispaces.net/VMEC =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ IF DEFINED (BEAMS3D_OPT) + IF (myid == master .and. ANY(sigma_orbit < bigno) ) THEN + WRITE(6,*) " Energetic Particle calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A,F5.2,A)") "========= BEAMS3D (v",BEAMS3D_VERSION,") =========" + WRITE(6,"(2X,A)") "========= (M. McMillan, S. Lazerson) =========" + WRITE(6,"(2X,A)") "========= lazerson@pppl.gov =========" + WRITE(6,"(2X,A)") "========= http://vmecwiki.pppl.wikispaces.net/BEAMS3D =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ ELSE + IF (ANY(sigma_orbit < bigno)) THEN + sigma_orbit = bigno + IF (myid == master) THEN + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' STELLOPT has not been linked to the BEAMS3D code. ' + WRITE(6,*) ' Optimization of particle orbits not possible.' + WRITE(6,*) ' Disabling energetic particle targets.' + END IF + END IF +!DEC$ ENDIF + IF (myid == master .and. ANY(sigma_bootstrap < bigno)) THEN + WRITE(6,*) " Bootstrap calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A,A,A)") "========= BOOTSJ (v",version_bootsj,") =========" + WRITE(6,"(2X,A)") "========= (J. Tolliver, K. Shaing, P. Moroz) =========" + WRITE(6,"(2X,A)") "========= http://vmecwiki.pppl.wikispaces.net/BOOTSJ =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF + IF (myid == master .and. ANY(sigma_balloon < bigno)) THEN + WRITE(6,*) " Ballooning stability calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A,F5.2,A)") "========= COBRAVMEC (v",4.10,") =========" + WRITE(6,"(2X,A)") "========= (R. Sanchez, S. Hirshman) =========" + WRITE(6,"(2X,A)") "========= raul.sanchez@uc3m.es =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ IF DEFINED (TERPSICHORE) + IF (myid == master .and. ANY(sigma_kink < bigno)) THEN + WRITE(6,*) " Kink stability calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A,F5.2,A)") "========= TERPSICHORE (v2016) =========" + WRITE(6,"(2X,A)") "========= (D. V. ANDERSON, W. A. COOPER, R. GRUBER AND U. SCHWENN) =========" + WRITE(6,"(2X,A)") "========= wilfred.cooper@epfl.ch =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ ELSE + IF (ANY(sigma_kink < bigno)) THEN + sigma_kink(:) = bigno + IF (myid == master) THEN + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' STELLOPT has not been linked to the TERPSICHORE code. ' + WRITE(6,*) ' Optimization of kink stability not possible.' + WRITE(6,*) ' Disabling kink stability targets.' + END IF + END IF +!DEC$ ENDIF +!DEC$ IF DEFINED (TRAVIS) + IF (myid == master .and. ANY(sigma_ece < bigno)) THEN + WRITE(6,*) " ECE Radiation calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + CALL printversion_sopt_f77 + !WRITE(6,"(2X,A,F5.2,A)") "========= TRAVIS =========" + WRITE(6,"(2X,A)") "========= (N. Marushchenko) =========" + WRITE(6,"(2X,A)") "========= nikolai.marushchenko@ipp.mpg.de =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ ELSE + IF (ANY(sigma_ece < bigno)) THEN + sigma_ece = bigno + IF (myid == master) THEN + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' STELLOPT has not been linked to the TRAVIS code. ' + WRITE(6,*) ' Optimization of ECE Radiation not possible.' + WRITE(6,*) ' Disabling ECE Radiation targets.' + END IF + END IF +!DEC$ ENDIF +!DEC$ IF DEFINED (COILOPTPP) + IF (myid == master .and. (sigma_coil_bnorm < bigno)) THEN + WRITE(6,*) " Stellarator Coil Optimization provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A)") "========= COILOPT++ =========" + WRITE(6,"(2X,A)") "========= (J. Breslau, S. Lazerson) =========" + WRITE(6,"(2X,A)") "========= jbreslau@pppl.gov =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ ELSE + IF (sigma_coil_bnorm < bigno) THEN + sigma_coil_bnorm = bigno + IF (myid == master) THEN + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' Coil optimization with the COILOPT++' + WRITE(6,*) ' code has been disabled. Coil optimziation' + WRITE(6,*) ' has been turned off. Contact your vendor for' + WRITE(6,*) ' further information.' + END IF + END IF +!DEC$ ENDIF +!DEC$ IF DEFINED (REGCOIL) + IF (myid == master .and. (ANY(sigma_regcoil_chi2_b < bigno) .or. & + (sigma_regcoil_current_density < bigno) )) THEN + WRITE(6,*) " Stellarator REGCOIL Optimization provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A)") "========= REGCOIL =========" + WRITE(6,"(2X,A)") "========= (M. Landreman) =========" + WRITE(6,"(2X,A)") "========= Matt dot Landreman at gmail dot com =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ ELSE + IF (myid == master .and. (ANY(sigma_regcoil_chi2_b < bigno) .or. & + (sigma_regcoil_current_density < bigno) ) ) THEN + sigma_regcoil_chi2_b = bigno + sigma_regcoil_current_density = bigno + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' Coil optimization with the REGCOIL' + WRITE(6,*) ' code has been disabled. Coil optimziation' + WRITE(6,*) ' has been turned off. Contact your vendor for' + WRITE(6,*) ' further information.' + END IF +!DEC$ ENDIF +!DEC$ IF DEFINED (DKES_OPT) + IF (myid == master .and. ( ANY(sigma_dkes < bigno) .or. & + ANY(sigma_dkes_Erdiff < bigno) .or. & + ANY(sigma_dkes_alpha < bigno) ) ) THEN + WRITE(6,*) " Drift-Kinetic Equation Solver (DKES) provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A)") "========= Drift Kinetic Equation Solver, Variational =========" + WRITE(6,"(2X,A)") "========= (S.Hirshman, W. van Rij) =========" + WRITE(6,"(2X,A)") "========= hirshmansp@ornl.gov =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ ELSE + IF (ANY(sigma_dkes < bigno) .or. ANY(sigma_dkes_Erdiff < bigno) .or. ANY(sigma_dkes_alpha < bigno)) THEN + sigma_dkes(:) = bigno + sigma_dkes_Erdiff(:) = bigno + sigma_dkes_alpha(:) = bigno + IF (myid == master) THEN + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' Drift-kinetic optimization with the DKES' + WRITE(6,*) ' code has been disabled. Drift-kinetic optimziation' + WRITE(6,*) ' has been turned off. Contact your vendor for' + WRITE(6,*) ' further information.' + END IF + END IF +!DEC$ ENDIF + IF (myid == master .and. (ANY(sigma_fluxloop < bigno) .or. ANY(sigma_bprobe < bigno) .or. ANY(sigma_segrog < bigno) )) THEN + WRITE(6,*) " Magnetic Diagnostic calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A,F5.2,A)") "========= DIAGNO (v",DIAGNO_VERSION,") =========" + WRITE(6,"(2X,A)") "========= (S.Lazerson, H Gardner, J. Geiger) =========" + WRITE(6,"(2X,A)") "========= lazerson@pppl.gov =========" + WRITE(6,"(2X,A)") "========= http://vmecwiki.pppl.wikispaces.net/DIAGNO =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ IF DEFINED (NEO_OPT) + IF (myid == master .and. ANY(sigma_neo < bigno)) THEN + WRITE(6,*) " Neoclassical Transport calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A)") "========= NEO (v3.02) =========" + WRITE(6,"(2X,A)") "========= (W.Kernbichler and S.Kasilov) =========" + WRITE(6,"(2X,A)") "========= kernbichler@itp.tu-graz.ac.at =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ ELSE + IF (ANY(sigma_neo < bigno)) THEN + sigma_neo(:) = bigno + IF (myid == master) THEN + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' Neoclassical transport optimization with the NEO' + WRITE(6,*) ' code has been disabled. Neoclassical optimziation' + WRITE(6,*) ' has been turned off. Contact your vendor for' + WRITE(6,*) ' further information.' + END IF + END IF +!DEC$ ENDIF +!DEC$ IF DEFINED (TXPORT_OPT) + IF (myid == master .and. ANY(sigma_txport < bigno)) THEN + WRITE(6,*) " Geometry Interface to Turbulent Transport provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A)") "========= Geometry Interface for Stellarators and Tokamaks =========" + WRITE(6,"(2X,A)") "========= (P.Xanthopoulos, W.A.Cooper, and Yu.Turkin) =========" + WRITE(6,"(2X,A)") "========= pax@ipp.mpg.de http://www.ipp.mpg.de/~pax/ =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + WRITE(6,"(2X,A)") " NOTICE: New TXPORT variables now used to control execution COORDINATES," + WRITE(6,"(2X,A)") " IN_OUT, and SETUP namelists are ignored. LGLOBAL_TXPORT," + WRITE(6,"(2X,A)") " NZ_TXPORT, NALPHA_TXPORT, ALPHA0_TXPORT have been added to the" + WRITE(6,"(2X,A)") " OPTIMUM namelist." + WRITE(6,*) " " + END IF +!DEC$ ELSE + IF (ANY(sigma_txport < bigno)) THEN + sigma_txport(:) = bigno + IF (myid == master) THEN + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' Turbulent transport optimization with the GIST/TXPORT' + WRITE(6,*) ' code has been disabled. Turbulent optimziation' + WRITE(6,*) ' has been turned off. Contact your vendor for' + WRITE(6,*) ' further information.' + END IF + END IF +!DEC$ ENDIF +!DEC$ IF DEFINED (AEOPT) + CALL tolower(txport_proxy) + IF (myid == master .and. ANY(sigma_txport < bigno) .and. (TRIM(txport_proxy(1:11)) == 'availenergy') ) THEN + WRITE(6,*) " Turbulent Transport calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A)") "========= Trapped Particle Available Energy Code =========" + WRITE(6,"(2X,A)") "========= (R. Mackenbach, S. Lazerson, J. Proll) =========" + WRITE(6,"(2X,A)") "========= https://github.com/RalfMackenbach/STELLOPT_AE =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ ELSE + CALL tolower(txport_proxy) + IF (ANY(sigma_txport < bigno) .and. (TRIM(txport_proxy(1:11)) == 'availenergy')) THEN + txport_proxy = 'prox1d' + IF (myid == master) THEN + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' STELLOPT has not been linked to the Available Energy code. ' + WRITE(6,*) ' Optimization with Available Energy for turblent' + WRITE(6,*) ' transport not possible. Defaulting to proxy function' + WRITE(6,*) ' txport_proxy = prox1d' + WRITE(6,*) ' Code Available at:' + WRITE(6,*) ' https://github.com/RalfMackenbach/STELLOPT_AE' + END IF + END IF +!DEC$ ENDIF +!DEC$ IF DEFINED (GENE) + CALL tolower(txport_proxy) + IF (myid == master .and. ANY(sigma_txport < bigno) .and. (TRIM(txport_proxy(1:4)) == 'gene') ) THEN + WRITE(6,*) " Turbulent Transport calculation provided by: " + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,"(2X,A)") "========= Gyrokinetic Electromagnetic Numerical Experiment =========" + WRITE(6,"(2X,A)") "========= (F. Jenko, P. Xanthopoulos) =========" + WRITE(6,"(2X,A)") "========= http://www2.ipp.mpg.de/~fsj/gene/ =========" + WRITE(6,"(2X,A)") "========= GENE11 (git-branch "//release_gene//") =========" + WRITE(6,"(2X,A)") "========= (git-master: "//svn_gene//") =========" + WRITE(6,"(2X,A)") "=================================================================================" + WRITE(6,*) " " + END IF +!DEC$ ELSE + CALL tolower(txport_proxy) + IF (ANY(sigma_txport < bigno) .and. (TRIM(txport_proxy(1:4)) == 'gene')) THEN + txport_proxy = 'prox1d' + IF (myid == master) THEN + WRITE(6,*) '!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!' + WRITE(6,*) ' STELLOPT has not been linked to the GENE code. ' + WRITE(6,*) ' Optimization with linear GENE for turblent' + WRITE(6,*) ' transport not possible. Defaulting to proxy function' + WRITE(6,*) ' txport_proxy = prox1d' + END IF + END IF +!DEC$ ENDIF + END SUBROUTINE stellopt_write_header \ No newline at end of file diff --git a/STELLOPTV2/Sources/Modules/stellopt_runtime.f90 b/STELLOPTV2/Sources/Modules/stellopt_runtime.f90 index a6e2857b4..8cab35203 100644 --- a/STELLOPTV2/Sources/Modules/stellopt_runtime.f90 +++ b/STELLOPTV2/Sources/Modules/stellopt_runtime.f90 @@ -146,6 +146,11 @@ MODULE stellopt_runtime ! Libraries !----------------------------------------------------------------------- USE stel_kinds, ONLY: rprec + USE stellopt_globals, ONLY: axis_init_option, cr_strategy, & + epsfcn, factor, ftol, gtol, lcentered_differences, lkeep_mins, & + lrefit, mode, noptimizers, npopulation, opt_type, refit_param, & + rho_exp, xtol, bigno, lcoil_geom, lno_restart, ltriangulate, & + maxwindsurf USE EZspline !----------------------------------------------------------------------- ! Module Variables @@ -195,27 +200,33 @@ MODULE stellopt_runtime INTEGER, PARAMETER :: MPI_BCAST_ERR = 830 INTEGER, PARAMETER :: MPI_FREE_ERR = 840 INTEGER, PARAMETER :: MPI_FINE_ERR = 890 + + !INTEGER, PARAMETER :: maxwindsurf=32 + REAL(rprec), PARAMETER :: STELLOPT_VERSION = 2.85 + !REAL(rprec), PARAMETER :: bigno = 1.0E+10 - LOGICAL :: lverb, lkeep_mins, lneed_output, lrestart,& - lrefit, lno_restart, lauto_domain, lparallel,& - ltriangulate, lcoil_geom, lrenorm - INTEGER :: nvars, mtargets, iter, mode, iunit_out,& - cr_strategy, rho_exp, npopulation, noptimizers,& - ier_paraexe +! LOGICAL :: lverb, lkeep_mins, lneed_output, lrestart,& +! lrefit, lno_restart, lauto_domain, lparallel,& +! ltriangulate, lcoil_geom, lrenorm + LOGICAL :: lverb, lneed_output, lrestart,& + lauto_domain, lparallel,lrenorm +! INTEGER :: nvars, mtargets, iter, mode, iunit_out,& +! cr_strategy, rho_exp, npopulation, noptimizers,& +! ier_paraexe + INTEGER :: nvars, mtargets, iter, iunit_out,ier_paraexe INTEGER, ALLOCATABLE :: var_dex(:),target_dex(:) INTEGER, ALLOCATABLE :: arr_dex(:,:) - REAL(rprec) :: pi, pi2, mu0, ftol, xtol, gtol, epsfcn,& - factor, chisq_min, refit_param, pct_domain +! REAL(rprec) :: pi, pi2, mu0, ftol, xtol, gtol, epsfcn,& +! factor, chisq_min, refit_param, pct_domain + REAL(rprec) :: pi, pi2, mu0, chisq_min, pct_domain REAL(rprec), ALLOCATABLE :: vars(:),targets(:),sigmas(:),vals(:),& diag(:),vars_min(:),vars_max(:) - CHARACTER(256) :: id_tag, id_string, opt_type, proc_string, & +! CHARACTER(256) :: id_tag, id_string, opt_type, proc_string, & +! proc_string_old, screen_str, xvec_file + CHARACTER(256) :: id_tag, id_string, proc_string, & proc_string_old, screen_str, xvec_file - LOGICAL :: lcentered_differences ! Available for MANGO algorithms - CHARACTER(256) :: axis_init_option - - REAL(rprec), PARAMETER :: STELLOPT_VERSION = 2.85 - - REAL(rprec), PARAMETER :: bigno = 1.0E+10 +! LOGICAL :: lcentered_differences ! Available for MANGO algorithms +! CHARACTER(256) :: axis_init_option !----------------------------------------------------------------------- ! Subroutines ! handle_err Controls Program Termination diff --git a/STELLOPTV2/Sources/Modules/stellopt_winding_surface.f90 b/STELLOPTV2/Sources/Modules/stellopt_winding_surface.f90 index f84019662..d7d8457ef 100644 --- a/STELLOPTV2/Sources/Modules/stellopt_winding_surface.f90 +++ b/STELLOPTV2/Sources/Modules/stellopt_winding_surface.f90 @@ -2,10 +2,9 @@ ! J. Breslau 8/18/17 MODULE windingsurface USE stel_kinds, ONLY : rprec + USE stellopt_runtime, ONLY: maxwindsurf IMPLICIT NONE - INTEGER, PARAMETER :: maxwindsurf=32 - TYPE vsurf REAL(rprec), DIMENSION(:,:), ALLOCATABLE :: rctab, zstab INTEGER :: mmax, nmax, nfp diff --git a/THRIFT/THRIFT.dep b/THRIFT/THRIFT.dep index fb15ce101..f93470d1c 100644 --- a/THRIFT/THRIFT.dep +++ b/THRIFT/THRIFT.dep @@ -28,8 +28,8 @@ thrift_diagno.o : \ thrift_runtime.o \ thrift_vars.o \ thrift_equil.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_input_mod.o \ - $(DIAGNO_DIR)/$(LOCTYPE)/diagno_runtime.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_input_mod.o \ + $(LIB_DIR)/$(LOCTYPE)/diagno_runtime.o \ $(LIB_DIR)/$(LOCTYPE)/biotsavart.o \ $(LIB_DIR)/$(LOCTYPE)/virtual_casing_mod.o \ $(LIB_DIR)/$(LOCTYPE)/mpi_inc.o \ diff --git a/pySTEL/FIELDLINESplot.py b/pySTEL/FIELDLINESplot.py index bfef1c80f..8dfec4b66 100755 --- a/pySTEL/FIELDLINESplot.py +++ b/pySTEL/FIELDLINESplot.py @@ -1,24 +1,25 @@ #!/usr/bin/env python3 import sys, os -os.environ['ETS_TOOLKIT'] = 'qt4' +os.environ['ETS_TOOLKIT'] = 'qt5' import matplotlib -matplotlib.use("Qt4Agg") +matplotlib.use("Qt5Agg") import matplotlib.pyplot as _plt import numpy as np #For Arrays import numpy.matlib from math import pi #QT4 -from PyQt4 import uic, QtGui -from PyQt4.QtGui import QMainWindow, QApplication, qApp, QVBoxLayout, QSizePolicy,QIcon -from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas +#from PyQt4 import uic, QtGui +#from PyQt4.QtGui import QMainWindow, QApplication, qApp, QVBoxLayout, QSizePolicy,QIcon +#from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas #QT5 -#from PyQt5 import uic, QtGui, QtWidgets -#from PyQt5.QtWidgets import QMainWindow, QApplication, QVBoxLayout, QSizePolicy -#from PyQt5.QtGui import QIcon -#from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas -from libstell.fieldlines import read_fieldlines, calc_iota, calc_reff +from PyQt5 import uic, QtGui, QtWidgets +from PyQt5.QtWidgets import QMainWindow, QApplication, QVBoxLayout, QSizePolicy +from PyQt5.QtGui import QIcon +# Matplotlib +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure from mpl_toolkits import mplot3d +from libstell import fieldlines try: qtCreatorPath=os.environ["STELLOPT_PATH"] @@ -26,7 +27,7 @@ print("Please set environment variable STELLOPT_PATH") sys.exit(1) -qtCreatorFile = qtCreatorPath+"/pySTEL/FIELDLINESplot.ui" # Enter file here. +qtCreatorFile = os.path.join(qtCreatorPath,'pySTEL','FIELDLINESplot.ui') Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile) class MyApp(QMainWindow): @@ -46,15 +47,16 @@ def __init__(self): if(name[0:10]=='fieldlines'): self.ui.FileName.addItem(name) # Init - self.fieldlines_data=read_fieldlines(self.ui.FileName.currentText()) + self.fieldlines_data=fieldlines.FIELDLINES() + self.fieldlines_data.read_fieldlines(self.ui.FileName.currentText()) self.ui.PlotList.addItems(self.ui.plot_list) self.ui.PlotButtons.setEnabled(0) - self.nlines = self.fieldlines_data['nlines'] - self.npoinc = self.fieldlines_data['npoinc'] - self.nsteps = self.fieldlines_data['nsteps'] - self.nr = self.fieldlines_data['nr'] - self.nphi = self.fieldlines_data['nphi'] - self.nz = self.fieldlines_data['nz'] + self.nlines = self.fieldlines_data.nlines + self.npoinc = self.fieldlines_data.npoinc + self.nsteps = self.fieldlines_data.nsteps + self.nr = self.fieldlines_data.nr + self.nphi = self.fieldlines_data.nphi + self.nz = self.fieldlines_data.nz self.ui.rhoslider.setMaximum(self.nr-1) self.ui.uslider.setMaximum(self.nphi-1) self.ui.vslider.setMaximum(self.nz-1) @@ -82,12 +84,12 @@ def __init__(self): def FileSelect(self,i): self.fieldlines_data=read_fieldlines(self.ui.FileName.currentText()) #self.ui.PlotList.addItems(self.ui.plot_list) - self.nlines = self.fieldlines_data['nlines'] - self.npoinc = self.fieldlines_data['npoinc'] - self.nsteps = self.fieldlines_data['nsteps'] - self.nr = self.fieldlines_data['nr'] - self.nphi = self.fieldlines_data['nphi'] - self.nz = self.fieldlines_data['nz'] + self.nlines = self.fieldlines_data.nlines + self.npoinc = self.fieldlines_data.npoinc + self.nsteps = self.fieldlines_data.nsteps + self.nr = self.fieldlines_data.nr + self.nphi = self.fieldlines_data.nphi + self.nz = self.fieldlines_data.nz self.ui.rhoslider.setMaximum(self.nr-1) self.ui.uslider.setMaximum(self.nphi-1) self.ui.vslider.setMaximum(self.nz-1) @@ -190,27 +192,27 @@ def update_plot(self,i): if (plot_name == 'Summary'): print(plot_name) elif (plot_name == 'Iota'): - temp = calc_iota(self.fieldlines_data) + reff,iota,iota_err = self.fieldlines_data.calc_iota() #self.ax.errorbar(temp['rho'],temp['iota'],yerr=temp['iota_err']) - self.ax.plot(temp['rho'],temp['iota'],'.k') - self.ax.set_ylim(min(temp['iota']),max(temp['iota'])) + self.ax.plot(reff,iota,'.k') + self.ax.set_ylim(min(iota),max(iota)) self.ax.set_xlim(0.0,1.25) self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel('iota') self.ax.set_title('Rotational Transform') #self.ax.set(xlabel='s',ylabel='iota',aspect='square') elif (plot_name == 'q'): - temp = calc_iota(self.fieldlines_data) - self.ax.plot(temp['rho'],1.0/temp['iota'],'.k') + reff,iota,iota_err = self.fieldlines_data.calc_iota() + self.ax.plot(reff,1.0/iota,'.k') self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel('q') self.ax.set_title('Safety Factor') elif (plot_name == 'Poincaré'): k = self.u - rmin = np.amin(self.fieldlines_data['raxis']) - rmax = np.amax(self.fieldlines_data['raxis']) - self.ax.plot(self.fieldlines_data['R_lines'][k:self.nsteps-1:self.npoinc,:],\ - self.fieldlines_data['Z_lines'][k:self.nsteps-1:self.npoinc,:],\ + rmin = np.amin(self.fieldlines_data.raxis) + rmax = np.amax(self.fieldlines_data.raxis) + self.ax.plot(self.fieldlines_data.R_lines[k:self.nsteps-1:self.npoinc,:],\ + self.fieldlines_data.Z_lines[k:self.nsteps-1:self.npoinc,:],\ '.k',markersize=0.1) self.ax.set_xlabel('R [m]') self.ax.set_ylabel('Z [m]') @@ -219,16 +221,16 @@ def update_plot(self,i): self.ax.set_xlim(rmin,rmax) elif (plot_name == 'Poincaré |B|'): k = self.u - rmin = np.amin(self.fieldlines_data['raxis']) - rmax = np.amax(self.fieldlines_data['raxis']) - cmin = np.amin(self.fieldlines_data['B_lines'][k:self.npoinc,0]) - cmax = np.amax(self.fieldlines_data['B_lines'][k:self.npoinc,0]) + rmin = np.amin(self.fieldlines_data.raxis) + rmax = np.amax(self.fieldlines_data.raxis) + cmin = np.amin(self.fieldlines_data.B_lines[k:self.npoinc,0]) + cmax = np.amax(self.fieldlines_data.B_lines[k:self.npoinc,0]) #cmin = cmin - 0.5*np.abs(cmin) #cmax = cmax + 0.5*np.abs(cmin) - print(self.fieldlines_data['B_lines'][0,:]) - cax = self.ax.scatter(self.fieldlines_data['R_lines'][k:self.nsteps-1:self.npoinc,:],\ - self.fieldlines_data['Z_lines'][k:self.nsteps-1:self.npoinc,:],\ - c=self.fieldlines_data['B_lines'][k:self.nsteps-1:self.npoinc,:], marker='.',s=0.3, \ + print(self.fieldlines_data.B_lines[0,:]) + cax = self.ax.scatter(self.fieldlines_data.R_lines[k:self.nsteps-1:self.npoinc,:],\ + self.fieldlines_data.Z_lines[k:self.nsteps-1:self.npoinc,:],\ + c=self.fieldlines_data.B_lines[k:self.nsteps-1:self.npoinc,:], marker='.',s=0.3, \ cmap='jet') self.ax.set_xlabel('R [m]') self.ax.set_ylabel('Z [m]') @@ -238,16 +240,16 @@ def update_plot(self,i): self.fig.colorbar(cax) #cax.set_clim(cmin,cmax) elif (plot_name == 'Poincaré Length'): - rho = self.fieldlines_data['L_lines'] + rho = self.fieldlines_data.L_lines k = self.u - rmin = np.amin(self.fieldlines_data['raxis']) - rmax = np.amax(self.fieldlines_data['raxis']) + rmin = np.amin(self.fieldlines_data.raxis) + rmax = np.amax(self.fieldlines_data.raxis) cmin = np.amin(rho) cmax = np.amax(rho) n = np.rint((self.nsteps-1-k)/self.npoinc) rho2d = np.matlib.repmat(rho,int(n),1) - cax = self.ax.scatter(self.fieldlines_data['R_lines'][k:self.nsteps-1:self.npoinc,:],\ - self.fieldlines_data['Z_lines'][k:self.nsteps-1:self.npoinc,:],\ + cax = self.ax.scatter(self.fieldlines_data.R_lines[k:self.nsteps-1:self.npoinc,:],\ + self.fieldlines_data.Z_lines[k:self.nsteps-1:self.npoinc,:],\ c=rho2d, marker='.',s=0.3, \ cmap='jet') self.ax.set_xlabel('R [m]') @@ -258,16 +260,16 @@ def update_plot(self,i): self.fig.colorbar(cax) cax.set_clim(cmin,cmax) elif (plot_name == 'Poincaré a'): - rho = calc_reff(self.fieldlines_data) + rho = self.fieldlines_data.calc_reff() k = self.u - rmin = np.amin(self.fieldlines_data['raxis']) - rmax = np.amax(self.fieldlines_data['raxis']) + rmin = np.amin(self.fieldlines_data.raxis) + rmax = np.amax(self.fieldlines_data.raxis) cmin = np.amin(rho) cmax = np.amax(rho) n = np.rint((self.nsteps-1-k)/self.npoinc) rho2d = np.matlib.repmat(rho,int(n),1) - cax = self.ax.scatter(self.fieldlines_data['R_lines'][k:self.nsteps-1:self.npoinc,:],\ - self.fieldlines_data['Z_lines'][k:self.nsteps-1:self.npoinc,:],\ + cax = self.ax.scatter(self.fieldlines_data.R_lines[k:self.nsteps-1:self.npoinc,:],\ + self.fieldlines_data.Z_lines[k:self.nsteps-1:self.npoinc,:],\ c=rho2d, marker='.',s=0.3, \ cmap='jet') self.ax.set_xlabel('R [m]') @@ -282,18 +284,18 @@ def update_plot(self,i): else: # First load the value based on plot if (plot_name=='B_R'): - val = self.fieldlines_data['B_R'] + val = self.fieldlines_data.B_R elif (plot_name=='B_PHI'): - val = self.fieldlines_data['B_PHI'] + val = self.fieldlines_data.B_PHI elif (plot_name=='B_Z'): - val = self.fieldlines_data['B_Z'] - r = self.fieldlines_data['raxis'] - p = self.fieldlines_data['phiaxis'] - z = self.fieldlines_data['zaxis'] - nr2 = np.int(self.nr/2) - nphi2 = np.int(self.nphi/2) - nz2 = np.int(self.nz/2) - cmin = self.fieldlines_data['B_PHI'][nr2,nphi2,nz2] + val = self.fieldlines_data.B_Z + r = self.fieldlines_data.raxis + p = self.fieldlines_data.phiaxis + z = self.fieldlines_data.zaxis + nr2 = int(self.nr/2) + nphi2 = int(self.nphi/2) + nz2 = int(self.nz/2) + cmin = self.fieldlines_data.B_PHI[nr2,nphi2,nz2] cmax = cmin + np.abs(cmin)*0.75 cmin = cmin - np.abs(cmin)*0.75 # Now handle the type of plot @@ -307,19 +309,20 @@ def update_plot(self,i): self.ax.plot(z,val[self.s,self.u,:]) self.ax.set_xlabel('Z [m]') elif (self.ui.flux_button.isChecked()): - cax=self.ax.pcolormesh(np.squeeze(val[self.s,:,:]),cmap='jet') + cax=self.ax.pcolormesh(z,p,np.squeeze(val[self.s,:,:]),cmap='jet') self.fig.colorbar(cax) self.ax.set_ylabel('Toroidal Angle [rad]') self.ax.set_xlabel('Z [m]') cax.set_clim(cmin,cmax) elif (self.ui.poltor_button.isChecked()): - cax=self.ax.pcolormesh(np.squeeze(val[:,self.u,:]),cmap='jet') + cax=self.ax.pcolormesh(r,z,np.squeeze(val[:,self.u,:]),cmap='jet') self.fig.colorbar(cax) self.ax.set_xlabel('R [m]') self.ax.set_ylabel('Z [m]') cax.set_clim(cmin,cmax) elif (self.ui.RZ_button.isChecked()): - cax = self.ax.pcolor(val[:,:,self.v],cmap='jet') + cax=self.ax.pcolormesh(p,r,np.squeeze(val[:,:,self.v]),cmap='jet') + #cax = self.ax.pcolor(r,p,val[:,:,self.v],cmap='jet') self.fig.colorbar(cax) self.ax.set_xlabel('R [m]') self.ax.set_ylabel('Toroidal Angle [rad]') diff --git a/pySTEL/VMECplot.py b/pySTEL/VMECplot.py index 94d359ce4..b8bb46615 100755 --- a/pySTEL/VMECplot.py +++ b/pySTEL/VMECplot.py @@ -14,10 +14,13 @@ from PyQt5 import uic, QtGui, QtWidgets from PyQt5.QtWidgets import QMainWindow, QApplication, QVBoxLayout, QSizePolicy from PyQt5.QtGui import QIcon +# Matplotlib from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas -from libstell.libstell import read_vmec, cfunct, sfunct, torocont, isotoro, calc_jll from matplotlib.figure import Figure from mpl_toolkits import mplot3d +# +from libstell import vmec +#from libstell.libstell import read_vmec, cfunct, sfunct, torocont, isotoro, calc_jll try: qtCreatorPath=os.environ["STELLOPT_PATH"] @@ -25,8 +28,8 @@ print("Please set environment variable STELLOPT_PATH") sys.exit(1) -#qtCreatorFile = "/u/slazerso/src/STELLOPT_GCC/pySTEL/VMECplot.ui" # Enter file here. -qtCreatorFile = qtCreatorPath+"/pySTEL/VMECplot.ui" # Enter file here. +qtCreatorFile = os.path.join(qtCreatorPath,'pySTEL','VMECplot.ui') +#qtCreatorFile = qtCreatorPath+"/pySTEL/VMECplot.ui" # Enter file here. Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile) class MyApp(QMainWindow): @@ -35,7 +38,6 @@ def __init__(self): self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setStyleSheet("background-color: white;"); - #self.ui.PlotButtons.setStyleSheet("background-color: white;"); self.statusBar().showMessage('Ready') self.ui.plot_list = ['Summary','-----1D-----','Iota','q','Pressure',\ '','','','','', '-----3D------','|B|','sqrt(g)',\ @@ -45,24 +47,25 @@ def __init__(self): if(name[0:4]=='wout'): self.ui.FileName.addItem(name) # Init - self.vmec_data=read_vmec(self.ui.FileName.currentText()) + self.vmec_data=vmec.VMEC() + self.vmec_data.read_wout(self.ui.FileName.currentText()) self.ui.PlotList.addItems(self.ui.plot_list) self.ui.PlotButtons.setEnabled(0) - self.ns = self.vmec_data['ns'] - self.nu = self.vmec_data['mpol']*4 - self.nv = self.vmec_data['ntor']*4*self.vmec_data['nfp'] - self.nv2 = self.vmec_data['ntor']*4 + self.ns = self.vmec_data.ns + self.nu = self.vmec_data.mpol + self.nv = self.vmec_data.ntor*4*self.vmec_data.nfp + self.nv2 = self.vmec_data.ntor*4 if self.nu < 128: self.nu = 128 if self.nv < 64: self.nv = 64 - self.TransformVMEC(self) + self.TransformVMEC() self.s=0 self.u=0 self.v=0 self.ui.rhoslider.setMaximum(self.ns-1) self.ui.uslider.setMaximum(self.nu-1) - self.ui.vslider.setMaximum((self.nv/self.vmec_data['nfp'])) + self.ui.vslider.setMaximum(round(self.nv/self.vmec_data.nfp)) # Plot figure self.fig = Figure(figsize=(2,2),dpi=100) self.ax = self.fig.add_subplot(111) @@ -83,19 +86,19 @@ def __init__(self): self.ui.uslider.valueChanged.connect(self.CutSelect) self.ui.vslider.valueChanged.connect(self.CutSelect) self.ui.savebutton.clicked.connect(self.plot_to_file) + self.update_plot(self) def FileSelect(self,i): - self.vmec_data=read_vmec(self.ui.FileName.currentText()) - #self.ui.PlotList.addItems(self.ui.plot_list) - self.ns = self.vmec_data['ns'] - self.nu = self.vmec_data['mpol']*4 - self.nv = self.vmec_data['ntor']*4*self.vmec_data['nfp'] - self.nv2 = self.vmec_data['ntor']*4 + self.vmec_data.read_wout(self.ui.FileName.currentText()) + self.ns = self.vmec_data.ns + self.nu = self.vmec_data.mpol + self.nv = self.vmec_data.ntor*4*self.vmec_data.nfp + self.nv2 = self.vmec_data.ntor*4 if self.nu < 32: self.nu = 32 if self.nv < 16: self.nv = 16 - self.TransformVMEC(self) + self.TransformVMEC() self.s=0 self.u=0 self.v=0 @@ -125,6 +128,7 @@ def PlotSelect(self,i): self.ui.rhoslider.setEnabled(0) self.ui.uslider.setEnabled(0) self.ui.vslider.setEnabled(0) + self.update_plot(self) elif (i<10): self.ui.rho_button.setChecked(1) self.ui.pol_button.setEnabled(0) @@ -178,51 +182,85 @@ def CutSelect(self,i): self.update_plot(self) def update_plot(self,i): - #self.ui.plot_widget.addWidget(self.canvas) plot_name = self.ui.PlotList.currentText(); self.fig.clf() - #self.fig.delaxes(self.ax) self.ax = self.fig.add_subplot(111) if (plot_name == 'Summary'): - print(plot_name) + #self.ax.plot([0,1],[0,0],'k') + self.ax.text(0.05,0.95,rf'Run: {self.vmec_data.input_extension.strip()}', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.91,rf'NS: {self.vmec_data.ns}', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.87,rf'MPOL: {self.vmec_data.mpol}', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.83,rf'NTOR: {self.vmec_data.ntor}', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.79,rf'NFP: {self.vmec_data.nfp}', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.75,rf'MGRID: {self.vmec_data.mgrid_file.strip()}', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.60,rf'Aspect: {self.vmec_data.aspect:5.3f}', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.56,rf'Rmajor: {self.vmec_data.rmajor:5.3f} [m]', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.52,rf'Aminor: {self.vmec_data.aminor:5.3f} [m]', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.48,rf'Volume: {self.vmec_data.volume:5.1f} [$m^3$]', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.33,r'$<\beta>_{total}$'+f': {self.vmec_data.betatot*100:3.2f} %', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.29,r'$<\beta>_{poloidal}$'+f': {self.vmec_data.betapol*100:3.2f} %', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.25,r'$<\beta>_{toroidal}$'+f': {self.vmec_data.betator*100:3.2f} %', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.05,0.21,r'$\beta_{axis}$'+f': {self.vmec_data.betaxis*100:3.2f} %', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.65,0.91,rf': {self.vmec_data.volavgb:3.2f} [T]', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.65,0.87,rf': {self.vmec_data.b0:3.2f} [T]', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.65,0.83,r'$B_{ECRH}$:'+f' {sum(self.vmec_data.bmnc[0,:]):3.2f} [T]', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) + self.ax.text(0.65,0.79,r'$I_{tor}$:'+f' {self.vmec_data.b0:3.2f} [A]', horizontalalignment='left',\ + verticalalignment='center', transform=self.ax.transAxes) elif (plot_name == 'Iota'): - self.ax.plot(self.nflux,self.vmec_data['iotaf']) + self.ax.plot(self.nflux,self.vmec_data.iotaf) self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel('iota') self.ax.set_title('Rotational Transform') #self.ax.set(xlabel='s',ylabel='iota',aspect='square') elif (plot_name == 'q'): - self.ax.plot(self.nflux,1.0/self.vmec_data['iotaf']) + self.ax.plot(self.nflux,1.0/self.vmec_data.iotaf) self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel('q') self.ax.set_title('Safety Factor') elif (plot_name == 'Pressure'): - self.ax.plot(self.nflux,self.vmec_data['presf']/1000) + self.ax.plot(self.nflux,self.vmec_data.presf/1000) self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel('Pressure [kPa]') self.ax.set_title('Pressure Profile') elif (plot_name == ''): - self.ax.plot(self.nflux,self.vmec_data['buco']) + self.ax.plot(self.nflux,self.vmec_data.buco) self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel(' [T]') self.ax.set_title('Flux surface Averaged B^u') elif (plot_name == ''): - self.ax.plot(self.nflux,self.vmec_data['bvco']) + self.ax.plot(self.nflux,self.vmec_data.bvco) self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel(' [T]') self.ax.set_title('Flux surface Averaged B^v') elif (plot_name == ''): - self.ax.plot(self.nflux,self.vmec_data['jcuru']/1000) + self.ax.plot(self.nflux,self.vmec_data.jcuru/1000) self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel(' [kA/m^2]') self.ax.set_title('Flux surface Averaged j^u') elif (plot_name == ''): - self.ax.plot(self.nflux,self.vmec_data['jcurv']/1000) + self.ax.plot(self.nflux,self.vmec_data.jcurv/1000) self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel(' [kA/m^2]') self.ax.set_title('Flux surface Averaged j^v') elif (plot_name == ''): - self.ax.plot(self.nflux,self.vmec_data['jdotb']/1000) + self.ax.plot(self.nflux,self.vmec_data.jdotb/1000) self.ax.set_xlabel('Normalized Flux') self.ax.set_ylabel(' [T*kA/m^2]') self.ax.set_title('Flux surface Averaged j.B') @@ -260,7 +298,7 @@ def update_plot(self,i): elif (plot_name=='j^v'): val = self.cv/self.g elif (plot_name=='jll'): - val = calc_jll(self.vmec_data, self.theta, self.zeta) + val = self.vmec_data.calc_jll(self.theta, self.zeta) elif (plot_name=='j.B'): val = (self.cu*self.bu+self.cv*self.bv)/self.g # Now handle the type of plot @@ -290,12 +328,13 @@ def update_plot(self,i): self.ax.set_aspect('equal') elif (self.ui.ThreeD_button.isChecked()): self.fig.delaxes(self.ax) - self.ax = isotoro(self.r,self.z,self.zeta,self.s,val,fig=self.fig) + self.ax = self.vmec_data.isotoro(self.r,self.z,self.zeta,self.s,val,fig=self.fig) + self.ax.set_aspect('equal', adjustable='box') self.ax.grid(False) self.ax.set_axis_off() self.canvas.draw() - def TransformVMEC(self, i): + def TransformVMEC(self): self.nflux = np.ndarray((self.ns,1)) self.theta = np.ndarray((self.nu,1)) self.zeta = np.ndarray((self.nv,1)) @@ -304,17 +343,17 @@ def TransformVMEC(self, i): for j in range(self.nu): self.theta[j]=2*pi*j/(self.nu-1) for j in range(self.nv): self.zeta[j]=2*pi*j/((self.nv-1)) self.zeta2=self.zeta[0:self.nv2+1] - self.r=cfunct(self.theta,self.zeta,self.vmec_data['rmnc'],self.vmec_data['xm'],self.vmec_data['xn']) - self.z=sfunct(self.theta,self.zeta,self.vmec_data['zmns'],self.vmec_data['xm'],self.vmec_data['xn']) - self.b=cfunct(self.theta,self.zeta,self.vmec_data['bmnc'],self.vmec_data['xm_nyq'],self.vmec_data['xn_nyq']) - self.g=cfunct(self.theta,self.zeta,self.vmec_data['gmnc'],self.vmec_data['xm_nyq'],self.vmec_data['xn_nyq']) - self.bu=cfunct(self.theta,self.zeta,self.vmec_data['bsupumnc'],self.vmec_data['xm_nyq'],self.vmec_data['xn_nyq']) - self.bv=cfunct(self.theta,self.zeta,self.vmec_data['bsupvmnc'],self.vmec_data['xm_nyq'],self.vmec_data['xn_nyq']) - self.cu=cfunct(self.theta,self.zeta,self.vmec_data['currumnc'],self.vmec_data['xm_nyq'],self.vmec_data['xn_nyq']) - self.cv=cfunct(self.theta,self.zeta,self.vmec_data['currvmnc'],self.vmec_data['xm_nyq'],self.vmec_data['xn_nyq']) - self.b_s=sfunct(self.theta,self.zeta,self.vmec_data['bsubsmns'],self.vmec_data['xm_nyq'],self.vmec_data['xn_nyq']) - self.b_u=cfunct(self.theta,self.zeta,self.vmec_data['bsubumnc'],self.vmec_data['xm_nyq'],self.vmec_data['xn_nyq']) - self.b_v=cfunct(self.theta,self.zeta,self.vmec_data['bsubvmnc'],self.vmec_data['xm_nyq'],self.vmec_data['xn_nyq']) + self.r=self.vmec_data.cfunct(self.theta,self.zeta,self.vmec_data.rmnc,self.vmec_data.xm,self.vmec_data.xn) + self.z=self.vmec_data.sfunct(self.theta,self.zeta,self.vmec_data.zmns,self.vmec_data.xm,self.vmec_data.xn) + self.b=self.vmec_data.cfunct(self.theta,self.zeta,self.vmec_data.bmnc,self.vmec_data.xm_nyq,self.vmec_data.xn_nyq) + self.g=self.vmec_data.cfunct(self.theta,self.zeta,self.vmec_data.gmnc,self.vmec_data.xm_nyq,self.vmec_data.xn_nyq) + self.bu=self.vmec_data.cfunct(self.theta,self.zeta,self.vmec_data.bsupumnc,self.vmec_data.xm_nyq,self.vmec_data.xn_nyq) + self.bv=self.vmec_data.cfunct(self.theta,self.zeta,self.vmec_data.bsupvmnc,self.vmec_data.xm_nyq,self.vmec_data.xn_nyq) + self.cu=self.vmec_data.cfunct(self.theta,self.zeta,self.vmec_data.currumnc,self.vmec_data.xm_nyq,self.vmec_data.xn_nyq) + self.cv=self.vmec_data.cfunct(self.theta,self.zeta,self.vmec_data.currvmnc,self.vmec_data.xm_nyq,self.vmec_data.xn_nyq) + self.b_s=self.vmec_data.sfunct(self.theta,self.zeta,self.vmec_data.bsubsmns,self.vmec_data.xm_nyq,self.vmec_data.xn_nyq) + self.b_u=self.vmec_data.cfunct(self.theta,self.zeta,self.vmec_data.bsubumnc,self.vmec_data.xm_nyq,self.vmec_data.xn_nyq) + self.b_v=self.vmec_data.cfunct(self.theta,self.zeta,self.vmec_data.bsubvmnc,self.vmec_data.xm_nyq,self.vmec_data.xn_nyq) def plot_to_file(self,i): text = self.ui.saveas_filename.toPlainText(); diff --git a/pySTEL/blender_coil.py b/pySTEL/blender_coil.py new file mode 100644 index 000000000..ec023fc89 --- /dev/null +++ b/pySTEL/blender_coil.py @@ -0,0 +1,64 @@ +import sys,os +import bpy +import numpy as np +sys.path.append("/Users/lazerson/Sims_Work/STELLOPT/pySTEL/") +os.environ["STELLOPT_PATH"] = "/Users/lazerson/Sims_Work/STELLOPT/" +from libstell.coils import COILSET + +coil_file = '/Users/lazerson/Sims_Work/GAUSS/GIGA_v120_FOCUS/GIGA_v120_c100.coils' + +# Generate Coil +coils = COILSET() +coils.read_coils_file(coil_file) +[vertices_coil,faces_coil]=coils.blenderCoil(dist=0.5) + +# Create mesh +mesh_coil = bpy.data.meshes.new(name="CoilMesh") +mesh_coil.from_pydata(vertices_coil, [], faces_coil) +mesh_coil.update() + +# Create object +coil_obj = bpy.data.objects.new("CoilObject", mesh_coil) + +# Create a new material +material = bpy.data.materials.new(name="CopperMaterial") +material.use_nodes = True + +# Clear default nodes +nodes = material.node_tree.nodes +nodes.clear() + +# Create Principled BSDF shader node +principled_node = nodes.new(type='ShaderNodeBsdfPrincipled') + +# Set Principled BSDF parameters for copper +principled_node.inputs['Base Color'].default_value = (0.8, 0.4, 0.2, 1.0) # Reddish-brown color +principled_node.inputs['Metallic'].default_value = 1.0 # Fully metallic +principled_node.inputs['Roughness'].default_value = 0.3 # Moderate roughness +principled_node.inputs['Specular'].default_value = 0.5 # Specular intensity +principled_node.inputs['Anisotropic'].default_value = 0.2 # Anisotropic reflection + +# Create material output node +output_node = nodes.new(type='ShaderNodeOutputMaterial') + +# Link nodes +links = material.node_tree.links +links.new(principled_node.outputs['BSDF'], output_node.inputs['Surface']) + +if coil_obj.data.materials: + # Assign to the first material slot + coil_obj.data.materials[0] = material +else: + # Create a new material slot and assign the material + coil_obj.data.materials.append(material) + + +# Link object to the scene +scene = bpy.context.scene +scene.collection.objects.link(coil_obj) + + +# Set object as active and select it +bpy.context.view_layer.objects.active = coil_obj +coil_obj.select_set(True) + diff --git a/pySTEL/blender_vmec.py b/pySTEL/blender_vmec.py new file mode 100644 index 000000000..590225b87 --- /dev/null +++ b/pySTEL/blender_vmec.py @@ -0,0 +1,116 @@ +import sys,os +import bpy +import numpy as np +sys.path.append("/Users/lazerson/Sims_Work/STELLOPT/pySTEL/") +os.environ["STELLOPT_PATH"] = "/Users/lazerson/Sims_Work/STELLOPT/" +wout_file = '/Users/lazerson/Sims_Work/GAUSS/GIGA_v120/wout_GIGA_v120.nc' + +from libstell.vmec import VMEC + + +# Define the RGB color (values between 0 and 1) +rgb_color = (0.1, 0.8, 0.2) # Example: a shade of green + +vmec_wout = VMEC() +vmec_wout.read_wout(wout_file) +nu = 360 +nv = 360 +theta = np.ndarray((nu,1)) +phi = np.ndarray((nv,1)) +for j in range(nu): theta[j]=2.0*np.pi*j/(nu) +for j in range(nv): phi[j]=2.0*np.pi*j/(nv) +r = vmec_wout.cfunct(theta,phi,vmec_wout.rmnc,vmec_wout.xm,vmec_wout.xn) +z = vmec_wout.sfunct(theta,phi,vmec_wout.zmns,vmec_wout.xm,vmec_wout.xn) +[vertices,faces] = vmec_wout.blenderSurface(r,z,phi,surface=vmec_wout.ns-1) + +# Create mesh data +mesh = bpy.data.meshes.new(name="VMECMesh") +mesh.from_pydata(vertices, [], faces) +mesh.update() + +# Create object +vmec_obj = bpy.data.objects.new("VMECObject", mesh) + +# Create a new material +material = bpy.data.materials.new(name="PlasmaMaterial") +material.use_nodes = True + +# Clear default nodes +nodes = material.node_tree.nodes +for node in nodes: + nodes.remove(node) + +# Create new nodes +output_node = nodes.new(type='ShaderNodeOutputMaterial') +emission_node = nodes.new(type='ShaderNodeEmission') +transparent_node = nodes.new(type='ShaderNodeBsdfTransparent') +mix_shader_node = nodes.new(type='ShaderNodeMixShader') +noise_texture_node = nodes.new(type='ShaderNodeTexNoise') +color_ramp_node = nodes.new(type='ShaderNodeValToRGB') + +# Arrange nodes +noise_texture_node.location = (-600, 0) +color_ramp_node.location = (-400, 0) +emission_node.location = (-200, 0) +transparent_node.location = (-200, -200) +mix_shader_node.location = (0, 0) +output_node.location = (200, 0) + +# Link nodes +links = material.node_tree.links +links.new(noise_texture_node.outputs['Fac'], color_ramp_node.inputs['Fac']) +links.new(color_ramp_node.outputs['Color'], emission_node.inputs['Color']) +links.new(emission_node.outputs['Emission'], mix_shader_node.inputs[2]) +links.new(transparent_node.outputs['BSDF'], mix_shader_node.inputs[1]) +links.new(mix_shader_node.outputs['Shader'], output_node.inputs['Surface']) + +# Adjust noise texture +noise_texture_node.inputs['Scale'].default_value = 20.0 +noise_texture_node.inputs['Detail'].default_value = 16.0 +noise_texture_node.inputs['Distortion'].default_value = 1.0 + +# Adjust color ramp +color_ramp = color_ramp_node.color_ramp +color_ramp.interpolation = 'EASE' +color_ramp.elements[0].position = 0.0 +color_ramp.elements[0].color = (0.0, 0.1, 0.0, 1.0) # Dark green +color_ramp.elements.new(0.3) +color_ramp.elements[1].position = 0.3 +color_ramp.elements[1].color = (0.0, 0.5, 0.0, 1.0) # Medium green +color_ramp.elements.new(0.6) +color_ramp.elements[2].position = 0.6 +color_ramp.elements[2].color = (0.0, 1.0, 0.0, 1.0) # Bright green +color_ramp.elements.new(1.0) +color_ramp.elements[3].position = 1.0 +color_ramp.elements[3].color = (0.5, 1.0, 0.5, 1.0) # Light green + + +# Ensure emission strength is sufficient +emission_node.inputs['Strength'].default_value = 1.0 + +# Adjust mix shader to balance between emission and transparency +mix_shader_node.inputs['Fac'].default_value = 0.5 # Adjust this value to change transparency + +# Ensure the object has an active material slot +if vmec_obj.data.materials: + # Assign to the first material slot + vmec_obj.data.materials[0] = material +else: + # Create a new material slot and assign the material + vmec_obj.data.materials.append(material) + + +# Link object to the scene +scene = bpy.context.scene +scene.collection.objects.link(vmec_obj) + +# Set render engine to Eevee and enable Bloom +bpy.context.scene.render.engine = 'BLENDER_EEVEE' +bpy.context.scene.eevee.use_bloom = True +bpy.context.scene.eevee.bloom_intensity = 0.2 # Adjust bloom intensity as needed + +# Set object as active and select it +bpy.context.view_layer.objects.active = vmec_obj +vmec_obj.select_set(True) + +##### \ No newline at end of file diff --git a/pySTEL/boozer_util.py b/pySTEL/boozer_util.py new file mode 100644 index 000000000..421cd1317 --- /dev/null +++ b/pySTEL/boozer_util.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Main routine +if __name__=="__main__": + import sys + from argparse import ArgumentParser + import numpy as np + import matplotlib.pyplot as pyplot + from libstell.boozer import BOOZER + parser = ArgumentParser(description= + '''Provides class for accessing boozer data also serves as a + simple tool for assessing boozer boozmn files.''') + parser.add_argument("-b", "--boozer", dest="booz_ext", + help="BOOZER boozmn file extension", default = None) + parser.add_argument("-p", "--plot", dest="lplot", action='store_true', + help="Plot the boozer file.", default = False) + parser.add_argument("-s", "--surf", dest="sval", + help="Equilibrium surface to plot.", default = None) + parser.add_argument("--bootsj", dest="lbootsj", action='store_true', + help="Output a bootsj file.", default = False) + boozmn_data = BOOZER() + args = parser.parse_args() + if args.booz_ext: + try: + boozmn_data.read_boozer(args.booz_ext) + except: + print(f'Could not file boozmn file: {args.booz_ext}') + sys.exit(-1) + if args.lplot: + if not args.sval: + sval = int(0.25*boozmn_data.ns_b) + else: + sval = int(args.sval)-1 + px = 1/pyplot.rcParams['figure.dpi'] + fig,(ax1,ax2) = pyplot.subplots(1,2,figsize=(1024*px,768*px)) + pyplot.subplots_adjust(hspace=0.1,wspace=0.3) + boozmn_data.plotBmnSpectrum(sval,ax=ax1) + boozmn_data.plotBsurf(sval,ax=ax2) + pyplot.show() + if args.lbootsj: + filename = 'in_bootsj.'+args.booz_ext + f = open(filename,'w') + f.write(f'{args.booz_ext}\n') + for i in range(1,boozmn_data.ns_b): + f.write(f' {i+1}') + f.write('\n') + f.close() + # Setup bootin dict + bootin_dict={'mbuse':int(max(np.squeeze(boozmn_data.ixm_b))),\ + 'nbuse':int(max(np.squeeze(boozmn_data.ixn_b))/boozmn_data.nfp_b),\ + 'teti':1.0,'zeff1':1.0,'dens0':1.0,'tempres':1.0,\ + 'damp_bs':0.001,\ + 'ate':np.array([1.0,-1.0,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.]),\ + 'ati':np.array([1.0,-1.0,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.]),\ + } + boozmn_data.libStell.set_bootin(bootin_dict) + boozmn_data.libStell.write_bootin('input.'+args.booz_ext) + sys.exit(0) \ No newline at end of file diff --git a/pySTEL/coilPlot b/pySTEL/coilPlot deleted file mode 100755 index 493874eb1..000000000 --- a/pySTEL/coilPlot +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python - -# The format for coils files is defined in LIBSTELL/Sources/Modules/biotsavart.f - -print "usage: coilPlot coils.XXXX" - -import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d import Axes3D -import numpy as np -#from scipy.io import netcdf -import sys -#import math - -if len(sys.argv) != 2: - print "Error! You must specify 1 argument: the coils.XXX file." - exit(1) - -f = open(sys.argv[1],'r') -lines = f.readlines() -f.close() - -if lines[0][:8] != "periods ": - print "Error! First line should begin with 'periods '" - exit(1) - -nfp = int(lines[0][8:]) -print "nfp =",nfp - -if lines[1][:14] != "begin filament": - print "Error! First line should be 'begin filament'" - exit(1) - -currentLine = 3 -coils = [] -thresh = 1e-13 -while lines[currentLine][:3] != "end": - x=[] - y=[] - z=[] - whichLineOfCoil = -1 - keepGoing = True - while keepGoing: - whichLineOfCoil += 1 - splitLine = lines[currentLine].split() - currentLine += 1 - last_x = float(splitLine[0]) - last_y = float(splitLine[1]) - last_z = float(splitLine[2]) - x.append(last_x) - y.append(last_y) - z.append(last_z) - thisCurrent = float(splitLine[3]) - if whichLineOfCoil == 0: - current = thisCurrent - start_x = last_x - start_y = last_y - start_z = last_z - nvals = len(splitLine) - #print whichLineOfCoil, nvals - if nvals == 6: - # This must be the last line of the coil. - currentGroup = int(splitLine[4]) - currentGroupName = splitLine[5] - numPointsInCoil = whichLineOfCoil + 1 - if numPointsInCoil == 1: - print "Found a coil in group ",currentGroup," containing 1 point: circular coil." - elif numPointsInCoil == 2: - print "Found a coil in group ",currentGroup," containing 2 points: infinite straight line current." - else: - print "Found a coil in group ",currentGroup," containing ",numPointsInCoil," points." - keepGoing = False - if numPointsInCoil > 2: - # Make sure coil ends where it started: - if (last_x-start_x) > thresh: - print "Error! Coil is not closed in x." - print "initial x: ",start_x - print "final x: ",last_x - exit(1) - if (last_y-start_y) > thresh: - print "Error! Coil is not closed in y." - print "initial y: ",start_y - print "final y: ",last_y - exit(1) - if (last_z-start_z) > thresh: - print "Error! Coil is not closed in z." - print "initial z: ",start_z - print "final z: ",last_z - exit(1) - - elif len(splitLine) != 4: - print "Error! This line should have either 4 or 6 elements, but it has ",len(splitLine) - print lines[currentLine] - exit(1) - - coil = {'x':x, 'y':y, 'z':z, 'group':currentGroup, 'groupName':currentGroupName, 'n':numPointsInCoil} - coils.append(coil) -#exit(0) - -colors = ['red','green','blue','black','darkorange','magenta','gray','darkturquoise','y','pink'] - -fig = plt.figure() -fig.patch.set_facecolor('white') -ax = fig.gca(projection='3d') - -for coil in coils: - ax.plot(coil['x'], coil['y'], coil['z'],'.-', color=colors[coil['group']-1]) - -#coil = coils[0] -#ax.plot(coil['x'], coil['y'], coil['z'],'.-',color=colors[coil['group']-1]) - -#plt.tight_layout() -plt.show() - diff --git a/pySTEL/coils_util.py b/pySTEL/coils_util.py new file mode 100644 index 000000000..c648f9f4f --- /dev/null +++ b/pySTEL/coils_util.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +if __name__=="__main__": + import sys + from argparse import ArgumentParser + from libstell.coils import COILSET + from libstell.wall import WALL + import matplotlib.pyplot as pyplot + import numpy as np + from datetime import datetime + parser = ArgumentParser(description= + '''Provides class for accessing coils files also serves as a + simple tool for assessing coils or coils files.''') + parser.add_argument("-c", "--coil", dest="coils_file", + help="Coils file for input", default = None) + parser.add_argument("-p", "--plot", dest="lplot", action='store_true', + help="Plot the coils file.", default = False) + parser.add_argument("-prz", "--plotRZ", dest="lplotRZ", action='store_true', + help="Plot each coil group in RZ.", default = False) + parser.add_argument("-b", "--bfield", dest="bxyz", + help="Output B field at x,y,z", default = None) + parser.add_argument("-a", "--afield", dest="axyz", + help="Output A field at x,y,z", default = None) + parser.add_argument("--genwall", dest="wall_offset", + help="Generate a wall file based on offset in [m]", default = None) + parser.add_argument("-o", "--output", dest="loutput", action='store_true', + help="Output the coil", default = False) + args = parser.parse_args() + coils = COILSET() + if args.coils_file: + coils.read_coils_file(args.coils_file) + if args.lplot: coils.plotcoils() + if args.lplotRZ: coils.plotcoilsRZ() + if args.loutput: coils.write_coils_file(args.coils_file+'_new') + if args.axyz: + x,y,z = args.axyz.split(',') + ax,ay,az = coils.coilvecpot(float(x),float(y),float(z)) + print(f"Vector Potential ({x},{y},{z}) : {ax}, {ay}, {az} ") + if args.bxyz: + x,y,z = args.bxyz.split(',') + bx,by,bz = coils.coilbiot(float(x),float(y),float(z)) + print(f"B-Field ({x},{y},{z}) : {bx}, {by}, {bz} [T]") + if args.wall_offset: + vertex = coils.coiloffset(float(args.wall_offset)) + wall = WALL() + wall.genWallfromOrdered(vertex) + wall.name = f"Offset from Coils file {args.wall_offset} {args.coils_file}" + print(wall.vertex.shape) + wall.write_wall('wall_test.dat') + px = 1/pyplot.rcParams['figure.dpi'] + fig=pyplot.figure(figsize=(1024*px,768*px)) + ax1=fig.add_subplot(111,projection='3d') + wall.plot_wall_cloud(ax=ax1) + coils.plotcoils(ax=ax1) + pyplot.show() diff --git a/pySTEL/fieldlines_util.py b/pySTEL/fieldlines_util.py new file mode 100644 index 000000000..ec68d1297 --- /dev/null +++ b/pySTEL/fieldlines_util.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Main routine +if __name__=="__main__": + import sys + from argparse import ArgumentParser + import matplotlib.pyplot as pyplot + from libstell.vmec import VMEC + from libstell.fieldlines import FIELDLINES + import numpy as np + parser = ArgumentParser(description= + '''Provides class for accessing fieldlines data also serves as a + simple tool for assessing fieldlines output.''') + parser.add_argument("-f", "--fieldlines", dest="fieldlines_ext", + help="FIELDLINES file extension", default = None) + parser.add_argument("-p", "--plot", dest="lplot", action='store_true', + help="Plot the fieldlines file.", default = False) + parser.add_argument("-v", "--vmec", dest="vmec_ext", + help="Add VMEC equilbrium to plot", default = None) + args = parser.parse_args() + field_data = FIELDLINES() + if args.fieldlines_ext: + field_data.read_fieldlines('fieldlines_'+args.fieldlines_ext+'.h5') + if args.lplot: + px = 1/pyplot.rcParams['figure.dpi'] + fig,(ax1,ax2,ax3) = pyplot.subplots(1,3,sharey=True,figsize=(1024*px,512*px)) + pyplot.subplots_adjust(hspace=0.1,wspace=0.15) + k = 0 + field_data.plot_poincare(k,6,ax=ax1) + k = field_data.phiaxis[int(field_data.nphi/4)] + field_data.plot_poincare(k,6,ax=ax2) + k = field_data.phiaxis[int(field_data.nphi/2)] + field_data.plot_poincare(k,6,ax=ax3) + if args.vmec_ext: + vmec_wout = VMEC() + vmec_wout.read_wout(args.vmec_ext) + theta = np.ndarray((360,1)) + zeta = np.ndarray((3,1)) + for j in range(360): theta[j]=2.0*np.pi*j/359.0 + for j in range(3): zeta[j]= np.pi*j/2.0 + r = vmec_wout.cfunct(theta,zeta,vmec_wout.rmnc,vmec_wout.xm,vmec_wout.xn/vmec_wout.nfp) + z = vmec_wout.sfunct(theta,zeta,vmec_wout.zmns,vmec_wout.xm,vmec_wout.xn/vmec_wout.nfp) + j = vmec_wout.ns-1 + ax1.plot(r[j,:,0],z[j,:,0],'r') + ax2.plot(r[j,:,1],z[j,:,1],'r') + ax3.plot(r[j,:,2],z[j,:,2],'r') + pyplot.show() + sys.exit(0) \ No newline at end of file diff --git a/pySTEL/focus_util.py b/pySTEL/focus_util.py new file mode 100644 index 000000000..f201dabf3 --- /dev/null +++ b/pySTEL/focus_util.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Main routine +if __name__=="__main__": + import sys + from argparse import ArgumentParser + import numpy as np + import matplotlib.pyplot as pyplot + from libstell.vmec import VMEC + from libstell.focus import FOCUS + from libstell.bnorm import BNORM + from libstell.coils import COILSET + parser = ArgumentParser(description= + '''Provides class for plotting FOCUS simulation results.''') + parser.add_argument("-f", "--focus", dest="focus_ext", + help="FOCUS file extension", default = None) + parser.add_argument("-v", "--vmec", dest="vmec_ext", + help="VMEC file extension", default = None) + parser.add_argument("--bnorm", dest="bnorm_ext", + help="BNORM file extension", default = None) + parser.add_argument("-p", "--plot", dest="lplot", action='store_true', + help="Plot the FOCUS data.", default = False) + parser.add_argument("--plot3d", dest="lplot3d", action='store_true', + help="Plot the plams surface and coil in 3D", default = False) + parser.add_argument("--plotcoildist", dest="lplotcoildist", action='store_true', + help="Plot the coil-plasma distance.", default = False) + parser.add_argument("--gensurf", dest="lgensurf", action='store_true', + help="Generate plasma.boundary VMEC.", default = False) + parser.add_argument("--limiter_dist", dest="lim_dist", + help="Generate limiter.boundary at offset distance of lim_dist.", default = None) + focus_data = FOCUS() + coil_data=COILSET() + args = parser.parse_args() + if args.focus_ext: + try: + focus_data.read_focus_HDF5(args.focus_ext) + except: + print(f'Could not file FOCUS HDF5 file: {args.focus_ext}') + sys.exit(-1) + if args.lgensurf and args.vmec_ext: + wout = VMEC() + wout.read_wout(args.vmec_ext) + rmns = None; zmnc = None + xm_b = None; xn_b = None + bmnc = None; bmns = None + if args.bnorm_ext: + bnorm = BNORM() + bnorm.read_bnorm(bnorm_filename) + curpol = wout.getCurrentPoloidal() + xn_b = -bnorm.xn + xm_b = bnorm.xm + bnmnc = curpol*bnorm.bnmnc[0,:] + bnmns = curpol*bnorm.bnmns[0,:] + k = wout.ns-1 + xm = wout.xm[:,0] + xn = -wout.xn[:,0]/wout.nfp + rmnc = wout.rmnc[k,:] + zmns = wout.zmns[k,:] + if wout.iasym == 1: + rmns = wout.rmns[k,:] + zmnc = wout.zmnc[k,:] + focus_data.write_focus_plasma(wout.nfp,xm,xn,rmnc,zmns,rmns=rmns,zmnc=zmnc,xm_b=xm_b,xn_b=xn_b,bmnc=bnmnc,bmns=bnmns,filename='plasma.boundary') + if args.lim_dist: + [rmnc,zmns,rmns,zmnc]=wout.fitSurface(dist=-dist) + focus_data.write_focus_plasma(wout.nfp,xm,xn,rmnc,zmns,rmns=rmns,zmnc=zmnc,filename='limiter.boundary') + # Make a plot + px = 1/pyplot.rcParams['figure.dpi'] + fig=pyplot.figure(figsize=(1024*px,768*px)) + ax=fig.add_subplot(111) + theta = np.ndarray((360,1)) + zeta = np.ndarray((3,1)) + for j in range(360): theta[j]=2.0*np.pi*j/359.0 + for j in range(3): zeta[j]= np.pi*j/2.0 + r = wout.cfunct(theta,zeta,wout.rmnc,wout.xm,wout.xn/wout.nfp) + z = wout.sfunct(theta,zeta,wout.zmns,wout.xm,wout.xn/wout.nfp) + r2 = wout.cfunct(theta,zeta,np.broadcast_to(rmnc,(1,wout.mnmax)),wout.xm,wout.xn/wout.nfp) + z2 = wout.sfunct(theta,zeta,np.broadcast_to(zmns,(1,wout.mnmax)),wout.xm,wout.xn/wout.nfp) + ax.plot(r[1,1,0],z[1,1,0],'+r') + ax.plot(r[1,1,1],z[1,1,1],'+g') + ax.plot(r[1,1,2],z[1,1,2],'+b') + j = wout.ns-1 + ax.plot(r[j,:,0],z[j,:,0],'r',label='Plasma') + ax.plot(r[j,:,1],z[j,:,1],'g') + ax.plot(r[j,:,2],z[j,:,2],'b') + j = 0 + ax.plot(r2[j,:,0],z2[j,:,0],'--r',label='Limiter') + ax.plot(r2[j,:,1],z2[j,:,1],'--g') + ax.plot(r2[j,:,2],z2[j,:,2],'--b') + ax.set_xlabel(r"R [m]$") + ax.set_ylabel(r"Z [m]") + ax.set_title("FOCUS Limiter Surface") + ax.set_aspect('equal', adjustable='box') + ax.legend() + pyplot.show() + if args.lplot: + px = 1/pyplot.rcParams['figure.dpi'] + fig,((ax1,ax2),(ax3,ax4)) = pyplot.subplots(2,2,figsize=(1024*px,768*px)) + pyplot.subplots_adjust(hspace=0.3,wspace=0.3) + focus_data.plotConvergence(ax1) + focus_data.plotBNormal(ax2) + focus_data.plotPoincare(ax3) + focus_data.plotIota(ax4) + pyplot.show() + if args.lplot3d: + px = 1/pyplot.rcParams['figure.dpi'] + fig=pyplot.figure(figsize=(1024*px,768*px)) + ax1=fig.add_subplot(111,projection='3d') + focus_data.plotBN3D(ax1) + try: + coil_data.read_coils_file(args.focus_ext+'.coils') + coil_data.plotcoilsHalfFP(ax1) + except: + i=1 + pyplot.show() + if args.lplotcoildist: + px = 1/pyplot.rcParams['figure.dpi'] + fig=pyplot.figure(figsize=(1024*px,768*px)) + ax1=fig.add_subplot(111,projection='3d') + coil_data.read_coils_file(args.focus_ext+'.coils') + coil_data.coilSurfDist(focus_data.xsurf.flatten(),\ + focus_data.ysurf.flatten(),\ + focus_data.zsurf.flatten()) + coil_data.plotcoilsDist(ax=ax1) + ax1.set_axis_off() + pyplot.show() diff --git a/pySTEL/libstell/__init__.py b/pySTEL/libstell/__init__.py deleted file mode 100644 index 483427092..000000000 --- a/pySTEL/libstell/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -def get_s123(): - import os - import ctypes as ct - from subprocess import Popen, PIPE - - # Load Libraries - try: - path = os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so" - libstell = ct.cdll.LoadLibrary(path) - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - # get the full function list - out = Popen(args="nm "+path, - shell=True, - stdout=PIPE).communicate()[0].decode("utf-8") - attrs = [ i.split(" ")[-1].replace("\r", "") - for i in out.split("\n") if " T " in i] - func = '_write_wout_file' - module = 'read_wout_mod_' - names = [ s for s in attrs if module in s and func in s] - name = names[0].replace(module, ',') - name = name.replace(func, ',') - s1, s2, s3 = name.split(',') - # This is a catch for weird Macports OSX behavior - if s1=='___': - s1='__' - return s1, s2, s3 -s1, s2, s3 = get_s123() - -__all__ = ["libstell","stellopt","fieldlines","beams3d"] diff --git a/pySTEL/libstell/beams3d.py b/pySTEL/libstell/beams3d.py index 9362e1385..70f0a0438 100644 --- a/pySTEL/libstell/beams3d.py +++ b/pySTEL/libstell/beams3d.py @@ -1,31 +1,495 @@ -def read_beams3d(file): - import h5py - import numpy as np - beams_data = {} - #read file - with h5py.File(file,'r') as f: - # Logicals - for temp in ['lascot', 'lbeam', 'lbeam_simple', 'lcoil', 'lcollision', 'ldepo', 'lflux', 'lmgrid', 'lpies', 'lspec',\ - 'lvac', 'lvessel', 'lvmec']: - if temp in f: - beams_data[temp] = np.int64(f[temp][0]) - # Integers - for temp in ['nbeams', 'nface', 'nparticles', 'nphi', 'npoinc', 'nz', 'nsteps', 'nvertex', 'nz']: - if temp in f: - beams_data[temp] = np.int64(f[temp][0]) - # Floats - for temp in ['VERSION','iota0']: - if temp in f: - beams_data[temp] = np.float64(f[temp][0]) - # Arrays - for temp in ['B_PHI', 'B_R', 'B_Z', 'B_lines', 'NE', 'PE_lines', 'PHI_lines', 'PI_lines', 'POT_ARR', 'R_lines',\ - 'S_ARR', 'S_lines', 'Shinethrough', 'TE', 'TI', 'U_ARR', 'U_lines', 'ZEFF_ARR', 'Z_lines', 'Zatom', \ - 'charge','mass','moment_lines','neut_lines','phiaxis','raxis','t_end','vll_lines','wall_faces','wall_strikes',\ - 'wall_vertex','zaxis','end_state','wall_load','wall_shine','epower_prof','ipower_prof','j_prof',\ - 'ndot_prof','dense_prof','dist_prof','Weight','Beam']: - if temp in f: - beams_data[temp] = np.array(f[temp][:]) - # Make derived arrays - beams_data['X_lines'] = beams_data['R_lines']*np.cos(beams_data['PHI_lines']) - beams_data['Y_lines'] = beams_data['R_lines']*np.sin(beams_data['PHI_lines']) - return beams_data \ No newline at end of file +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for reading and handling +BEAMS3D Energetic particle data. +""" + +# Libraries +from libstell.libstell import LIBSTELL + +# Constants + +# BEAMS3D Class +class BEAMS3D(): + """Class for working with BEAMS3D data + + """ + def __init__(self): + test = 0 + + def read_beams3d(self,file): + """Reads a BEAMS3D HDF5 file + + This routine reads and initilizes the BEAMS3D + class with variable information from an HDF5 file. + + Parameters + ---------- + file : str + Path to HDF5 file. + """ + import h5py + import numpy as np + beams_data = {} + #read file + with h5py.File(file,'r') as f: + # Logicals + for temp in ['lascot', 'lbeam', 'lbeam_simple', \ + 'lcoil', 'lcollision', 'ldepo', 'lflux', \ + 'lmgrid', 'lpies', 'lspec', 'lvac', \ + 'lvessel', 'lvmec', 'leqdsk', 'lhint', \ + 'lfusion', 'lboxsim', 'lhitonly']: + if temp in f: + setattr(self, temp, np.int64(f[temp][0])==1) + # Integers + for temp in ['nbeams', 'nface', 'nparticles', 'nphi', \ + 'npoinc', 'nr', 'nsteps', 'nvertex', 'nz', \ + 'ns_prof1', 'ns_prof2', 'ns_prof3', \ + 'ns_prof4', 'ns_prof5']: + if temp in f: + setattr(self, temp, np.int64(f[temp][0])) + # Floats + for temp in ['VERSION','plasma_mass','plasma_Zmean', \ + 'B_kick_min', 'B_kick_max', 'freq_kick', \ + 'E_kick', 'partvmax']: + if temp in f: + setattr(self, temp, float(f[temp][0])) + # Arrays + for temp in ['raxis', 'phiaxis', 'zaxis', 'B_R', \ + 'B_PHI', 'B_Z', 'S_ARR', 'U_ARR', 'POT_ARR', \ + 'GFactor', 'TE', 'NE', 'NI', 'TI', \ + 'ZEFF_ARR', 'wall_vertex', 'wall_faces', \ + 'mass', 'charge', 'Weight', 'Beam', 'Zatom', \ + 'end_state', 'Energy', 'wall_strikes', \ + 'wall_load', 'wall_shine', 'beam_density', \ + 't_end', 'R_lines', 'Z_lines', 'PHI_lines', \ + 'vll_lines', 'neut_lines', 'moment_lines', \ + 'S_lines', 'U_lines', 'B_lines', \ + 'dist_rhoaxis', 'dist_uaxis', 'dist_paxis', \ + 'dist_Vaxis', 'dist_Waxis', 'ndot_prof', \ + 'epower_prof', 'ipower_prof', 'j_prof', \ + 'dense_prof', 'dist_prof', 'Shinethrough', \ + 'Shineport', 'NEUTRON_RATE', 'E_NEUTRONS']: + if temp in f: + setattr(self, temp, np.array(f[temp][:])) + # Make derived arrays + self.X_lines = self.R_lines*np.cos(self.PHI_lines) + self.Y_lines = self.R_lines*np.sin(self.PHI_lines) + self.MODB = np.sqrt(self.B_R**2 + self.B_PHI**2 + self.B_Z**2) + return + + def calcVperp(self): + """Calculates the perpendicular marker velocity + + This routine calcualtes the perpendicular marker velocity + from the magnetic moment. + + Returns + ------- + Vperp : float + Perpendicular velocity [m/s] + """ + mass2D = np.broadcast_to(self.mass,(self.nsteps+1,self.nparticles)) + vperp = np.sqrt(2.0*self.moment_lines*self.B_lines/mass2D) + vperp = np.where(self.B_lines < 0,0,vperp) + return vperp + + + def calcBaxis(self,kphi=0): + """Calculates the magnetic field on axis + + This routine calcualtes the magnetic field on axis + given a toroidal cut in the background grid. Default is + to use the first toroidald gridpoint (phi=0). + + Parameters + ---------- + kphi : int (optional) + Toroidal plane to evaluate + + Returns + ------- + Baxis : float + Magnetic field on axis. + """ + import numpy as np + S2D = np.squeeze(self.S_ARR[:,kphi,:]) + B2D = np.squeeze(self.MODB[:,kphi,:]) + dex = np.argwhere(S2D == np.min(S2D)).flatten() + return B2D[dex[0],dex[1]] + + def calcAminor(self): + """Calculates the minor radius + + This routine calculates the minor radius using the + normalized toroidal flux label (S). + + Returns + ------- + Aminor : float + Equilibrium minor radius + """ + import numpy as np + from contourpy import contour_generator, LineType + Aminor = 0 + for k in range(self.nphi): + S2D = np.squeeze(self.S_ARR[:,k,:]) + S2D = np.where(S2D>1.2,1.2,S2D) + dex = np.argwhere(S2D == np.min(S2D)).flatten() + r0 = self.raxis[dex[0]] + z0 = self.zaxis[dex[1]] + cont_gen = contour_generator(x=self.raxis,y=self.zaxis,z=S2D, line_type=LineType.Separate) + lines = cont_gen.lines(1.0) + lines = lines[0] + x = lines[:,0] - r0 + y = lines[:,1] - z0 + Aminor = Aminor + np.mean(np.sqrt(x*x+y*y)) + return Aminor/self.nphi + + def calcVolume(self,ns=None): + """Calculates the differential volume + + This routine calcualtes the differential volume and the volume + as a function of normalized toroidal flux (S). + + Parameters + ---------- + ns : int (optional) + Number of radial gridpoints (default ns_prof1) + + Returns + ------- + S : ndarray + Normalized toroidal flux array + V : ndarray + Volume [m^3] + dVds : ndarray + Differential volume dV/ds [m^3] + """ + import numpy as np + from scipy.signal import savgol_filter + + if not ns: + ns = self.ns_prof1 + dr = self.raxis[1] - self.raxis[0] + dz = self.zaxis[1] - self.zaxis[0] + dp = self.phiaxis[1] - self.phiaxis[0] + nfp = np.round(2*np.pi/self.phiaxis[-1]) + + area = dr*dz + vol = self.raxis*dp*area + vol2d = np.broadcast_to(vol,(self.nr,self.nz)) + dV = np.zeros((self.nr,self.nphi,self.nz)) + for j in range(self.nphi-1): + grid = np.squeeze(self.S_ARR[:,j,:]) + dV[:,j,:] = np.where(grid<=1,vol2d,0.0) + + edges = np.linspace(0.0,1.0,ns+1) + ds = edges[1]-edges[0] + s = (edges[1:]+edges[0:-1])*0.5 + + plasma_dvolds = np.zeros((ns)) + for i in range(ns): + dtemp = np.where( self.S_ARR > edges[i], \ + dV,0.0) + dtemp = np.where( self.S_ARR <= edges[i+1], \ + dtemp,0.0) + plasma_dvolds[i] = np.sum(dtemp) + + plasma_dvolds = savgol_filter(plasma_dvolds,5,2)*nfp/ds + plasma_vol = np.cumsum(plasma_dvolds)*ds + + z = np.polyfit(s,plasma_vol,3) + p = np.poly1d(z) + pp = np.polyder(p) + plasma_dvolds = pp(s) + plasma_vol = np.cumsum(plasma_dvolds)*ds + + return s, plasma_vol, plasma_dvolds + + def calcProfiles(self,ns=None): + """Calculates the kinetic plasma profiles used + + This routine claculates the kinetic profiles used in the + BEAMS3D simulation based on the background grid quantities. + + Parameters + ---------- + ns : int (optional) + Number of radial gridpoints (default ns_prof1) + + Returns + ------- + S : ndarray + Normalized toroidal flux array + ne : ndarray + Electron Density [m^-3] + ni : ndarray + Ion Density [m^-3] + te : ndarray + Electron Temperature [eV] + ti : ndarray + Ion Temperature [eV] + zeff : ndarray + Effective ion charge + """ + import numpy as np + from scipy.interpolate import PchipInterpolator + + # Radial grid + if not ns: + ns = self.ns_prof1 + s = np.linspace(0.0,1.0,ns) + + # Extract data + [C, IA] = np.unique(self.S_ARR,return_index=True) + NE_FLAT = self.NE.flatten() + TE_FLAT = self.TE.flatten() + TI_FLAT = self.TI.flatten() + ZEFF_FLAT = self.ZEFF_ARR.flatten() + ne_temp = NE_FLAT[IA] + te_temp = TE_FLAT[IA] + ti_temp = TI_FLAT[IA] + zeff_temp = ZEFF_FLAT[IA] + + # Extract Ion density + nni = np.size(self.NI,3) + ni_temp = np.zeros((nni,len(IA))) + for i in range(nni): + NI_FLAT = self.NI[:,:,:,i].flatten() + ni_temp[i,:] = NI_FLAT[IA] + + # Make Mirror + C = np.concatenate((-C[::-1], C)) + ne_temp = np.concatenate((ne_temp[::-1], ne_temp)) + te_temp = np.concatenate((te_temp[::-1], te_temp)) + ti_temp = np.concatenate((ti_temp[::-1], ti_temp)) + zeff_temp = np.concatenate((zeff_temp[::-1], zeff_temp)) + ni_temp = np.concatenate((ni_temp[:,::-1],ni_temp),axis=1) + + + # Fit + [C, IA] = np.unique(C,return_index=True) + ne_spl = PchipInterpolator(C,ne_temp[IA]) + te_spl = PchipInterpolator(C,te_temp[IA]) + ti_spl = PchipInterpolator(C,ti_temp[IA]) + zeff_spl = PchipInterpolator(C,zeff_temp[IA]) + ne = ne_spl(s) + te = te_spl(s) + ti = ti_spl(s) + zeff = zeff_spl(s) + ni = np.zeros((nni,ns)) + for i in range(nni): + ni_spl = PchipInterpolator(C,ni_temp[i,IA]) + ni[i,:] = ni_spl(s) + + return s,ne,ni,te,ti,zeff + + def calcEr(self,ns=None): + """Calculates the radial electric field + + This routine calcualtes the radial electric field and returns + the radial grid (s), electrostatic scalar potential (V), and + the radial derivative of the electrostatic scalar potential. + Note that Er = dV/ds * ds/dr + = dV/ds * ds/drho * drho/dr + = dV/ds * 2.0 * rho * (1.0/Aminor) + s = rho*rho -> ds/drho = 2 * rho + rho = r/Aminor -> drho/dr = 1.0 / Aminor + + Parameters + ---------- + ns : int (optional) + Number of radial gridpoints (default ns_prof1) + + Returns + ------- + S : ndarray + Normalized toroidal flux array + V : ndarray + Electrostatic scalar potential [V] + dVds : ndarray + Radial derivative of the ES potential (dV/ds) [V] + """ + import numpy as np + from scipy.interpolate import PchipInterpolator + + # Radial grid + if not ns: + ns = self.ns_prof1 + s = np.linspace(0.0,1.0,ns) + + # Extract data + [C, IA] = np.unique(self.S_ARR,return_index=True) + POT_FLAT = self.POT_ARR.flatten() + pot_temp = POT_FLAT[IA] + + # Make Mirror + C = np.concatenate((-C[::-1], C)) + pot_temp = np.concatenate((pot_temp[::-1], pot_temp)) + + # Fit + [C, IA] = np.unique(C,return_index=True) + p = PchipInterpolator(C,pot_temp[IA]) + V = p(s) + x = np.concatenate((-s[:0:-1],s)) + f = np.concatenate((V[:0:-1],V)) + dVds = np.gradient(f,x) + return s, V, dVds + + def calcMagaxis(self): + """Calculates the magetic axis location + + This routine calcualtes the magnetic axis location in each + toroidal cut of the background grid. The magnetic axis is + returned in an R array and Z array for each toridal cut. + + Returns + ------- + R : ndarray + Magnetic axis radial position (R) [m] + Z : ndarray + Magnetic axis vertical position (R) [m] + """ + import numpy as np + raxis = [] + zaxis = [] + for k in range(self.nphi-1): + S2D = np.squeeze(self.S_ARR[:,k,:]) + S2D = np.where(S2D>1.2,1.2,S2D) + dex = np.argwhere(S2D == np.min(S2D)).flatten() + raxis.append(self.raxis[dex[0]]) + zaxis.append(self.zaxis[dex[1]]) + raxis.append(raxis[0]) + zaxis.append(zaxis[0]) + return np.array(raxis),np.array(zaxis) + + + def calcDepo(self,ns=None): + """Calculates the deposition profile + + This routine calcualtes the radial birth profile in + units of [part/m^3/s] + + Parameters + ---------- + ns : int (optional) + Number of radial gridpoints (default ns_prof1) + + Returns + ------- + rho : ndarray + Normalized minor radius array + birth : ndarray + Birth Rate [part/m^3/s] + """ + import numpy as np + from scipy.interpolate import PchipInterpolator + + # Setup rho on centered grid + if not ns: + ns = self.ns_prof1 + edges = np.linspace(0.0,1.0,ns+1) + rho = (edges[1:]+edges[0:-1])/2.0 + + # Calc volume elements + [s,_,dVds]=self.calcVolume(ns=ns) + rho_s = np.sqrt(s) + p = PchipInterpolator(rho_s,2.0*rho_s*dVds) + dVdrho = p(rho) + + # Select start index + dex_start = 0 + if self.lbeam: + dex_start = 1 + + # Calc births + births = np.zeros((self.nbeams,ns)) + rho_lines = np.sqrt(self.S_lines) + for b in range(self.nbeams): + dexb = np.nonzero(self.Beam == b+1) + rho_temp = rho_lines[dexb,dex_start] + for i in range(ns): + w_temp = self.Weight[dexb] + w_temp = np.where(rho_temp >= edges[i],w_temp,0.0) + w_temp = np.where(rho_temp < edges[i+1],w_temp,0.0) + births[b,i] = np.sum(w_temp) + births[b,:] = ns * births[b,:] / dVdrho + + return rho,births + + def calcLoss(self,ns=None): + """Calculates the losses as a function of time + + This routine calcualtes the cumulative losses as a function of + time for each beam line. Losses are of particles not + markers. + + Returns + ------- + time : ndarray + Time array [s] + loss : ndarray + Losses [particles] + """ + import numpy as np + + # Setup time arrays + time_ns = np.linspace(0,0.999E-6,1000) + time_mus = np.linspace(1E-6,0.999E-3,1000) + time_ms = np.linspace(1E-3,1,1000) + time = np.append([time_ns,time_mus,time_ms]) + + # Calc losses + loss = np.zeros((self.nbeams,len(time))) + for b in range(self.nbeams): + lostdex = np.nonzero(self.end_state==2 and self.Beam == b) + t = self.t_end[lostdex] + w = self.Weight[lostdext] + [counts,_] = np.histogram(t,bins=time,weights=w) + nlost = np.cumsum(counts) + lost[b,:] = nlost + + return time,nlost + +# BEASM3D Input Class +class BEAMS3D_INPUT(): + """Class for working with BEAMS3D INPUT data + + """ + def __init__(self, parent=None): + self.libStell = LIBSTELL() + + def read_input(self,filename): + """Reads BEAMS3D_INPUT namelist from a file + + This routine wrappers the beams3d_input_mod module reading routine. + Parameters + ---------- + filename : string + Input file name with BEASM3D_INPUT namelist + """ + indata_dict = self.libStell.read_beams3d_input(filename) + for key in indata_dict: + setattr(self, key, indata_dict[key]) + + def write_input(self,filename): + """Writes BEASM3D_INPUT namelist to a file + + This routine wrappers the beams3d_input_mod module writing routine. + Parameters + ---------- + filename : string + Input file name to write BEASM3D_INPUT namelist to + """ + out_dict = vars(self) + self.libStell.write_beams3d_input(filename,out_dict) + +# Main routine +if __name__=="__main__": + import sys + sys.exit(0) + + + diff --git a/pySTEL/libstell/bnorm.py b/pySTEL/libstell/bnorm.py new file mode 100644 index 000000000..fc79cd299 --- /dev/null +++ b/pySTEL/libstell/bnorm.py @@ -0,0 +1,128 @@ +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for reading and handling BNORM +data. +""" + +# Libraries +from libstell.libstell import LIBSTELL, FourierRep + +# Constants + +# VMEC Class +class BNORM(FourierRep): + """Class for working with VMEC equilibria + + """ + def __init__(self): + super().__init__() + self.libStell = LIBSTELL() + + def read_bnorm(self,filename): + """Reads a BNORM file + + This routine reads and initilizes the BNORM class + with variable information from a BNORM file. + + Parameters + ---------- + file : str + Path to wout file. + """ + import numpy as np + f = open(filename,'r') + lines = f.readlines() + f.close() + self.mnmax = len(lines) + self.xm = np.zeros((self.mnmax)) + self.xn = np.zeros((self.mnmax)) + self.bnmnc = np.zeros((1,self.mnmax)) + self.bnmns = np.zeros((1,self.mnmax)) + mn = 0 + for line in lines: + (txt1,txt2,txt3) = line.split() + self.xm[mn] = int(txt1) + self.xn[mn] = int(txt2) + self.bnmnc[0,mn] = float(txt3) + mn = mn + 1 + + def plotBnmnSpectrum(self,ax=None): + """Plots the Bnormal spectrum for a surface + + This routine plots the bnormal spectrum for a given + surface. + + Parameters + ---------- + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes() + lplotnow = True + # Array extents + mmax = int(max(np.squeeze(self.xm))) + nmax = int(max(np.squeeze(self.xn))) + # Sort BMN into array + bmn = np.zeros((mmax+1,2*nmax+1)) + for mn in range(self.mnmax): + m = self.xm[mn] + n = int(self.xn[mn]) + nmax + bmn[m,n] = self.bmnc_b[1,mn] + #Plot + x = np.linspace(0,mmax,mmax+1) + y = np.linspace(-nmax,nmax,2*nmax+1) + hmesh=ax.pcolormesh(x,y,np.log10(np.abs(bmn.T)),cmap='jet',shading='gouraud') + ax.set_xlabel('Poloidal Modes (m)') + ax.set_ylabel('Toroidal Modes (n)') + ax.set_title(rf'BNORM Normal Field') + pyplot.colorbar(hmesh,label='$log_{10}$[arb]',ax=ax) + if lplotnow: pyplot.show() + + def plotBsurf(self,ax=None): + """Plots the Bnormal on a surface + + This routine plots the bnormal. + + Parameters + ---------- + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes() + lplotnow = True + theta = np.ndarray((360,1)) + zeta = np.ndarray((256,1)) + for j in range(360): theta[j]=2.0*np.pi*j/359.0 + for j in range(256): zeta[j]=2.0*np.pi*j/256.0 + b = self.cfunct(theta,zeta,self.bnmnc,self.xm,self.xn) + hmesh=ax.pcolormesh(np.squeeze(zeta),np.squeeze(theta),np.squeeze(b[1,:,:]),cmap='jet',shading='gouraud') + ax.set_xlabel(r'Toroidal Angle ($\phi$) [rad]') + ax.set_ylabel(r'Poloidal Angle ($\theta$) [rad]') + ax.set_title(rf'BNORM') + pyplot.colorbar(hmesh,label=r'$B_{normal}$ [arb]',ax=ax) + if lplotnow: pyplot.show() + + + +# Main routine +if __name__=="__main__": + import sys + sys.exit(0) + + + + + + + + + diff --git a/pySTEL/libstell/bootsj.py b/pySTEL/libstell/bootsj.py new file mode 100644 index 000000000..239e2f705 --- /dev/null +++ b/pySTEL/libstell/bootsj.py @@ -0,0 +1,111 @@ +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for reading and handling +BOOTSJ data. +""" + +# Libraries +#from libstell import libstell + +# Constants + +# BOOTSJ Class +class BOOTSJ(): + """Class for working with BOOTSJ data + + """ + def __init__(self): + test = 0 + + def read_jBbs(self,filename): + """Reads a BOOTSJ jBbs file + + This routine reads a BOOTSJ jBbs file. + + Parameters + ---------- + file : str + Path to jBbs file. + """ + import numpy as np + f = open(filename,'r') + lines = f.readlines() + f.close() + #check header + if 'surface' not in lines[0]: + print("Bad Synatx line 1 in jBbs file") + npts = int(len(lines)) + self.jBbs_s = np.zeros((npts)) + self.jBbs_JbsdotB = np.zeros((npts)) + self.jBbs_tokfrac = np.zeros((npts)) + for i in range(npts): + line = lines[i+1].split() + self.jBbs_s[i] = float(line[0]) + self.jBbs_JbsdotB[i] = float(line[1]) + self.jBbs_tokfrac[i] = float(line[2]) + + def read_answers_plot(self,filename): + """Reads a BOOTSJ answers_plot file + + This routine reads a BOOTSJ answers_plot file. + + Parameters + ---------- + file : str + Path to answers_plot file. + """ + import numpy as np + f = open(filename,'r') + lines = f.readlines() + f.close() + # No header + npts = int(len(lines)) + self.rhoar = np.zeros((npts)) + self.gbsnorm = np.zeros((npts)) + self.amain = np.zeros((npts)) + self.aiterm1 = np.zeros((npts)) + self.other1 = np.zeros((npts)) + self.dibs = np.zeros((npts)) + self.bsdense = np.zeros((npts)) + self.bsdensi = np.zeros((npts)) + self.bstempe = np.zeros((npts)) + self.bstempi = np.zeros((npts)) + self.qsafety = np.zeros((npts)) + self.ftrapped = np.zeros((npts)) + self.bsnorm = np.zeros((npts)) + self.tempe1 = np.zeros((npts)) + self.tempi1 = np.zeros((npts)) + self.dense = np.zeros((npts)) + self.densi = np.zeros((npts)) + self.betar = np.zeros((npts)) + self.ajBbs = np.zeros((npts)) + for i in range(npts): + line = lines[i].split() + self.rhoar[i] = float(line[0]) + self.gbsnorm[i] = float(line[1]) + self.amain[i] = float(line[2]) + self.aiterm1[i] = float(line[3]) + self.other1[i] = float(line[4]) + self.dibs[i] = float(line[5]) + self.bsdense[i] = float(line[6]) + self.bsdensi[i] = float(line[7]) + self.bstempe[i] = float(line[8]) + self.bstempi[i] = float(line[9]) + self.qsafety[i] = float(line[10]) + self.ftrapped[i] = float(line[11]) + self.bsnorm[i] = float(line[12]) + self.tempe1[i] = float(line[13]) + self.tempi1[i] = float(line[14]) + self.dense[i] = float(line[15]) + self.densi[i] = float(line[16]) + self.betar[i] = float(line[17]) + self.ajBbs[i] = float(line[18]) + +if __name__=="__main__": + import sys + sys.exit(0) + + + + diff --git a/pySTEL/libstell/boozer.py b/pySTEL/libstell/boozer.py new file mode 100644 index 000000000..517f36504 --- /dev/null +++ b/pySTEL/libstell/boozer.py @@ -0,0 +1,125 @@ +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for reading and handling BOOZER +transform data. +""" + +# Libraries +from libstell.libstell import LIBSTELL, FourierRep + +# Constants + +# VMEC Class +class BOOZER(FourierRep): + """Class for working with VMEC equilibria + + """ + def __init__(self): + super().__init__() + self.nfp = None + self.libStell = LIBSTELL() + + def read_boozer(self,filename): + """Reads a BOOZER boozmn file + + This routine reads and initilizes the BOOZER class + with variable information from a BOOZER boozmn file. + + Parameters + ---------- + file : str + Path to wout file. + """ + import numpy as np + boozmn_dict = self.libStell.read_boozer(filename) + for key in boozmn_dict: + setattr(self, key, boozmn_dict[key]) + self.mboz_b = int(max(np.squeeze(self.ixm_b))) + nmax = int(max(np.squeeze(self.ixn_b))/self.nfp_b) + + def plotBmnSpectrum(self,sval,ax=None): + """Plots the boozer spectrum for a surface + + This routine plots the boozer spectrum for a given + surface. + + Parameters + ---------- + sval : int + Surface to plot + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes() + lplotnow = True + # Array extents + mmax = int(max(np.squeeze(self.ixm_b))) + nmax = int(max(np.squeeze(self.ixn_b))/self.nfp_b) + # Sort BMN into array + bmn = np.zeros((mmax+1,2*nmax+1)) + for mn in range(self.mnboz_b): + m = self.ixm_b[mn,0] + n = int(self.ixn_b[mn,0]/self.nfp_b) + nmax + bmn[m,n] = self.bmnc_b[sval,mn] + #Plot + x = np.linspace(0,mmax,mmax+1) + y = np.linspace(-nmax,nmax,2*nmax+1) + hmesh=ax.pcolormesh(x,y,np.log10(np.abs(bmn.T)),cmap='jet',shading='gouraud') + ax.set_xlabel('Poloidal Modes (m)') + ax.set_ylabel('Toroidal Modes (n)') + ax.set_title(rf'BOOZER $s$ = {sval/self.ns_b:5.2f}') + pyplot.colorbar(hmesh,label='$log_{10}$[T]',ax=ax) + if lplotnow: pyplot.show() + + def plotBsurf(self,sval,ax=None): + """Plots the boozer |B| on a surface + + This routine plots the boozer |B| for a given + surface. + + Parameters + ---------- + sval : int + Surface to plot + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes() + lplotnow = True + theta = np.ndarray((360,1)) + zeta = np.ndarray((256,1)) + for j in range(360): theta[j]=2.0*np.pi*j/359.0 + for j in range(256): zeta[j]=2.0*np.pi*j/256.0 + b = self.cfunct(theta,zeta,self.bmnc_b,self.ixm_b,self.ixn_b/self.nfp_b) + hmesh=ax.pcolormesh(np.squeeze(zeta),np.squeeze(theta),np.squeeze(b[sval,:,:]),cmap='jet',shading='gouraud') + ax.plot(zeta,zeta*self.iota_b[sval],'w') + ax.set_xlabel(r'Toroidal Angle ($\phi$) [rad]') + ax.set_ylabel(r'Poloidal Angle ($\theta$) [rad]') + ax.set_title(rf'BOOZER $s$ = {sval/self.ns_b:5.2f}') + pyplot.colorbar(hmesh,label='[T]',ax=ax) + if lplotnow: pyplot.show() + + + +# Main routine +if __name__=="__main__": + import sys + sys.exit(0) + + + + + + + + + diff --git a/pySTEL/libstell/coils.py b/pySTEL/libstell/coils.py new file mode 100644 index 000000000..d9f479817 --- /dev/null +++ b/pySTEL/libstell/coils.py @@ -0,0 +1,827 @@ +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for working with coils files +""" + +# Libraries +from libstell.libstell import LIBSTELL + +# Constants + +# VMEC Class +class COILSET(LIBSTELL): + """Class for working with coils files + + """ + def __init__(self): + from collections import deque + super().__init__() + self.libStell = LIBSTELL() + self.nfp = None + self.ngroups = None + self.groups = [] + self.xmin=None; self.xmax=None; + self.ymin=None; self.ymax=None; + self.zmin=None; self.zmax=None; + self.color_cycle = deque(['g', 'b', 'c', 'm', 'y', 'k']) + + def read_coils_file(self,filename): + """Directly reads a coils file + + This routine reads a coils file into the class. + + Parameters + ---------- + filename : str + Path to coils file. + """ + import numpy as np + f = open(filename,'r') + lines = f.readlines() + f.close() + if 'periods' in lines[0]: + self.nfp = int(lines[0][8:]) + else: + print("Bad Synatx line 1 in coils file") + if 'begin filament' not in lines[1]: + print("Bad Synatx line 2 in coils file") + if 'mirror' not in lines[2]: + print("Bad Synatx line 3 in coils file") + npts = int(len(lines))-3 + if 'end' in lines[-1]: npts = npts - 1 + coords = np.zeros((3,npts)) + group = np.zeros((npts)) + current = np.zeros((npts)) + coilnames = [] + last_dex = 0 + self.ngroups = 0 + for i in range(0,npts): + line = lines[i+3].split() + if len(line) < 4: continue + #print(line) + coords[0,i] = float(line[0]) + coords[1,i] = float(line[1]) + coords[2,i] = float(line[2]) + current[i] = float(line[3]) + if len(line) == 6: + if int(line[4]) not in group: + coilnames.extend([line[5]]) + self.ngroups = max([self.ngroups,int(line[4])]) + group[last_dex:i+1] = int(line[4]) + last_dex=i+1 + # Set extents + self.xmin = min(coords[0]); self.xmax = max(coords[0]) + self.ymin = min(coords[1]); self.ymax = max(coords[1]) + self.zmin = min(coords[2]); self.zmax = max(coords[2]) + # Create the coil object + for i in range(self.ngroups): + x = coords[0,group==(i+1)] + y = coords[1,group==(i+1)] + z = coords[2,group==(i+1)] + c = current[group==(i+1)] + self.groups.extend([COILGROUP(x,y,z,c,coilnames[i])]) + + def plotcoils(self,ax=None,*args,**kwargs): + """Plots a coilset in 3D + + This routine plots coils in 3D + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes(projection='3d') + lplotnow = True + c_temp = self.color_cycle[0] + for i in range(self.ngroups): + for j in range(self.groups[i].ncoils): + if j == 0: + ax.plot(self.groups[i].coils[j].x, \ + self.groups[i].coils[j].y, \ + self.groups[i].coils[j].z, c=c_temp, label=self.groups[i].name) + else: + ax.plot(self.groups[i].coils[j].x, \ + self.groups[i].coils[j].y, \ + self.groups[i].coils[j].z, c=c_temp) + self.color_cycle.rotate(1) + c_temp = self.color_cycle[0] + ax.set_xlim(self.xmin*1.05,self.xmax*1.05); ax.set_xlabel('X [m]') + ax.set_ylim(self.ymin*1.05,self.ymax*1.05); ax.set_ylabel('Y [m]') + ax.set_zlim(self.zmin*1.05,self.zmax*1.05); ax.set_zlabel('Z [m]') + ax.set_title('COILS') + ax.set_aspect('equal', adjustable='box') + pyplot.legend(loc="upper left") + if lplotnow: pyplot.show() + + def plotcoilsHalfFP(self,ax=None,*args,**kwargs): + """Plots a coilset for a half field period + + This routine plots coils in 3D for a half field period. + Really it plots the first coil in each group. + """ + import numpy as np + import matplotlib.pyplot as pyplot + import mpl_toolkits.mplot3d as mplot3d + lplotnow = False + if not ax: + ax = pyplot.axes(projection='3d') + lplotnow = True + c_temp = self.color_cycle[0] + for i in range(self.ngroups): + j = 0 + ax.plot(self.groups[i].coils[j].x, \ + self.groups[i].coils[j].y, \ + self.groups[i].coils[j].z, c=c_temp, label=self.groups[i].name) + self.color_cycle.rotate(1) + c_temp = self.color_cycle[0] + ax.set_aspect('equal', adjustable='box') + pyplot.legend(loc="upper left") + if lplotnow: pyplot.show() + + def plotcoilsDist(self,ax=None,*args,**kwargs): + """Plots a coilset for a half field period + + This routine plots coils in 3D for a half field period. + Really it plots the first coil in each group. + """ + import numpy as np + import matplotlib.pyplot as pyplot + from mpl_toolkits.mplot3d.art3d import Line3DCollection + lplotnow = False + if not ax: + ax = pyplot.axes(projection='3d') + lplotnow = True + c_temp = self.color_cycle[0] + xmin = 1E6; xmax = -1E6 + ymin = 1E6; ymax = -1E6 + zmin = 1E6; zmax = -1E6 + vmin = 1E6; vmax = -1E6 + for i in range(self.ngroups): + j = 0 + x = self.groups[i].coils[j].x + y = self.groups[i].coils[j].y + z = self.groups[i].coils[j].z + v = self.groups[i].coils[j].dist_surf + points = np.array([x,y,z]).transpose().reshape(-1,1,3) + segs = np.concatenate([points[:-1],points[1:]],axis=1) + lc = Line3DCollection(segs, cmap=pyplot.get_cmap('jet')) + lc.set_array(v) + h = ax.add_collection(lc) + xmin = min(x.min(),xmin) + xmax = max(x.max(),xmax) + ymin = min(y.min(),ymin) + ymax = max(y.max(),ymax) + zmin = min(z.min(),zmin) + zmax = max(z.max(),zmax) + vmin = min(v.min(),vmin) + vmax = max(v.max(),vmax) + print(v.min(),v.max(),vmin,vmax) + ax.axes.set_xlim3d(left=xmin, right=xmax) + ax.axes.set_ylim3d(bottom=ymin, top=ymax) + ax.axes.set_zlim3d(bottom=zmin, top=zmax) + ax.set_aspect('equal', adjustable='box') + cbar = pyplot.colorbar(h,label='Distance [m]',ax=ax) + h.set_clim(vmin,vmax) + if lplotnow: pyplot.show() + + def plotcoilsRZ(self,*args,**kwargs): + """Plots each coil in the RZ plot + + This routine plots coils in 2D R,Z projection. + """ + import numpy as np + import matplotlib.pyplot as pyplot + c_temp = self.color_cycle[0] + for i in range(self.ngroups): + fig=kwargs.pop('fig',pyplot.figure()) + ax=kwargs.pop('axes',fig.add_subplot(111)) + rmax = -1E7; rmin = 1E7 + zmax = -1E7; zmin = 1E7 + for j in range(self.groups[i].ncoils): + if j == 0: + r = np.sqrt(self.groups[i].coils[j].x**2 + self.groups[i].coils[j].y**2) + phi = np.arctan2(self.groups[i].coils[j].y,self.groups[i].coils[j].x) + ax.plot(r,self.groups[i].coils[j].z, c=c_temp) + rmin = min(rmin,min(r)) + rmax = max(rmin,max(r)) + zmin = min(zmin,min(self.groups[i].coils[j].z)) + zmax = max(zmin,max(self.groups[i].coils[j].z)) + ax.set_xlim(rmin*0.95,rmax*1.05); ax.set_xlabel('R [m]') + ax.set_ylim(zmin*1.05,zmax*1.05); ax.set_ylabel('Z [m]') + ax.set_title(f"Coil - {self.groups[i].name}") + pyplot.show() + self.color_cycle.rotate(1) + c_temp = self.color_cycle[0] + + def write_coils_file(self,filename): + """Writes a coils file + + This routine writes a coils file into a file. + + Parameters + ---------- + filename : str + Path to coils file. + """ + import numpy as np + f = open(filename,'w') + f.write(f"periods {self.nfp}\n") + f.write(f"begin filament\n") + f.write(f"mirror NIL\n") + for i in range(self.ngroups): + for j in range(self.groups[i].ncoils): + offset = 0 + if j == self.groups[i].ncoils-1: offset = 1 + current = np.ones((self.groups[i].coils[j].npts))*self.groups[i].current + current[-1] = 0 + for k in range(self.groups[i].coils[j].npts-offset): + f.write(f"{self.groups[i].coils[j].x[k]:.10E} {self.groups[i].coils[j].y[k]:.10E} {self.groups[i].coils[j].z[k]:.10E} {current[k]:.10E}\n") + k = self.groups[i].coils[j].npts-offset-1 + f.write(f"{self.groups[i].coils[j].x[k]:.10E} {self.groups[i].coils[j].y[k]:.10E} {self.groups[i].coils[j].z[k]:.10E} {current[k]:.10E} {i+1} {self.groups[i].name}\n") + f.close() + + def coilbiot(self,x,y,z,extcur=None): + """Calculates field at point in space + + This routine calculates the magnetic field at a point in space + given the point and external current array. + + Parameters + ---------- + x : real + Cartesian x value [m]. + y : real + Cartesian y value [m]. + z : real + Cartesian z value [m]. + extcur : list + Array of currents in coil groups [A] + Returns + ---------- + bx : real + Magnetic field in cartesian x direction [T] + by : real + Magnetic field in cartesian y direction [T] + bz : real + Magnetic field in cartesian z direction [T] + """ + import numpy as np + bx = 0; by = 0; bz = 0 + for i in range(self.ngroups): + for j in range(self.groups[i].ncoils): + if extcur: + bxt,byt,bzt = self.groups[i].coils[j].bfield(x,y,z,extcur[i]) + else: + bxt,byt,bzt = self.groups[i].coils[j].bfield(x,y,z,self.groups[i].current) + bx = bx + bxt + by = by + byt + bz = bz + bzt + return bx,by,bz + + def coilvecpot(self,x,y,z,extcur=None): + """Calculates vector potential at point in space + + This routine calculates the vector potential at a point in space + given the point and external current array. + + Parameters + ---------- + x : real + Cartesian x value [m]. + y : real + Cartesian y value [m]. + z : real + Cartesian z value [m]. + extcur : list + Array of currents in coil groups [A] + Returns + ---------- + ax : real + Vector potential in cartesian x direction [] + ay : real + Vector potential in cartesian y direction [] + az : real + Vector potential in cartesian z direction [] + """ + import numpy as np + ax = 0; ay = 0; az = 0 + for i in range(self.ngroups): + for j in range(self.groups[i].ncoils): + if extcur: + axt,ayt,azt = self.groups[i].coils[j].vecpot(x,y,z,extcur[i]) + else: + axt,ayt,azt = self.groups[i].coils[j].vecpot(x,y,z,self.groups[i].current) + ax = ax + axt + ay = ay + ayt + az = az + azt + return ax,ay,az + + def coiloffset(self,dist=0.0): + """Calculates offset from coils + + This routine calculates an offset position based on the + geometric mean of the coil. It returns an odered list of points. + + Parameters + ---------- + dist : real + Offset distance in [m] (- is toward geometric mean) + Returns + ---------- + vertex : ndarray [3,ncoils,npts] + Order set of points for each coil. + """ + import numpy as np + from scipy import interpolate + ntheta = 64 + l_new = np.linspace(0,1,ntheta) + ncoils_total = 0 + for i in range(self.ngroups): + for j in range(self.groups[i].ncoils): + ncoils_total = ncoils_total + 1 + k = 0 + vertex = np.zeros((3,ncoils_total,ntheta-1)) + P_order = np.zeros(ncoils_total) + for i in range(self.ngroups): + for j in range(self.groups[i].ncoils): + [x0,y0,z0] = self.groups[i].coils[j].geomCenter() + R0 = np.sqrt(x0*x0+y0*y0) + P0 = np.arctan2(y0,x0) + P_order[k] = P0 + l = np.linspace(0,1,self.groups[i].coils[j].npts) + x = np.interp(l_new,l,self.groups[i].coils[j].x,period=1) + y = np.interp(l_new,l,self.groups[i].coils[j].y,period=1) + z = np.interp(l_new,l,self.groups[i].coils[j].z,period=1) + R = np.sqrt(x*x+y*y) + p = np.arctan2(y,x) + dr = R-R0 + dz = z-z0 + d = np.sqrt(dr*dr+dz*dz) + r2 = R + dr*dist/d + z2 = z + dz*dist/d + x2 = r2 * np.cos(p) + y2 = r2 * np.sin(p) + vertex[0][k][:] = x2[0:-1] + vertex[1][k][:] = y2[0:-1] + vertex[2][k][:] = z2[0:-1] + k = k + 1 + # Reorder in phi + Pdex = P_order.argsort() + vertex = vertex[:,Pdex,:] + P_order = P_order[Pdex] + # Now Smooth + #nphi = 180 + #phi_new = np.linspace(-np.pi,np.pi,nphi) + #vertex2 = np.zeros((3,nphi,ntheta)) + #for i in range(ntheta): + # x_spl = interpolate.splrep(P_order, np.squeeze(vertex[0,:,i]),per=True) + # y_spl = interpolate.splrep(P_order, np.squeeze(vertex[1,:,i]),per=True) + # z_spl = interpolate.splrep(P_order, np.squeeze(vertex[2,:,i]),per=True) + # vertex2[0,:,i] = interpolate.splev(phi_new,x_spl) + # vertex2[1,:,i] = interpolate.splev(phi_new,y_spl) + # vertex2[2,:,i] = interpolate.splev(phi_new,z_spl) + return vertex + + def coilSurfDist(self,xs,ys,zs): + """Calculates coil-surface distance + + This routine calculates the distance between a coil and a + surface defined by points in cartesian coordiantes (x,y,z). + Values are stored in the coil atribute dist_coil. + + Parameters + ---------- + xs : ndarray + X points defining surface [m] + ys : ndarray + Y points defining surface [m] + zs : ndarray + Z points defining surface [m] + """ + for i in range(self.ngroups): + for j in range(self.groups[i].ncoils): + self.groups[i].coils[j].surfDist(xs,ys,zs) + + def blenderCoil(self,dist=0.2): + """Generates the lists Blender needs to render a coilset + + This routine generates the verticies and faces lists which + Blender needs to render a coil. + + Returns + ---------- + vertices : list + List of tuples defining verticies + faces: list + List of tubles defining faces + """ + import numpy as np + # Generate volumetric coil rendering + vertices = [] + faces = [] + l = int(0) + for i in range(self.ngroups): + for j in range(self.groups[i].ncoils): + xx,yy,zz = self.groups[i].coils[j].finiteBuildCoil(width=dist,height=dist) + for k in range(xx.shape[1]-1): + vertices.append((xx[0,k],yy[0,k],zz[0,k])) + vertices.append((xx[1,k],yy[1,k],zz[1,k])) + vertices.append((xx[2,k],yy[2,k],zz[2,k])) + vertices.append((xx[3,k],yy[3,k],zz[3,k])) + faces.append((l,l+1,l+5)) + faces.append((l,l+5,l+4)) + l=l+1 + faces.append((l,l+1,l+5)) + faces.append((l,l+5,l+4)) + l=l+1 + faces.append((l,l+1,l+5)) + faces.append((l,l+5,l+4)) + l=l+1 + faces.append((l,l-3,l+1)) + faces.append((l,l+1,l+4)) + l=l+1 + vertices.append((xx[0,-1],yy[0,-1],zz[0,-1])) + vertices.append((xx[1,-1],yy[1,-1],zz[1,-1])) + vertices.append((xx[2,-1],yy[2,-1],zz[2,-1])) + vertices.append((xx[3,-1],yy[3,-1],zz[3,-1])) + l = l + 4 + # Last step + #vertices = [] + #faces = [] + #for i in range(self.nvertex): + # vertices.append((self.vertex[i,0],self.vertex[i,1],self.vertex[i,2])) + #for i in range(self.nfaces): + # faces.append((int(self.faces[i,0]),int(self.faces[i,1]),int(self.faces[i,2]))) + return vertices,faces + + + + +class COILGROUP(): + """Class which defines a coil group + + """ + def __init__(self, x, y, z, current,name): + self.name = name + self.current = current[0] + self.coils = [] + idex = [index for index, value in enumerate(current) if value == 0] + self.ncoils = len(idex) + i = 0 + for j in idex: + # Reverse order the coil if current sign changes + if current[j-1] != current[0]: + x2 = x[i:j+1] + y2 = y[i:j+1] + z2 = z[i:j+1] + self.coils.extend([COIL(x2[::-1],y2[::-1],z2[::-1])]) + else: + self.coils.extend([COIL(x[i:j+1],y[i:j+1],z[i:j+1])]) + i = j+1 + +class COIL(): + """Class which defines a coil + + """ + def __init__(self,x,y,z): + self.npts = len(x) + self.x = x + self.y = y + self.z = z + self.dx = x[1:]-x[0:-1] + self.dy = y[1:]-y[0:-1] + self.dz = z[1:]-z[0:-1] + self.vx = self.y[0:-1]*self.dz - self.z[0:-1]*self.dy + self.vy = self.z[0:-1]*self.dx - self.x[0:-1]*self.dz + self.vz = self.x[0:-1]*self.dy - self.y[0:-1]*self.dx + self.xt = None + self.yt = None + self.zt = None + self.dist_surf = None + + def vecpot(self,x,y,z,current): + """Calculates Vector potential + + This routine calculates the vector potential for a given coil + a position in space and a current in said coil. + + Parameters + ---------- + x : real + Cartesian x value [m]. + y : real + Cartesian y value [m]. + z : real + Cartesian z value [m]. + current : real + Current in coil [A] + Returns + ---------- + ax : real + Vector potential in cartesian x direction [A/m] + ay : real + Vector potential in cartesian y direction [A/m] + az : real + Vector potential in cartesian z direction [A/m] + """ + import numpy as np + x1 = x - self.x + y1 = y - self.y + z1 = z - self.z + rw = np.sqrt(x1*x1+y1*y1+z1*z1) + fa = ( rw[1:] + rw[0:-1] ) / \ + ( rw[1:] * rw[0:-1] * \ + ( rw[1:] * rw[0:-1] + x1[1:] * x1[0:-1] + \ + y1[1:] * y1[0:-1] + z1[1:] * z1[0:-1] ) ) + ax = sum( fa * self.dx ) * current + ay = sum( fa * self.dy ) * current + az = sum( fa * self.dz ) * current + return ax, ay, az + + def bfield(self,x,y,z,current): + """Calculates magnetic field + + This routine calculates the magnetic field for a given coil + a position in space and a current in said coil. + + Parameters + ---------- + x : real + Cartesian x value [m]. + y : real + Cartesian y value [m]. + z : real + Cartesian z value [m]. + current : real + Current in coil [A] + Returns + ---------- + bx : real + Magnetic field in cartesian x direction [T] + by : real + Magnetic field in cartesian y direction [T] + bz : real + Magnetic field in cartesian z direction [T] + """ + import numpy as np + fac = 1.0E-7 + x1 = x - self.x + y1 = y - self.y + z1 = z - self.z + rw = np.sqrt(x1*x1+y1*y1+z1*z1) + fa = ( rw[1:] + rw[0:-1] ) / \ + ( rw[1:] * rw[0:-1] * \ + ( rw[1:] * rw[0:-1] + x1[1:] * x1[0:-1] + \ + y1[1:] * y1[0:-1] + z1[1:] * z1[0:-1] ) ) + ax = sum(fa*self.dx)*current + ay = sum(fa*self.dy)*current + az = sum(fa*self.dz)*current + bx = sum( fa * self.vx * current ) - y * az + z * ay + by = sum( fa * self.vy * current ) - z * ax + x * az + bz = sum( fa * self.vz * current ) - x * ay + y * ax + return fac*bx, fac*by, fac*bz + + def geomCenter(self): + """Calculates geometric center of the coil + + This routine calculates the geometric center of the coil. + + Parameters + ---------- + Returns + ---------- + x : real + Center in x coordinate [m] + y : real + Center in y coordinate [m] + z : real + Center in z coordinate [m] + """ + import numpy as np + return np.mean(self.x),np.mean(self.y),np.mean(self.z) + + def surfDist(self,xs,ys,zs): + """Calculates coil-surface distance + + This routine calculates the distance between a coil and a + surface defined by points in cartesian coordiantes (x,y,z). + + Parameters + ---------- + xs : ndarray + X points defining surface [m] + ys : ndarray + Y points defining surface [m] + zs : ndarray + Z points defining surface [m] + """ + import numpy as np + nsurf = len(xs) + xc = np.broadcast_to(self.x,(nsurf,self.npts)).T + yc = np.broadcast_to(self.y,(nsurf,self.npts)).T + zc = np.broadcast_to(self.z,(nsurf,self.npts)).T + x = np.broadcast_to(xs,(self.npts,nsurf)) + y = np.broadcast_to(ys,(self.npts,nsurf)) + z = np.broadcast_to(zs,(self.npts,nsurf)) + dx = xc - x + dy = yc - y + dz = zc - z + dl2 = dx*dx + dy * dy + dz * dz + self.dist_surf = np.sqrt(np.min(dl2,axis=1)) + return + + def spline_tangent(self, order=3, der=1): + """Calculate the tangent of coil using spline interpolation + + This routine calculates the tangent of a coil using spline + interpolation. Order and derivative level can be set by user. + + Parameters + ---------- + order : int (optional) + Order of spline (default: 3) + der : int + Derivative order (default:1) + """ + import numpy as np + from scipy import interpolate + t = np.linspace(0, 2 * np.pi, len(self.x), endpoint=True) + self.dt = 2 * np.pi / (len(self.x) - 1) + fx = interpolate.splrep(t, self.x, s=0, k=order) + fy = interpolate.splrep(t, self.y, s=0, k=order) + fz = interpolate.splrep(t, self.z, s=0, k=order) + self.xt = interpolate.splev(t, fx, der=1) + self.yt = interpolate.splev(t, fy, der=1) + self.zt = interpolate.splev(t, fz, der=1) + if der == 2: + self.xa = interpolate.splev(t, fx, der=2) + self.ya = interpolate.splev(t, fy, der=2) + self.za = interpolate.splev(t, fz, der=2) + return + + def finiteBuildCoil(self, width=0.1, height=0.1, frame="centroid", **kwargs): + """Expand single coil filament to a finite-build coil. + + This routine expands a coil filament of a finite-build coil. + The coil width, height and build frame can be set by the user. + + Parameters + ---------- + width : float (optional) + Toroidal width of the coil [m] (default: 0.1) + height : float (optional) + Radial height of the coil [m] (default: 0.1) + frame : string (optional) + Finite build frame "centroid", "frenet", "parallel" (default:centroid) + + Returns + ---------- + x : ndarry + X-coordiante for plotting as a mesh [m] + y : ndarry + Y-coordiante for plotting as a mesh [m] + z : ndarry + Z-coordiante for plotting as a mesh [m] + """ + import numpy as np + n = self.npts + # calculate the tangent + if self.xt is None: + self.spline_tangent() + xt = self.xt + yt = self.yt + zt = self.zt + tt = np.sqrt(xt * xt + yt * yt + zt * zt) + xt = xt / tt + yt = yt / tt + zt = zt / tt + + # use surface normal if needed + if frame == "centroid": + # use the geometry center is a good idea + [center_x,center_y,center_z]=self.geomCenter() + xn = self.x - center_x + yn = self.y - center_y + zn = self.z - center_z + nt = xn * xt + yn * yt + zn * zt + xn = xn - nt * xt + yn = yn - nt * yt + zn = zn - nt * zt + elif frame == "frenet": + self.spline_tangent(der=2) + xn = self.xa + yn = self.ya + zn = self.za + elif frame == "parallel": + # parallel transport frame + # Hanson & Ma, Parallel Transp ort Approach to Curve Framing, 1995 + def rotate(x, ang): + c = np.cos(ang) + s = np.sin(ang) + return [ + [ + c + x[0] ** 2 * (1 - c), + x[0] * x[1] * (1 - c) - s * x[2], + x[2] * x[0] * (1 - c) + s * x[1], + ], + [ + x[0] * x[1] * (1 - c) + s * x[2], + c + x[1] ** 2 * (1 - c), + x[2] * x[1] * (1 - c) - s * x[0], + ], + [ + x[0] * x[2] * (1 - c) - s * x[1], + x[1] * x[2] * (1 - c) + s * x[0], + c + x[2] ** 2 * (1 - c), + ], + ] + + T = np.transpose([self.xt, self.yt, self.zt]) + T = T / np.linalg.norm(T, axis=1)[:, np.newaxis] + B = np.cross(T[:-1], T[1:], axis=1) + B = B / np.linalg.norm(B, axis=1)[:, np.newaxis] + theta = np.arccos(np.sum(T[:-1] * T[1:], axis=1)) + V = np.zeros_like(T) + kwargs.setdefault("vx", self.x[0] - np.average(self.x[0:-1])) + kwargs.setdefault("vy", self.y[0] - np.average(self.y[0:-1])) + vx = kwargs["vx"] + vy = kwargs["vy"] + vz = -(vx * T[0, 0] + vy * T[0, 1]) / T[0, 2] + vv = np.linalg.norm([vx, vy, vz]) + V[0, :] = [vx / vv, vy / vv, vz / vv] + print(np.dot(V[0, :], T[0, :])) + for i in range(len(theta)): + V[i + 1, :] = rotate(B[i, :], theta[i]) @ V[i, :] + xn = V[:, 0] + yn = V[:, 1] + zn = V[:, 2] + else: + assert True, "not finished" + + nn = np.sqrt(xn * xn + yn * yn + zn * zn) + xn = xn / nn + yn = yn / nn + zn = zn / nn + # calculate the bi-normal + xb = yt * zn - yn * zt + yb = zt * xn - zn * xt + zb = xt * yn - xn * yt + bb = np.sqrt(xb * xb + yb * yb + zb * zb) + xb = xb / bb + yb = yb / bb + zb = zb / bb + # get the boundary lines + z1 = self.z - width / 2 * zb + height / 2 * zn + x1 = self.x - width / 2 * xb + height / 2 * xn + x2 = self.x + width / 2 * xb + height / 2 * xn + y2 = self.y + width / 2 * yb + height / 2 * yn + z2 = self.z + width / 2 * zb + height / 2 * zn + x3 = self.x + width / 2 * xb - height / 2 * xn + y3 = self.y + width / 2 * yb - height / 2 * yn + z3 = self.z + width / 2 * zb - height / 2 * zn + x4 = self.x - width / 2 * xb - height / 2 * xn + y4 = self.y - width / 2 * yb - height / 2 * yn + z4 = self.z - width / 2 * zb - height / 2 * zn + y1 = self.y - width / 2 * yb + height / 2 * yn + # assemble + xx = np.array([x1, x2, x3, x4, x1]) + yy = np.array([y1, y2, y3, y4, y1]) + zz = np.array([z1, z2, z3, z4, z1]) + return xx, yy, zz + +if __name__=="__main__": + import sys + from argparse import ArgumentParser + parser = ArgumentParser(description= + '''Provides class for accessing coils files also servers as a + simple tool for assessing coils or coils files.''') + parser.add_argument("-c", "--coil", dest="coils_file", + help="Coils file for input", default = None) + parser.add_argument("-p", "--plot", dest="lplot", action='store_true', + help="Plot the coils file.", default = False) + parser.add_argument("-prz", "--plotRZ", dest="lplotRZ", action='store_true', + help="Plot each coil group in RZ.", default = False) + parser.add_argument("-b", "--bfield", dest="bxyz", + help="Output B field at x,y,z", default = None) + parser.add_argument("-a", "--afield", dest="axyz", + help="Output A field at x,y,z", default = None) + parser.add_argument("-o", "--output", dest="loutput", action='store_true', + help="Output the coil", default = False) + args = parser.parse_args() + coils = COILSET() + if args.coils_file: + coils.read_coils_file(args.coils_file) + if args.lplot: coils.plotcoils() + if args.lplotRZ: coils.plotcoilsRZ() + if args.loutput: coils.write_coils_file(args.coils_file+'_new') + if args.axyz: + x,y,z = args.axyz.split(',') + ax,ay,az = coils.coilvecpot(float(x),float(y),float(z)) + print(f"Vector Potential ({x},{y},{z}) : {ax}, {ay}, {az} ") + if args.bxyz: + x,y,z = args.bxyz.split(',') + bx,by,bz = coils.coilbiot(float(x),float(y),float(z)) + print(f"B-Field ({x},{y},{z}) : {bx}, {by}, {bz} [T]") + sys.exit(0) + diff --git a/pySTEL/libstell/collisions.py b/pySTEL/libstell/collisions.py new file mode 100644 index 000000000..e75802e89 --- /dev/null +++ b/pySTEL/libstell/collisions.py @@ -0,0 +1,260 @@ +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for calculating +quantities related to collisions +""" + +# Libraries +#from libstell import libstell + +# Constants +EC = 1.602176634E-19 # Electron charge [C] +HBAR = 1.054571817E-34 # Planks reduced constant [J.s] +DA = 1.66053906660E-27 # Dalton +ME = 9.1093837E-31 # Electron mass [kg] +C = 299792458 # Speed of light [m/s] + +# VMEC Class +class COLLISIONS(): + """Class for working with FUSION data + + """ + def __init__(self): + # Electron Mass + self.ME = ME + # Proton Mass + self.MP = 1.007276466621*DA + # Deuturium Mass + self.MD = 2.01410177811*DA + # Tritium Mass + self.MT = 3.01604928*DA + # Helium Mass + self.MHe3 = 3.0160293*DA + self.MHe4 = 4.002603254*DA + + def coullog_ee(self,ne,te): + """Computes the Coulomb e-e logarithm + + This routine calculates the Coulomb Logarithm acording to the + NRL plasma formulary general deffinition. + + Parameters + ---------- + ne : real + Electron density [m^-3] + te : real + Electron Temperature [eV] + Returns + ---------- + clog : real + Coulomb logarithm + """ + import numpy as np + ne_cm = ne*1E-6 + a1 = -np.log(np.sqrt(ne_cm)*te**(-1.25)) + a2 = -np.sqrt(1E-5 + ((np.log(te)-2)**2)/16.0) + return 23.5 + a1 + a2 + + def coullog_ei(self,ne,te,mi,Z,ni,ti): + """Computes the Coulomb e-i logarithm + + This routine calculates the Coulomb Logarithm acording to the + NRL plasma formulary general deffinition. + + Parameters + ---------- + ne : real + Electron density [m^-3] + te : real + Electron Temperature [eV] + mi : real + Ion mass [kg] + Z : real + Ion Charge number + ni : real + Ion density [m^-3] + ti : real + Ion Temperature [eV] + Returns + ---------- + clog : real + Coulomb logarithm + """ + import numpy as np + ne_cm = ne*1E-6 + mu = mi/self.MP + # No need to convert masses from kg to g + if ti/mi < (te/self.ME): + if (te < (10 * Z * Z)): + clog = 23 - np.log(np.sqrt(ne_cm)*Z*te**(-1.5)) + else: + clog = 24 - np.log(np.sqrt(ne_cm)/te) + else: + mu = (self.ME*mi)/(self.ME+mi) + clog = 16 - np.log(mu*Z*Z*np.sqrt(ni)*ti**-1.5) + return clog + + def coullog_ii(self,mi1,Z1,ni1,ti1,mi2,Z2,ni2,ti2): + """Computes the Coulomb i-i logarithm + + This routine calculates the Coulomb Logarithm acording to the + NRL plasma formulary general deffinition. + + Parameters + ---------- + mi1 : real + Ion #1 mass [kg] + Z1 : real + Ion #1 Charge number + ni1 : real + Ion #1 density [m^-3] + ti1 : real + Ion #1 Temperature [eV] + mi2 : real + Ion #2 mass [kg] + Z2 : real + Ion #2 Charge number + ni2 : real + Ion #2 density [m^-3] + ti2 : real + Ion #2 Temperature [eV] + Returns + ---------- + clog : real + Coulomb logarithm + """ + import numpy as np + ni1_cm = ni1*1E-6 + ni2_cm = ni2*1E-6 + mu1 = mi1/self.MP + mu2 = mi2/self.MP + # No need to convert masses from kg to g + clog = (ni1_cm*Zi1*Zi1/ti1) + (ni2_cm*Zi2*Zi2/ti2) + clog = Zi1*Zi2*(mu1+mu2)*np.sqrt(clog)/(mu1*ti2+mu2*ti1) + clog = 23 - np.log(clog) + return clog + + def coullog_iifast(self,ne,te,mi1,Z1,mi2,Z2,vd): + """Computes the Coulomb counterstreaming i-i logarithm + + This routine calculates the Coulomb Logarithm acording to the + NRL plasma formulary general deffinition. + + Parameters + ---------- + ne : real + Electron density [m^-3] + te : real + Electron Temperature [eV] + mi1 : real + Ion #1 mass [kg] + Z1 : real + Ion #1 Charge number + mi2 : real + Ion #2 mass [kg] + Z2 : real + Ion #2 Charge number + vd : real + Ion relative velocity [m/s] + Returns + ---------- + clog : real + Coulomb logarithm + """ + import numpy as np + ne_cm = ne*1E-6 + mu1 = mi1/self.MP + mu2 = mi2/self.MP + # No need to convert masses from kg to g + beta = vd/C + clog = ne_cm/te + clog = Z1*Z2*(mu1+mu2) * np.sqrt(clog) / (mu1*mu2*beta*beta) + clog = 43-np.log(clog) + return clog + + def collisionfreq(self,m1,Z1,T1,m2,Z2,n2,T2,clog): + """Computes the collision frequency for two species + + This routine calculates the collision frequency acording to the + NRL plasma formulary general deffinition. + + Parameters + ---------- + m1 : real + Particle #1 mass [kg] + Z1 : real + Particle #1 Charge number + T1 : real + Particle #1 Temperature [eV] + m2 : real + Particle #2 mass [kg] + Z2 : real + Particle #2 Charge number + n2 : real + Particle #2 Density [m^-3] + T2 : real + Particle #2 Temperature [eV] + clog : real + Coulomb logarithm + Returns + ---------- + freq : real + Collision frequency + """ + import numpy as np + n2_cm = n2*1E-6 + # factor of 1000 comes from sqrt(mass in kg to g) + freq = 1.8E-19*np.sqrt(m1*m2)*Z1*Z1*Z2*Z2*n2_cm*clog*1000 + freq = freq / (m1*T2+m2*T1)**1.5 + return freq + + def tauspitzer(self,mi,Zi,ne,Te,clog): + """Computes the Spitzer ion-electron exchange time + + This routine calculates the Spitzer ion-electron momentum + exchange time. + + Parameters + ---------- + mi : real + Ion Mass [kg] + Zi : real + Ion Charge number + ne : real + Electron Density [m^-3] + Te : real + Electron Temperature [eV] + clog : real + Coulomb logarithm + Returns + ---------- + tau : real + Spitzer ion-electron momentum exchange time + """ + import numpy as np + return 3.777183E41*mi*np.sqrt(Te*Te*Te)/(ne*Zi*Zi*clog) + + def criticalvelocity(self,mp,Te): + """Computes the critical velocity + + This routine calculates the critical velocity for an energetic + particle. + + Parameters + ---------- + mi : real + Plasma Ion Mass [kg] + Te : real + Electron Temperature [eV] + Returns + ---------- + vcrit : real + Critical velocity [m/s] + """ + import numpy as np + return (0.75*np.sqrt(np.pi*mp/self.ME))**(1.0/3.0) * np.sqrt(2*EC*Te/mp) + +if __name__=="__main__": + import sys + sys.exit(0) diff --git a/pySTEL/libstell/diagno.py b/pySTEL/libstell/diagno.py new file mode 100644 index 000000000..d3a752e08 --- /dev/null +++ b/pySTEL/libstell/diagno.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for reading and handling +DIAGNO synthetic magnetic diagnostic data. +""" + +# Libraries +from libstell.libstell import LIBSTELL + +# Constants + +# DIAGNO Class +class DIAGNO(): + """Class for working with DIAGNO data + + """ + def __init__(self): + test = 0 + + def read_fluxloops(self,filename,scale_factor=1.0): + """Reads a DIAGNO fluxloop definition file. + + This routine reads the diagno fluxloop deffinition file. + + Parameters + ---------- + filename : str + Path to diagno_fluxloops file. + scale_factor : float + Scale factor to apply to data (default = 1.0) + + Returns + ------- + floops : dict + Dictionary of fluxloop names and array of x,y,z data. + """ + import numpy as np + f = open(filename,'r') + line = f.readline() + nloops = int(line) + floops = {} + for i in range(nloops): + line = f.readline() + [txt1,txt2,txt3,txt4] = line.split() + nels = int(txt1) + name = txt4 + xyz = np.ndarray((3,nels)) + for j in range(loops): + xyz[:,j]=[float(x) for x in line.split()] + floops[name] = xyz + f.close() + return floops + + def read_diagno_flux(self,filename): + """Reads a DIAGNO fluxloop data file. + + This routine reads the diagno fluxloop response data. + + Parameters + ---------- + filename : str + Path to diagno_flux file. + + Returns + ------- + names : list + List of flux loop names + flux : ndarray + Flux [Wb] + """ + import numpy as np + f = open(filename,'r') + line = f.readline() + nels = int(line) + line = f.readline() + flux = [float(x) for x in line.split()] + for line in f: + names = names.append(line) + f.close() + return names,np.array(flux) + + + +# BEASM3D Input Class +class DIAGNO_IN(): + """Class for working with DIAGNO_IN data + + """ + def __init__(self, parent=None): + self.libStell = LIBSTELL() + + def read_input(self,filename): + """Reads DIAGNO_IN namelist from a file + + This routine wrappers the diagno_input_mod module reading routine. + Parameters + ---------- + filename : string + Input file name with DIAGNO_IN namelist + """ + diagno_in_dict = self.libStell.read_diagno_in(filename) + for key in diagno_in_dict: + setattr(self, key, diagno_in_dict[key]) + + def write_input(self,filename): + """Writes DIAGNO_IN namelist to a file + + This routine wrappers the diagno_input_mod module writing routine. + Parameters + ---------- + filename : string + Input file name to write DIAGNO_IN namelist to + """ + out_dict = vars(self) + self.libStell.write_diagno_in(filename,out_dict) + +# Main routine +if __name__=="__main__": + import sys + sys.exit(0) \ No newline at end of file diff --git a/pySTEL/libstell/fieldlines.py b/pySTEL/libstell/fieldlines.py index cafad6e49..2c25f9854 100644 --- a/pySTEL/libstell/fieldlines.py +++ b/pySTEL/libstell/fieldlines.py @@ -1,75 +1,208 @@ -def read_fieldlines(file): - import h5py - import numpy as np - fieldline_data = {} - #read file - with h5py.File(file,'r') as f: - # Logicals - for temp in ['ladvanced', 'laxis_i', 'lcoil', 'lmgrid', 'lmu', 'lpies', 'lreverse', 'lspec', 'lvac', 'lvessel', 'lvmec']: - if temp in f: - fieldline_data[temp] = np.int64(f[temp][0]) - # Integers - for temp in ['nlines', 'nphi', 'npoinc', 'nr', 'nsteps', 'nz']: - if temp in f: - fieldline_data[temp] = np.int64(f[temp][0]) - # Floats - for temp in ['VERSION','iota0']: - if temp in f: - fieldline_data[temp] = np.float(f[temp][0]) - # Arrays - for temp in ['phiaxis', 'raxis', 'zaxis', 'B_lines', 'PHI_lines', 'R_lines', 'Z_lines', 'B_PHI', 'B_R', 'B_Z',\ - 'wall_vertex', 'wall_faces', 'wall_strikes', 'A_R', 'A_PHI', 'A_Z', 'L_lines', 'Rhc_lines', 'Zhc_lines']: - if temp in f: - fieldline_data[temp] = np.array(f[temp][:]) - # Make derived arrays - fieldline_data['X_lines'] = fieldline_data['R_lines']*np.cos(fieldline_data['PHI_lines']) - fieldline_data['Y_lines'] = fieldline_data['R_lines']*np.sin(fieldline_data['PHI_lines']) - brtemp = np.zeros(fieldline_data['B_R'].shape) - bztemp = np.zeros(fieldline_data['B_Z'].shape) - for i in range(fieldline_data['nr']): - brtemp[i,:,:] = fieldline_data['B_R'][i,:,:]*fieldline_data['B_PHI'][i,:,:]/fieldline_data['raxis'][i] - bztemp[i,:,:] = fieldline_data['B_Z'][i,:,:]*fieldline_data['B_PHI'][i,:,:]/fieldline_data['raxis'][i] - fieldline_data['B_R'] = brtemp - fieldline_data['B_Z'] = bztemp - return fieldline_data - -def calc_reff(data): - import numpy as np - x = np.zeros(data['R_lines'].shape) - y = np.zeros(data['Z_lines'].shape) - nstep = data['nsteps'] - for i in range(data['nsteps']): - x[i,:] = data['R_lines'][i,:]-data['R_lines'][i,0] - y[i,:] = data['Z_lines'][i,:]-data['Z_lines'][i,0] - theta = np.arctan2(y,x) - dtheta = np.diff(theta,axis=0) - dtheta = np.where(dtheta<-np.pi,dtheta+2*np.pi,dtheta) - dtheta = np.where(dtheta>np.pi,dtheta-2*np.pi,dtheta) - theta = np.cumsum(dtheta,axis=0) - out = {} - out = np.mean(np.sqrt(x*x+y*y),axis=0) - return out - -def calc_iota(data): - import numpy as np - x = np.zeros(data['R_lines'].shape) - y = np.zeros(data['Z_lines'].shape) - nstep = data['nsteps'] - for i in range(data['nsteps']): - x[i,:] = data['R_lines'][i,:]-data['R_lines'][i,0] - y[i,:] = data['Z_lines'][i,:]-data['Z_lines'][i,0] - theta = np.arctan2(y,x) - dtheta = np.diff(theta,axis=0) - dtheta = np.where(dtheta<-np.pi,dtheta+2*np.pi,dtheta) - dtheta = np.where(dtheta>np.pi,dtheta-2*np.pi,dtheta) - theta = np.cumsum(dtheta,axis=0) - out = {} - out['rho'] = np.mean(np.sqrt(x*x+y*y),axis=0) - out['iota'] = np.zeros(out['rho'].shape) - out['iota_err'] = np.zeros(out['rho'].shape) - for i in range(data['nlines']): - p, residuals, rank, singular_values, rcond = np.polyfit(data['PHI_lines'][0:nstep-1,i],theta[:,i],1,full=True) - out['iota'][i]=p[0] - out['iota_err'][i] = np.sqrt(residuals) - out['iota'][0]=2*out['iota'][1]-out['iota'][2] - return out +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for reading and handling +FIELDLINES fieldline data data. +""" + +# Libraries +from libstell.libstell import LIBSTELL + +# Constants + +# FIELDLINES Class +class FIELDLINES(): + """Class for working with FIELDLINES data + + """ + def __init__(self): + test = 0 + + def read_fieldlines(self,filename): + """Reads a FIELDLINES HDF5 file + + This routine reads and initilizes the FIELDLINES + class with variable information from an HDF5 file. + + Parameters + ---------- + file : str + Path to HDF5 file. + """ + import h5py + import numpy as np + fieldline_data = {} + #read file + with h5py.File(filename,'r') as f: + # Logicals + for temp in ['ladvanced', 'laxis_i', 'lcoil', 'lmgrid', \ + 'lmu', 'lpies', 'lreverse', 'lspec', 'lvac', 'lvessel',\ + 'lvmec']: + if temp in f: + setattr(self, temp, np.int64(f[temp][0])==1) + # Integers + for temp in ['nlines', 'nphi', 'npoinc', 'nr', 'nsteps', 'nz']: + if temp in f: + setattr(self, temp, np.int64(f[temp][0])) + # Floats + for temp in ['VERSION','iota0']: + if temp in f: + setattr(self, temp, float(f[temp][0])) + # Arrays + for temp in ['phiaxis', 'raxis', 'zaxis', 'B_lines', \ + 'PHI_lines', 'R_lines', 'Z_lines', 'B_PHI', 'B_R', \ + 'B_Z','wall_vertex', 'wall_faces', 'wall_strikes', \ + 'A_R', 'A_PHI', 'A_Z', 'L_lines', 'Rhc_lines', \ + 'Zhc_lines']: + if temp in f: + setattr(self, temp, np.array(f[temp][:])) + # Make derived arrays + self.X_lines = self.R_lines*np.cos(self.PHI_lines) + self.Y_lines = self.R_lines*np.sin(self.PHI_lines) + # Fix B_R and B_Z + for i in range(self.nr): + self.B_R[i,:,:] = self.B_R[i,:,:]*self.B_PHI[i,:,:]/self.raxis[i] + self.B_Z[i,:,:] = self.B_Z[i,:,:]*self.B_PHI[i,:,:]/self.raxis[i] + + def calc_reff(self): + """Calculates the effective radius + + Using the first traced fieldline the routine calculates + the effective minor radius [m]. + + Returns + ---------- + reff : ndarray + Effective minor radius [m]. + """ + import numpy as np + x = self.R_lines + y = self.Z_lines + for i in range(self.nsteps): + x[i,:] = x[i,:] - x[i,0] + y[i,:] = y[i,:] - y[i,0] + theta = np.arctan2(y,x) + theta = np.arctan2(y,x) + dtheta = np.diff(theta,axis=0) + dtheta = np.where(dtheta<-np.pi,dtheta+2*np.pi,dtheta) + dtheta = np.where(dtheta>np.pi,dtheta-2*np.pi,dtheta) + theta = np.cumsum(dtheta,axis=0) + reff = np.mean(np.sqrt(x*x+y*y),axis=0) + return reff + + def calc_iota(self): + """Calculates the rotational transform + + Using the first traced fieldline the routine calculates + the effective minor radius [m], rotational transform, + and error in rotational transform. + + Returns + ---------- + reff : ndarray + Effective minor radius [m] + iota : ndarray + Rotational transform + iota_err : ndarray + Error in rotational transform + """ + import numpy as np + x = self.R_lines + y = self.Z_lines + for i in range(self.nsteps): + x[i,:] = x[i,:] - x[i,0] + y[i,:] = y[i,:] - y[i,0] + theta = np.arctan2(y,x) + dtheta = np.diff(theta,axis=0) + dtheta = np.where(dtheta<-np.pi,dtheta+2*np.pi,dtheta) + dtheta = np.where(dtheta>np.pi,dtheta-2*np.pi,dtheta) + theta = np.cumsum(dtheta,axis=0) + reff = np.mean(np.sqrt(x*x+y*y),axis=0) + iota = np.zeros((self.nlines)) + iota_err = np.zeros((self.nlines)) + for i in range(self.nlines): + p, residuals, rank, singular_values, rcond = np.polyfit(self.PHI_lines[0:self.nsteps-1,i],theta[:,i],1,full=True) + iota[i] = p[0] + iota_err[i] = np.sqrt(residuals) + iota[0] = 2.0 * iota[1] - iota[2] + return reff, iota, iota_err + + def plot_poincare(self,phi,nskip=1,ax=None,color_data=None): + """Creates a basic Poincare plot + + Plots a Poincare plot given a toroidal angle in radians (phi). + A number of fieldlines to skip can also be provided (nskip). + The user may also provide an axes (ax) to plot to. + + Returns + ---------- + phi : float + Toroidal angle to plot. [radians] + nskip : int (optional) + Number of fieldlines to skip. + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + lcdata = False + if not ax: + ax = pyplot.axes() + lplotnow = True + if color_data is not None: + lcdata = True + k = int(self.npoinc*phi/self.phiaxis[-1]) + rmin = np.amin(self.raxis) + rmax = np.amax(self.raxis) + x = self.R_lines[k:self.nsteps-1:self.npoinc,0:self.nlines:nskip] + y = self.Z_lines[k:self.nsteps-1:self.npoinc,0:self.nlines:nskip] + if lcdata: + c = color_data[k:self.nsteps-1:self.npoinc,0:self.nlines:nskip] + ax.scatter(x,y,s=0.1,c=c,marker='.') + else: + ax.plot(x,y,'.k',markersize=0.1) + ax.set_xlabel('R [m]') + ax.set_ylabel('Z [m]') + ax.set_title(rf'FIELDLINES $\phi$ = {np.rad2deg(phi):3.1f}') + ax.set_aspect('equal') + ax.set_xlim(rmin,rmax) + if lplotnow: pyplot.show() + +# FIELDLINES Input Class +class FIELDLINES_INPUT(): + """Class for working with FIELDLINES INPUT data + + """ + def __init__(self, parent=None): + self.libStell = LIBSTELL() + + def read_input(self,filename): + """Reads FIELDLINES_INPUT namelist from a file + + This routine wrappers the fieldlines_input_mod module reading routine. + Parameters + ---------- + filename : string + Input file name with FIELDLINES_INPUT namelist + """ + indata_dict = self.libStell.read_fieldlines_input(filename) + for key in indata_dict: + setattr(self, key, indata_dict[key]) + + def write_input(self,filename): + """Writes FIELDLINES_INPUT namelist to a file + + This routine wrappers the fieldlines_input_mod module writing routine. + Parameters + ---------- + filename : string + Input file name to write FIELDLINES_INPUT namelist to + """ + out_dict = vars(self) + self.libStell.write_fieldlines_input(filename,out_dict) + +# Main routine +if __name__=="__main__": + import sys + sys.exit(0) diff --git a/pySTEL/libstell/focus.py b/pySTEL/libstell/focus.py new file mode 100644 index 000000000..9d6b74326 --- /dev/null +++ b/pySTEL/libstell/focus.py @@ -0,0 +1,292 @@ +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for reading and handling FOCUS +data. +""" + +# Libraries +#from libstell.libstell import LIBSTELL, FourierRep + +# Constants + +# VMEC Class +class FOCUS(): + """Class for working with VMEC equilibria + + """ + def __init__(self): + return + + def read_focus_HDF5(self,filename): + """Reads a FOCUS HDF5 file + + This routine reads and initilizes the FIELDLINES + class with variable information from an HDF5 file. + + Parameters + ---------- + file : str + Path to HDF5 file. + """ + import h5py + import numpy as np + focus_data = {} + if '.h5' not in filename: + filename = filename + '.h5' + if 'focus_' not in filename: + filename = 'focus_' + filename + with h5py.File(filename,'r') as f: + # Integers + for temp in ['IsQuiet','IsSymmetric','case_surface',\ + 'knotsurf','Nteta','Nzeta','case_init','case_coils',\ + 'Ncoils','IsVaryCurrent','IsVaryGeometry','NFcoil',\ + 'Nseg','case_optimize','IsNormalize','ISNormWeight',\ + 'case_bnormal','case_length','case_curv','curv_alpha',\ + 'DF_maxiter','CG_maxiter','HN_maxiter','TN_maxiter',\ + 'TN_reorder','case_postproc','save_freq','save_coils',\ + 'save_harmonics','save_filaments','update_plasma',\ + 'pp_ns','pp_maxiter','Nfp','iout','ibnorm','mbnorm',\ + 'ibharm','mbharm','itflux','mtflux','ittlen','mttlen',\ + 'icssep','mcssep','icurv','mcurv']: + if temp in f: + setattr(self, temp, np.int64(f[temp][0])) + # Reals + for temp in ['knotsurf','init_current','init_radius',\ + 'exit_xtol','weight_bnorm','weight_bharm','weight_tflux',\ + 'target_tflux','weight_ttlen','target_length','k0',\ + 'weight_specw','weight_cssep','weight_gnorm','weight_inorm',\ + 'weight_mnorm','weight_curv','DF_tausta','DF_tauend','DF_xtol',\ + 'CG_xtol','CG_wolfe_c1','CG_wolfe_c2','HN_xtol','HN_factor',\ + 'TN_xtol','TN_cr','pp_phi','pp_raxis','pp_zaxis','pp_rmax',\ + 'pp_zmax','pp_xtol','surf_vol','Inorm','Gnorm','Mnorm',\ + 'overlap','time_initialize','time_optimize','time_postproc']: + if temp in f: + setattr(self, temp, float(f[temp][0])) + # Arrays + for temp in ['xsurf','ysurf','zsurf','nx','ny','nz','nn',\ + 'plas_Bn','Bn','Bx','By','Bz','evolution','coilspace',\ + 'deriv','Bmnin','Bmnim','initial_Bmnc','initial_Bmns',\ + 'target_Bmnc','target_Bmns','Bmnc','Bmns','coil_importance',\ + 'LM_fvec','LM_fjac','ppr','ppz','iota','XYZB','booz_mnc',\ + 'booz_mns','bmim','bmin']: + if temp in f: + setattr(self, temp, np.array(f[temp][:])) + + def write_focus_plasma(self,nfp,xm,xn,rmnc,zmns,rmns=None,zmnc=None,xm_b=None,\ + xn_b=None,bmnc=None,bmns=None,filename='plasma.boundary'): + """Writes a focus boundary file + + This routine writes the FOCUS plasma boundary file. + + Parameters + ---------- + nfp : int + Field periodicity + xm : ndarray + Poloidal mode array + xn : ndarray + Toroidal mode array + rmnc : ndarray + R cosine boundary harmonics + zmns : ndarray + Z sine boundary harmonics + rmns : ndarray (optional) + R sine boundary harmonics + zmnc : ndarray (optional) + Z cosine boundary harmonics + xm_b : ndarray (optional) + Poloidal mode array (B-normal) + xn_b : ndarray (optional) + Toroidal mode array (B-normal) + bmnc : ndarray (optional) + B-normal cosine boundary harmonics + bmns : ndarray (optional) + B-normal sine boundary harmonics + filename : string (optional) + Boundary file name (default: plasma.boundary) + """ + mnmax = len(xm) + mnmax_b = 1 + if (xm_b and xn_b and (bmnc)): + mnmax_b = len(xm_b) + else: + xm_b = [0] + xn_b = [0] + bmnc = [0] + bmns = [0] + if not (rmns and zmnc): + rmns = np.zeros((mnmax)) + zmnc = np.zeros((mnmax)) + f=open(filename,'w') + f.write(f'#Nfou Nfp NBnf\n') + f.write(f'{int(mnmax)} {int(nfp)} {int(mnmax_b)}\n') + f.write(f'#plasma boundary\n') + f.write(f'# n m Rbc Rbs Zbc Zbs\n') + for mn in range(mnmax): + f.write(f'{int(xn[mn])} {int(xm[mn])} {rmnc[mn]:10.9f} {rmns[mn]:10.9f} {zmnc[mn]:10.9f} {zmns[mn]:10.9f}\n') + f.write(f'#Bn harmonics\n') + f.write(f'# n m bnc bns\n') + for mn in range(mnmax_b): + f.write(f'{int(xm_b[mn])} {int(xn_b[mn])} {bmnc[mn]:10.9f} {bmns[mn]:10.9f}\n') + f.close() + + def plotConvergence(self,ax=None): + """Plots the FOCUS Convergence + + This routine plots the FOCUS code convergence for a given + run. + + Parameters + ---------- + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes() + lplotnow = True + ax.semilogy(self.evolution[0],self.evolution[1],label=r'$\chi^2$') + ax.semilogy(self.evolution[0],self.evolution[2],label=r"$|d \chi^2 / d {\bf X}|$") + ax.semilogy(self.evolution[0],self.evolution[3],label=r"$f_{B_n}$") + ax.semilogy(self.evolution[0],self.evolution[4],label=r"$f_{B_{mn}}$") + ax.semilogy(self.evolution[0],self.evolution[5],label=r"$f_{\Psi}$") + ax.semilogy(self.evolution[0],self.evolution[6],label=r"$f_L$") + ax.semilogy(self.evolution[0],self.evolution[7],label=r"$f_{COIL-SURF}$") + ax.semilogy(self.evolution[0],self.evolution[8],label=r"$f_{curv}$") + ax.set_xlabel('Time [s]') + ax.set_ylabel('Cost Function') + ax.set_title('FOCUS Convergence') + ax.legend() + if lplotnow: pyplot.show() + + def plotBNormal(self,ax=None): + """Plots the FOCUS B-normal + + This routine plots the FOCUS code B-normal + + Parameters + ---------- + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes() + lplotnow = True + if self.IsSymmetric == 0: + x = np.linspace(0,2*np.pi,int(self.Nzeta)) + elif self.IsSymmetric == 1: + x = np.linspace(0,2*np.pi/self.Nfp,int(self.Nzeta)) + elif self.IsSymmetric == 2: + x = np.linspace(0,np.pi/self.Nfp,int(self.Nzeta)) + else: + return + y = np.linspace(0,2.*np.pi,int(self.Nteta)) + hmesh=ax.pcolormesh(x,y,self.Bn.T,cmap='jet',shading='gouraud') + #ax.semilogy(abscissa, data, **kwargs) + ax.set_xlabel('Toroidal angle [rad]') + ax.set_ylabel('Poloidal angle [rad]') + ax.set_title('FOCUS B-Normal') + pyplot.colorbar(hmesh,label='$B_n$ [T]',ax=ax) + if lplotnow: pyplot.show() + + def plotBN3D(self,ax=None): + """Plots the FOCUS B-normal in 3D + + This routine plots the FOCUS code B-normal in 3D + + Parameters + ---------- + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + import matplotlib.tri as mtri + lplotnow = False + if not ax: + ax = pyplot.axes() + lplotnow = True + vertex = np.zeros((self.Nzeta*self.Nteta,3)) + ivertex = 0 + for v in range(self.Nzeta): + for u in range(self.Nteta): + vertex[ivertex,0]=self.xsurf[u,v] + vertex[ivertex,1]=self.ysurf[u,v] + vertex[ivertex,2]=self.zsurf[u,v] + ivertex = ivertex + 1 + u = np.linspace(0, 1, endpoint=True, num=self.Nteta) + v = np.linspace(0, 1, endpoint=True, num=self.Nteta) + u, v = np.meshgrid(u, v) + u, v = u.flatten(), v.flatten() + tri = mtri.Triangulation(u, v) + vals = self.Bn.T.flatten() + colors = np.mean(vals[tri.triangles], axis=1) + tsurf=ax.plot_trisurf(vertex[:,0],vertex[:,1],vertex[:,2], triangles=tri.triangles,cmap='jet',shade=True, alpha=1.0) + tsurf.set_array(colors) + tsurf.autoscale() + pyplot.colorbar(tsurf,label='$B_n$ [T]',ax=ax) + if lplotnow: pyplot.show() + + def plotPoincare(self,ax=None): + """Plots the FOCUS Poincare Plot + + This routine plots the FOCUS Poincare plots + + Parameters + ---------- + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes() + lplotnow = True + ax.plot(self.ppr,self.ppz,'.',markersize=1) + rsurf = np.sqrt(self.xsurf**2+self.ysurf**2) + rmin = min(rsurf[0,:]) + rmax = max(rsurf[0,:]) + zmin = min(self.zsurf[0,:]) + zmax = max(self.zsurf[0,:]) + ax.plot(rsurf[0,:],self.zsurf[0,:],'k') + ax.set_xlabel('R [m]') + ax.set_ylabel('Z [m]') + ax.set_aspect('equal') + ax.set_xlim(rmin*0.9,rmax*1.1) + ax.set_ylim(zmin*1.1,zmax*1.1) + if lplotnow: pyplot.show() + + def plotIota(self,ax=None): + """Plots the FOCUS Iota + + This routine plots the FOCUS rotational transform + + Parameters + ---------- + ax : axes (optional) + Matplotlib axes object to plot to. + """ + import numpy as np + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes() + lplotnow = True + ax.plot(self.ppr[0]-self.ppr[0,1],self.iota) + ax.set_xlabel('r [m]') + ax.set_ylabel(r'$\iota$') + ax.set_ylabel('Rotational Transform') + if lplotnow: pyplot.show() + +# Main routine +if __name__=="__main__": + import sys + sys.exit(0) + diff --git a/pySTEL/libstell/fusion.py b/pySTEL/libstell/fusion.py new file mode 100644 index 000000000..c8990517f --- /dev/null +++ b/pySTEL/libstell/fusion.py @@ -0,0 +1,86 @@ +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for calculating +quantities related to nuclear fusion +""" + +# Libraries +#from libstell import libstell + +# Constants +EC = 1.602176634E-19 # Electron charge + +# VMEC Class +class FUSION(): + """Class for working with FUSION data + + """ + def __init__(self): + self.C_DICT = { "DT" : [ 1.17302E-09, 1.51361E-02, 7.51886E-02, \ + 4.60643E-03, 1.35000E-02, -1.06750E-04, \ + 1.36600E-05] , \ + "DDT" : [ 5.65718E-12, 3.41267E-03, 1.99167E-03, \ + 0.00000E+00, 1.05060E-05, 0.00000E+00, \ + 0.00000E+00] , \ + "DDHe3" : [ 5.43360E-12, 5.85778E-03, 7.68222E-03, \ + 0.00000E+00, -2.96400E-06, 0.00000E+00, \ + 0.00000E+00] , \ + "DHe3" : [ 5.51036E-10, 6.41918E-03, -2.02896E-03, \ + -1.91080E-05, 1.35776E-04, 0.00000E+00, \ + 0.00000E+00] } + self.MRC2_DICT = { "DT" : 1124656, \ + "DDT" : 937814 ,\ + "DDHe3" : 937814 ,\ + "DHe3" : 1124572 } + self.BG_DICT = { "DT" : 34.3827, \ + "DDT" : 31.3970 ,\ + "DDHe3" : 31.3970 ,\ + "DHe3" : 68.7508 } + self.E_DT_He = 3.52E6*EC + self.E_DD_T = 1.01E6*EC + self.E_DD_p = 3.02E6*EC + self.E_DD_He3 = 0.82E6*EC + self.E_DHe3_He4 = 3.60E6*EC + self.E_DHe3_p = 1.47E7*EC + + def sigmaBH(self, ti, reaction='DT'): + """Computs the Bosch Hale Fusion cross sections + + This routine calculates the fusion cross sections given + density and temperature using the Bosch Hale model. + H.-S. Bosch and G. M. Hale 1992 Nucl. Fusion 32 611 + https://doi.org/10.1088/0029-5515/32/4/I07 + + Parameters + ---------- + ti : real + Ion Temperature in [eV] + reaction : string + Reaction type 'DT','DDT','DDHe3','DHe3' + Returns + ---------- + sigma : real + Reaction rate [m^3/s] + """ + import math + C = self.C_DICT[reaction] + BG = self.BG_DICT[reaction] + MRC2 = self.MRC2_DICT[reaction] + ti_kev = ti * 1E-3 + zeta = ( ( ( C[5] * ti_kev ) + C[3] ) * ti_kev + C[1] ) * ti_kev + zeta = zeta / ( ( ( ( C[6] * ti_kev ) + C[4] ) * ti_kev + C[2] ) * ti_kev + 1.0 ) + zeta = 1.0 - zeta + theta = ti_kev / zeta + eta = ( 0.25 * BG * BG / theta ) ** (1.0/3.0) + return 1.0E-6 * C[0] * theta * math.sqrt( eta / ( MRC2 * ti_kev * ti_kev * ti_kev ) ) * math.exp( -3 * eta ) + + +if __name__=="__main__": + import sys + temp = FUSION() + print(temp.sigmaBH(10000,'DDT') * 1E20 * 1E20) + #temp = FIELDLINES() + #val=temp.read_indata('input.ORBITS') + #temp.read_wout('fieldlines_test.nc') + sys.exit(0) diff --git a/pySTEL/libstell/libstell.py b/pySTEL/libstell/libstell.py index 190ff2102..4cdb80765 100644 --- a/pySTEL/libstell/libstell.py +++ b/pySTEL/libstell/libstell.py @@ -1,645 +1,1396 @@ -# LIBSTELL Module -from . import s1, s2, s3 - -def read_vmec(file): - import os, sys - import ctypes as ct - import numpy.ctypeslib as npct - import numpy as np - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - # Read File - read_wout = getattr(libstell,s1+'read_wout_mod_'+s2+'_readw_and_open'+s3) - read_wout.argtypes=[ct.c_char_p, ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.c_long] - read_wout.restype=None - ierr = ct.c_int(0) - iopen = ct.c_int(0) - read_wout(file.encode('UTF-8'), ct.byref(ierr), ct.byref(iopen), len(file)) - # Setup Arrays - vmec_data={} - # Check - if not (ierr.value == 0): - return vmec_data - # Logical - varlist=['lasym','lthreed','lwout_opened'] - for temp in varlist: - vmec_data[temp]=ct.c_bool.in_dll(libstell,s1+'read_wout_mod_'+s2+'_'+temp+s3).value - # Integers - varlist=['ns','nfp','mpol','ntor','mnmax','mnmax_nyq','iasym','ierr_vmec'] - for temp in varlist: - vmec_data[temp]=ct.c_int.in_dll(libstell,s1+'read_wout_mod_'+s2+'_'+temp+s3).value - # Doubles - varlist=['wb','wp','gamma','pfac','rmax_surf','rmin_surf','zmax_surf',\ - 'aspect','betatot','betapol','betator','betaxis','b0','version_',\ - 'ionlarmor','volavgb','fsql','fsqr','fsqz','ftolv','aminor','rmajor',\ - 'volume','rbtor','rbtor0','itor','machsq'] - for temp in varlist: - vmec_data[temp]=ct.c_double.in_dll(libstell,s1+'read_wout_mod_'+s2+'_'+temp+s3).value - # REAL Arrays (ns) - varlist = ['iotas','iotaf','presf','phipf','chipf','chi','phi','mass',\ - 'pres','beta_vol','phip','buco','bvco','vp','overr','jcuru',\ - 'jcurv','specw','jdotb','dmerc','dwell','dcurr','dgeod','equif'] - arr_size = vmec_data['ns'] - ftemp = ct.POINTER(ct.c_double) - for temp in varlist: - vmec_data[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'read_wout_mod_'+s2+'_'+temp+s3),(arr_size,1)) - # REAL Arrays (mnmax) - ftemp = ct.POINTER(ct.c_double) - vmec_data['xm']=npct.as_array(ftemp.in_dll(libstell,s1+'read_wout_mod_'+s2+'_xm'+s3),(vmec_data['mnmax'],1)) - vmec_data['xn']=npct.as_array(ftemp.in_dll(libstell,s1+'read_wout_mod_'+s2+'_xn'+s3),(vmec_data['mnmax'],1)) - vmec_data['xm_nyq']=npct.as_array(ftemp.in_dll(libstell,s1+'read_wout_mod_'+s2+'_xm_nyq'+s3),(vmec_data['mnmax_nyq'],1)) - vmec_data['xn_nyq']=npct.as_array(ftemp.in_dll(libstell,s1+'read_wout_mod_'+s2+'_xn_nyq'+s3),(vmec_data['mnmax_nyq'],1)) - ## Array values 1D - ftemp=ct.POINTER(ct.c_double) - ns = vmec_data['ns'] - mnmax = vmec_data['mnmax'] - mnmax_nyq = vmec_data['mnmax_nyq'] - ns_size = (ns,1) - mn_size = (mnmax,1) - mnnyq_size = (mnmax_nyq,1) - ## 2D Arrays - mn2d_size = (ns, mnmax) - mn2d_nyq_size = (ns, mnmax_nyq) - fmn=ct.POINTER(ct.c_double) - vmec_data['rmnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_rmnc'+s3),mn2d_size) #ns,mnmax format - vmec_data['zmns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_zmns'+s3),mn2d_size) #ns,mnmax format - vmec_data['lmns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_lmns'+s3),mn2d_size) #ns,mnmax format - vmec_data['bmnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bmnc'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['gmnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_gmnc'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsupumnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsupumnc'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsupvmnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsupvmnc'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsubsmns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsubsmns'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsubumnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsubumnc'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsubvmnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsubvmnc'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['currumnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_currumnc'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['currvmnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_currvmnc'+s3),mn2d_nyq_size) #ns,mnmax format - if vmec_data['iasym']: - vmec_data['rmns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_rmns'+s3),mn2d_size) #ns,mnmax format - vmec_data['zmnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_zmnc'+s3),mn2d_size) #ns,mnmax format - vmec_data['lmnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_lmnc'+s3),mn2d_size) #ns,mnmax format - vmec_data['bmns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bmns'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['gmns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_gmns'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsupumns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsupumns'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsupvmns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsupvmns'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsubsmnc']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsubsmnc'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsubumns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsubumns'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['bsubvmns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_bsubvmns'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['currumns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_currumns'+s3),mn2d_nyq_size) #ns,mnmax format - vmec_data['currvmns']=npct.as_array(fmn.in_dll(libstell,s1+'read_wout_mod_'+s2+'_currvmns'+s3),mn2d_nyq_size) #ns,mnmax format - # Free memory (don't do this as python accesses this memory) - #read_wout_dealloc = getattr(libstell,s1+'read_wout_mod_'+s2+'_read_wout_deallocate'+s3) - #read_wout_dealloc() - # Correct Arrays (mn-nv) to (mn+nv) - vmec_data['xn'] = -vmec_data['xn'] - # Put on full grid - vmec_data['buco'] = h2f(vmec_data['buco'],ns) - vmec_data['bvco'] = h2f(vmec_data['bvco'],ns) - vmec_data['vp'] = h2f(vmec_data['vp'],ns) - vmec_data['overr'] = h2f(vmec_data['overr'],ns) - vmec_data['specw'] = h2f(vmec_data['specw'],ns) - # Put matrix quantities on full grid - for key in ['bmnc','gmnc','lmns','bsupumnc','bsupvmnc','bsubsmns','bsubumnc','bsubvmnc']: - vmec_data[key][0,:] = 1.5 * vmec_data[key][1,:] - 0.5 * vmec_data[key][2,:] - vmec_data[key][1:ns-2,:] = 0.5 * (vmec_data[key][1:ns-2,:] + vmec_data[key][2:ns-1,:]) - vmec_data[key][ns-1,:] = 2.0 * vmec_data[key][ns-2,:] - vmec_data[key][ns-3,:] - if vmec_data['iasym']: - for key in ['bmns','gmns','lmnc','bsupumns','bsupvmns','bsubsmnc','bsubumns','bsubvmns']: - vmec_data[key][0,:] = 1.5 * vmec_data[key][1,:] - 0.5 * vmec_data[key][2,:] - vmec_data[key][1:ns-2,:] = 0.5 * (vmec_data[key][1:ns-2,:] + vmec_data[key][2:ns-1,:]) - vmec_data[key][ns-1,:] = 2.0 * vmec_data[key][ns-2,:] - vmec_data[key][ns-3,:] - # Return the data dictionary - return vmec_data - -def read_boozer(file): - import os, sys - import ctypes as ct - import numpy.ctypeslib as npct - import numpy as np - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - # Read File - read_boozer = getattr(libstell,s1+'read_boozer_mod_'+s2+'_read_boozer_file'+s3) - read_boozer.argtypes=[ct.c_char_p, ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.c_long] - read_boozer.restype=None - ierr = ct.c_int(0) - iopen = ct.c_int(0) - read_boozer(file.encode('UTF-8'), ct.byref(ierr), ct.byref(iopen), len(file)) - # Setup Arrays - boozer_data={} - # Check - if not (ierr.value == 0): - return boozer_data - # Logical - varlist=['lasym_b'] - for temp in varlist: - boozer_data[temp]=ct.c_bool.in_dll(libstell,s1+'read_boozer_mod_'+s2+'_'+temp+s3).value - # Integers - varlist=['ns_b','nfp_b','mboz_b','nboz_b','mnboz_b'] - for temp in varlist: - boozer_data[temp]=ct.c_int.in_dll(libstell,s1+'read_boozer_mod_'+s2+'_'+temp+s3).value - # Doubles - varlist=['aspect_b','rmax_b','rmin_b','betaxis_b'] - for temp in varlist: - boozer_data[temp]=ct.c_double.in_dll(libstell,s1+'read_boozer_mod_'+s2+'_'+temp+s3).value - # INTEGER Arrays (mnboz_b) - varlist = ['ixm_b','ixn_b'] - arr_size = boozer_data['mnboz_b'] - ftemp = ct.POINTER(ct.c_int) - for temp in varlist: - boozer_data[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'read_boozer_mod_'+s2+'_'+temp+s3),(arr_size,1)) - # REAL Arrays (ns) - varlist = ['iota_b','pres_b','phip_b','phi_b','beta_b','buco_b','bvco_b'] - arr_size = boozer_data['ns_b'] - ftemp = ct.POINTER(ct.c_double) - for temp in varlist: - boozer_data[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'read_boozer_mod_'+s2+'_'+temp+s3),(arr_size,1)) - ## Array values 1D - ftemp=ct.POINTER(ct.c_double) - ns = boozer_data['ns_b'] - mnmax = boozer_data['mnboz_b'] - ns_size = (ns,1) - mn_size = (mnmax,1) - ## 2D Arrays - varlist = ['rmnc_b','zmns_b','bmnc_b','pmns_b','gmnc_b'] - mn2d_size = (ns, mnmax) - fmn=ct.POINTER(ct.c_double) - for temp in varlist: - boozer_data[temp]=npct.as_array(fmn.in_dll(libstell,s1+'read_boozer_mod_'+s2+'_'+temp+s3),mn2d_size) #ns,mnmax format - if boozer_data['lasym_b']: - varlist = ['rmns_b','zmnc_b','bmns_b','pmnc_b','gmns_b'] - for temp in varlist: - boozer_data[temp]=npct.as_array(fmn.in_dll(libstell,s1+'read_boozer_mod_'+s2+'_'+temp+s3),mn2d_size) #ns,mnmax format - # Return the data dictionary - return boozer_data - -def h2f(var,ns): - import numpy as np - temp = np.zeros((ns,1)) - temp[0] = 1.5 * var[0] - 0.5 * var[1] - temp[1:ns-1] = 0.5* (var[0:ns-2] + var[1:ns-1]) - temp[ns-1] = 1.5 * var[ns-2] - 0.5 * var[ns-3] - return temp - -def cfunct(theta,zeta,fmnc,xm,xn): - import numpy as np - f=0 - (ns,mn)=fmnc.shape - lt = len(theta) - lz = len(zeta) - mt=np.matmul(xm,theta.T) - nz=np.matmul(xn,zeta.T) - cosmt=np.cos(mt) - sinmt=np.sin(mt) - cosnz=np.cos(nz) - sinnz=np.sin(nz) - f = np.zeros((ns,lt,lz)) - fmn = np.ndarray((mn,lt)) - for k in range(ns): - fmn = np.broadcast_to(fmnc[k,:],(lt,mn)).T - fmncosmt=(fmn*cosmt).T - fmnsinmt=(fmn*sinmt).T - f[k,:,:]=np.matmul(fmncosmt, cosnz)-np.matmul(fmnsinmt, sinnz) - return f - -def sfunct(theta,zeta,fmnc,xm,xn): - import numpy as np - f=0 - (ns,mn)=fmnc.shape - lt = len(theta) - lz = len(zeta) - mt=np.matmul(xm,theta.T) - nz=np.matmul(xn,zeta.T) - cosmt=np.cos(mt) - sinmt=np.sin(mt) - cosnz=np.cos(nz) - sinnz=np.sin(nz) - f = np.zeros((ns,lt,lz)) - fmn = np.ndarray((mn,lt)) - for k in range(ns): - fmn = np.broadcast_to(fmnc[k,:],(lt,mn)).T - f[k,:,:]=np.matmul((fmn*sinmt).T,cosnz)+np.matmul((fmn*cosmt).T,sinnz) - return f - -def torocont(r,z,val,s): - import numpy as np - import matplotlib.pyplot as pyplot - h=pyplot.axes(xlabel='R [m]',ylabel='Z [m]',aspect='equal') - pyplot.pcolormesh(r[:,:,s],z[:,:,s],val[:,:,s],cmap='jet',shading='gouraud',axes=h) - pyplot.show() - return h - -def toroslice(r,zeta,z,s): - import numpy as np - import matplotlib.pyplot as pyplot - h=pyplot.axes(xlabel='R [m]',ylabel='Z [m]',aspect='equal') - if (s[0] == 0): - pyplot.plot(r[0,0,zeta],z[0,0,zeta],'+',color='black',axes=h) - pyplot.plot(np.transpose(r[s[1:],:,zeta]),np.transpose(z[s[1:],:,zeta]),color='black',axes=h) - else: - for i in range(0,): - pyplot.plot(np.transpose(r[s,:,zeta]),np.transpose(z[s,:,zeta]),color='black',axes=h) - pyplot.show() - return h - -def isotoro(r,z,zeta,svals,*args,**kwargs): - import numpy as np - import matplotlib.pyplot as pyplot - import mpl_toolkits.mplot3d as mplot3d - import math as math - import matplotlib.tri as mtri - #from mayavi import mlab - nr = np.size(svals) - if (nr == 1): - s= [svals] - nr = 1 - else: - s=svals - nt = np.size(r,1) - nz = np.size(r,2) - vertex = np.zeros((nt*nz,3,nr)) - for k in range(0,nr): - ivertex = 0 - ifaces = 0 - for j in range(0,nz): - for i in range(0,nt): - vertex[ivertex,0,k]=r[s[k],i,j]*math.cos(zeta[j]) - vertex[ivertex,1,k]=r[s[k],i,j]*math.sin(zeta[j]) - vertex[ivertex,2,k]=z[s[k],i,j] - ivertex = ivertex + 1 - u = np.linspace(0, 1, endpoint=True, num=nt) - v = np.linspace(0, 1, endpoint=True, num=nz) - u, v = np.meshgrid(u, v) - u, v = u.flatten(), v.flatten() - tri = mtri.Triangulation(u, v) - test=len(kwargs) - fig=kwargs.pop('fig',pyplot.figure()) - h=kwargs.pop('axes',fig.add_subplot(111,projection='3d')) - for k in range(0,nr): - if (len(args)==0): - tsurf=h.plot_trisurf(vertex[:,0,k],vertex[:,1,k],vertex[:,2,k], triangles=tri.triangles,color='red',shade='yes',linewidths=0.0) - #tsurf=mlab.triangular_mesh(vertex[:,0,k],vertex[:,1,k],vertex[:,2,k], tri.triangless) - else: - # Matplotlib way (SLOW) - vals = args[0][s[k],:,:].T.flatten() - colors = np.mean(vals[tri.triangles], axis=1) - tsurf=h.plot_trisurf(vertex[:,0,k],vertex[:,1,k],vertex[:,2,k], triangles=tri.triangles,cmap='jet',shade='yes',linewidths=0.0) - tsurf.set_array(colors) - tsurf.autoscale() - #MAYAVI Way (need to figure out how to embed) - #h = mlab.figure() - #vals = args[0][s[k],:,:].T.flatten() - #tsurf=mlab.triangular_mesh(vertex[:,0,k],vertex[:,1,k],vertex[:,2,k], tri.triangles, scalars=vals, colormap='jet',figure=h) - #print(type(tsurf)) - if (test==0): - pyplot.show() - return h - -def calc_jll(vmec_data, theta, zeta ): - # CALC_JLL(vmec_data,theta,zeta) Calculates the parallel current density. - # This funciton takes a VMEC data structure (as read by read_vmec) and - # theta/zeta arrays as input and outputs the parallel current density. - - # Example usage (Matlab) - # theta=0:2*pi/359:2*pi; - # zeta=0:2*pi/63:2*pi; - # data=read_vmec('wout.test'); % Reads VMEC wout file - # jll=calc_jll(vmec_data,theta,zeta); % Calculate the current - # - # Example usage (Python) - # theta=np.linspace(0, 2*np.pi, 360) - # zeta=np.linspace(0, 2*np.pi, 64) - # vmec_data=read_vmec('wout.nc') - # jll=calc_jll(vmec_data, theta, zeta) - - - # Maintained by: Samuel Lazerson (lazerson@pppl.gov) - # Version: 1.00 - - b =cfunct(theta,zeta,vmec_data['bmnc'], vmec_data['xm_nyq'],vmec_data['xn_nyq']) - g =cfunct(theta,zeta,vmec_data['gmnc'], vmec_data['xm_nyq'],vmec_data['xn_nyq']) - bu=cfunct(theta,zeta,vmec_data['bsubumnc'],vmec_data['xm_nyq'],vmec_data['xn_nyq']) - bv=cfunct(theta,zeta,vmec_data['bsubvmnc'],vmec_data['xm_nyq'],vmec_data['xn_nyq']) - ju=cfunct(theta,zeta,vmec_data['currumnc'],vmec_data['xm_nyq'],vmec_data['xn_nyq']) - jv=cfunct(theta,zeta,vmec_data['currvmnc'],vmec_data['xm_nyq'],vmec_data['xn_nyq']) - - if (vmec_data['iasym']): - b =b +sfunct(theta,zeta,vmec_data['bmns'], vmec_data['xm_nyq'],vmec_data['xn_nyq']) - g =g +sfunct(theta,zeta,vmec_data['gmns'], vmec_data['xm_nyq'],vmec_data['xn_nyq']) - bu=bu+sfunct(theta,zeta,vmec_data['bsubumns'],vmec_data['xm_nyq'],vmec_data['xn_nyq']) - bv=bv+sfunct(theta,zeta,vmec_data['bsubvmns'],vmec_data['xm_nyq'],vmec_data['xn_nyq']) - ju=ju+sfunct(theta,zeta,vmec_data['currumns'],vmec_data['xm_nyq'],vmec_data['xn_nyq']) - jv=jv+sfunct(theta,zeta,vmec_data['currvmns'],vmec_data['xm_nyq'],vmec_data['xn_nyq']) - - - jll = (bu*ju+bv*jv)/(g*b) - return jll - -def safe_close(iunit): - import os, sys - import ctypes as ct - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - # Handle interface - safe_close_h = getattr(libstell,s1+'safe_open_mod_'+s2+'_safe_close'+s3) - safe_close_h.restype=None - iunit_temp = ct.c_int(iunit) - safe_close_h(ct.byref(iunit_temp)) - return - -def safe_open(iunit,istat,filename,filestat,fileform,record_in,access_in,delim_in): - import os, sys - import ctypes as ct - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - # Handle interface - safe_open_h = getattr(libstell,s1+'safe_open_mod_'+s2+'_safe_open'+s3) - # SUBROUTINE safe_open(int iunit, int istat, char filename, char filestat, char fileform, int record_in, char access_in, char delim_in) - safe_open_h.argtypes= [ ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.c_char_p, ct.c_char_p, ct.c_char_p, \ - ct.POINTER(ct.c_int), ct.c_char_p, ct.c_char_p, \ - ct.c_long, ct.c_long, ct.c_long, ct.c_long, ct.c_long] - safe_open_h.restype=None - iunit_temp = ct.c_int(iunit) - istat_temp = ct.c_int(istat) - record_in_temp = ct.c_int(record_in) - opt1 = ct.c_bool(True) - opt2 = ct.c_bool(True) - opt3 = ct.c_bool(True) - safe_open_h(ct.byref(iunit_temp),ct.byref(istat_temp), \ - filename.encode('UTF-8'),filestat.encode('UTF-8'),fileform.encode('UTF-8'),\ - ct.byref(record_in_temp),access_in.encode('UTF-8'),delim_in.encode('UTF-8'), \ - len(filename),len(filestat),len(fileform),len(access_in),len(delim_in)) - istat = istat_temp - iunit = iunit_temp - istat = istat_temp - return istat - -def read_indata_namelist(iunit,istat): - import os, sys - import ctypes as ct - import numpy.ctypeslib as npct - import numpy as np - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - # Handle interface - read_indata_namelist = getattr(libstell,s1+'vmec_input_'+s2+'_read_indata_namelist'+s3) - #SUBROUTINE read_indata_namelist (iunit, istat) - read_indata_namelist.argtypes = [ct.POINTER(ct.c_int),ct.POINTER(ct.c_int)] - read_indata_namelist.restype=None - iunit_temp = ct.c_int(iunit) - istat_temp = ct.c_int(istat) - read_indata_namelist(ct.byref(iunit_temp),ct.byref(istat_temp)) - istat = istat_temp - iunit = iunit_temp - # Setup Arrays - indata_namelist={} - # Logicals - varlist=['lpofr','lmac','lfreeb','lrecon','loldout','ledge_dump','lasym','lforbal','lrfp',\ - 'lmovie','lmove_axis','lwouttxt','ldiagno','lmoreiter','lfull3d1out','l_v3fit',\ - 'lspectrum_dump','loptim','lgiveup','lbsubs','lgiveup'] - for temp in varlist: - indata_namelist[temp]=ct.c_bool.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3).value - # Integers - varlist=['nfp','ncurr','nsin','niter','nstep','nvacskip','mpol','ntor','ntheta','nzeta', \ - 'mfilter_fbdy','nfilter_fbdy','max_main_iterations','omp_num_threads',\ - 'imse','isnodes','itse','ipnodes','iopt_raxis','imatch_phiedge','nflxs'] - for temp in varlist: - indata_namelist[temp]=ct.c_int.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3).value - # Reals - varlist=['time_slice','curtor','delt','ftol','tcon0','gamma','phiedge','phidiam',\ - 'sigma_current','sigma_delphid','tensi','tensp','tensi2','fpolyi','presfac',\ - 'mseangle_offset','pres_offset','mseangle_offsetm','spres_ped','bloat',\ - 'pres_scale','prec2d_threshold','bcrit','fgiveup'] - for temp in varlist: - indata_namelist[temp]=ct.c_double.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3).value - # Get integers defined elsewhere (Hardcode for now, not sure how to get them) - #indata_namelist['nbsetsp']=ct.c_int.in_dll(libstell,s1+'vsvd0_'+s2+'_nbsetsp').value - # Integer Arrays (100) - varlist = ['ns_array','niter_array'] - arr_size=100 - ftemp = ct.c_int*arr_size - for temp in varlist: - indata_namelist[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3),(arr_size,1)) - # Note that we skip some arrays related to recon stuff because we don't need them and we - # need to figure out how to pull stuff from other modules see the above issue. - # Real 2D Arrays (ntord=101,mpol1d=100) - varlist = ['rbs','zbc','rbc','zbs'] - arr_size1=2*101+1 - arr_size2=100+1 - ftemp = ct.c_double*arr_size1*arr_size2 - for temp in varlist: - indata_namelist[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3),(arr_size1,arr_size2)) - # REAL Arrays (21) - varlist = ['am','ai','ac','ah','at'] - arr_size=21 - ftemp = ct.c_double*arr_size - for temp in varlist: - indata_namelist[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3),(arr_size,1)) - # REAL Arrays (20) - varlist = ['aphi'] - arr_size=20 - ftemp = ct.c_double*arr_size - for temp in varlist: - indata_namelist[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3),(arr_size,1)) - # REAL Arrays (ndatafmax=101) - varlist = ['am_aux_s','am_aux_f','ac_aux_s','ac_aux_f','ai_aux_s','ai_aux_f',\ - 'ah_aux_s','ah_aux_f','at_aux_s','at_aux_f'] - arr_size=101 - ftemp = ct.c_double*arr_size - for temp in varlist: - indata_namelist[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3),(arr_size,1)) - # REAL Arrays (ntord+1=102) - varlist = ['raxis','zaxis','raxis_cc','raxis_cs','zaxis_cc','zaxis_cs'] - arr_size=102 - ftemp = ct.c_double*arr_size - for temp in varlist: - indata_namelist[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3),(arr_size,1)) - # REAL Arrays (100) - varlist = ['ftol_array'] - arr_size=100 - ftemp = ct.c_double*arr_size - for temp in varlist: - indata_namelist[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3),(arr_size,1)) - # REAL Arrays (nigroup=300) - varlist = ['extcur'] - arr_size=300 - ftemp = ct.c_double*arr_size - for temp in varlist: - indata_namelist[temp]=npct.as_array(ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3),(arr_size,1)) - # Charater arrays - varlist = ['pcurr_type','piota_type','pmass_type','pt_type','ph_type'] - arr_size=20 - ftemp = ct.c_char*arr_size - for temp in varlist: - indata_namelist[temp]=ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_'+temp+s3).value.decode('UTF-8') - ftemp = ct.c_char*200 - indata_namelist['mgrid_file']=ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_mgrid_file'+s3).value.decode('UTF-8') - ftemp = ct.c_char*200 - indata_namelist['trip3d_file']=ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_trip3d_file'+s3).value.decode('UTF-8') - ftemp = ct.c_char*10 - indata_namelist['precon_type']=ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_precon_type'+s3).value.decode('UTF-8') - ftemp = ct.c_char*120 - indata_namelist['arg1']=ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_arg1'+s3).value.decode('UTF-8') - ftemp = ct.c_char*100 - indata_namelist['input_extension']=ftemp.in_dll(libstell,s1+'vmec_input_'+s2+'_input_extension'+s3).value.decode('UTF-8') - return indata_namelist - -def set_module_var(module,var,val): - import os, sys - import ctypes as ct - import numpy.ctypeslib as npct - import numpy as np - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - if type(val) == bool: - f = ct.c_bool - elif type(val) == int: - f = ct.c_int - elif type(val) == float: - f = ct.c_double - elif type(val) == str: - n = len(val) - f = ct.c_char*n - elif type(val) == np.ndarray: - if type(val[0]) == bool: - tt = ct.c_bool - elif type(val[0]) == np.int32: - tt = ct.c_int - elif type(val[0]) == np.float64: - tt = ct.c_double - else: - print(' Unrecognized type:',type(val[0])) - return - n = val.ndim - f = tt*val.size - #print(n,val.size) - else: - print(' Unrecognized type:',type(val)) - return - temp=f.in_dll(libstell,s1+''+module+'_'+s2+'_'+var) - if type(val) == np.ndarray: - if n==1: - for i,col in enumerate(val): - temp[i] = val[i] - elif type(val) == str: - temp.value = val.encode('UTF-8') - else: - temp.value = val - return - -def write_indata_namelist(iunit,istat): - import os, sys - import ctypes as ct - import numpy.ctypeslib as npct - import numpy as np - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - # Handle interface - write_indata_namelist = getattr(libstell,s1+'vmec_input_'+s2+'_write_indata_namelist'+s3) - #SUBROUTINE read_indata_namelist (iunit, istat) - write_indata_namelist.argtypes = [ct.POINTER(ct.c_int),ct.POINTER(ct.c_int)] - write_indata_namelist.restype=None - iunit_temp = ct.c_int(iunit) - istat_temp = ct.c_int(istat) - write_indata_namelist(ct.byref(iunit_temp),ct.byref(istat_temp)) - #istat = istat_temp - #iunit = iunit_temp - return - -def pcurr(xx): - import os, sys - import ctypes as ct - import numpy.ctypeslib as npct - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - pcurr_func = getattr(libstell,'pcurr_') - #SUBROUTINE pcurr (xx) - pcurr_func.argtypes = [ct.POINTER(ct.c_double)] - pcurr_func.restype=ct.c_double - xx_temp = ct.c_double(xx) - val = pcurr_func(ct.byref(xx_temp)) - return val; - -def pmass(xx): - import os, sys - import ctypes as ct - import numpy.ctypeslib as npct - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - pmass_func = getattr(libstell,'pmass_') - #SUBROUTINE piota (xx) - pmass_func.argtypes = [ct.POINTER(ct.c_double)] - pmass_func.restype=ct.c_double - xx_temp = ct.c_double(xx) - val = pmass_func(ct.byref(xx_temp)) - return val; - -def piota(xx): - import os, sys - import ctypes as ct - import numpy.ctypeslib as npct - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - qtCreatorPath=os.environ["STELLOPT_PATH"] - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - piota_func = getattr(libstell,'piota_') - #SUBROUTINE piota (xx) - piota_func.argtypes = [ct.POINTER(ct.c_double)] - piota_func.restype=ct.c_double - xx_temp = ct.c_double(xx) - val = piota_func(ct.byref(xx_temp)) - return val; +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for interfacing to libstell +""" +# Libraries +# Constants +# LIBSTELL Class +class LIBSTELL(): + """Class for working with VMEC equilibria + """ + def __init__(self, parent=None): + import os,sys + import ctypes as ct + from subprocess import Popen, PIPE + self.STELLOPT_PATH = os.environ["STELLOPT_PATH"] + self.PATH_TO_LIBSTELL = os.path.join(self.STELLOPT_PATH,'LIBSTELL','Release','libstell.so') + try: + self.libstell = ct.cdll.LoadLibrary(self.PATH_TO_LIBSTELL) + except: + print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + print("!! Could not load shared libraray libstell.so !!") + print(f"!! PATH: {self.PATH_TO_LIBSTELL} !!") + print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + # Figure out uderscoring + out = Popen(args="nm "+self.PATH_TO_LIBSTELL, + shell=True, + stdout=PIPE).communicate()[0].decode("utf-8") + attrs = [ i.split(" ")[-1].replace("\r", "") \ + for i in out.split("\n") if " T " in i] + func = '_write_wout_file' + module = 'read_wout_mod_' + names = [ s for s in attrs if module in s and func in s] + name = names[0].replace(module, ',') + name = name.replace(func, ',') + self.s1, self.s2, self.s3 = name.split(',') + # Weird OSX behavior + if self.s1=='___': + self.s1='__' + def safe_open(self,iunit,istat,filename,filestat,fileform,record_in=None,access_in='SEQUENTIAL',delim_in='APOSTROPHE'): + """Wrapper to safe_open in safe_open_mod + This routine wrappers safe_open from safe_open_mod + Parameters + ---------- + iunit : int + Fortran file unit number + istat : int + Status value + filename : str + Filename string + filestat : str + Fortran open file status ('OLD' 'NEW' 'UNKNOWN' 'SCRATCH') + fileform : str + Fortran open file form ('FORMATTED' 'UNFORMATTED' 'PRINT') + record_in : int + Fortran open record size + access_in : str + Fortran open access ('APPEND' 'DIRECT' 'SEQUENTIAL') + delim_in : str + Fortran open delimter () + """ + import ctypes as ct + module_name = self.s1+'safe_open_mod_'+self.s2 + safe_open_h = getattr(self.libstell,module_name+'_safe_open'+self.s3) + # SUBROUTINE safe_open(int iunit, int istat, char filename, char filestat, char fileform, int record_in, char access_in, char delim_in) + safe_open_h.argtypes= [ ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.c_char_p, ct.c_char_p, ct.c_char_p, \ + ct.POINTER(ct.c_int), ct.c_char_p, ct.c_char_p, \ + ct.c_long, ct.c_long, ct.c_long, ct.c_long, ct.c_long] + safe_open_h.restype=None + iunit_temp = ct.c_int(iunit) + istat_temp = ct.c_int(istat) + opt1 = ct.c_bool(True) + opt2 = ct.c_bool(True) + opt3 = ct.c_bool(True) + #if record_in: + if record_in: + record_in_temp = ct.c_int(record_in) + else: + record_in_temp = ct.c_int(0) + safe_open_h(ct.byref(iunit_temp),ct.byref(istat_temp), \ + filename.encode('UTF-8'),filestat.encode('UTF-8'),fileform.encode('UTF-8'),\ + ct.byref(record_in_temp),access_in.encode('UTF-8'),delim_in.encode('UTF-8'), \ + len(filename),len(filestat),len(fileform),len(access_in),len(delim_in)) + istat = istat_temp + iunit = iunit_temp + return + def safe_close(self,iunit): + """Wrapper to safe_close in safe_open_mod + + This routine wrappers safe_close from safe_open_mod + + Parameters + ---------- + iunit : int + Fortran file unit number + """ + import ctypes as ct + module_name = self.s1+'safe_open_mod_'+self.s2 + safe_close_h = getattr(self.libstell,module_name+'_safe_close'+self.s3) + safe_close_h.restype=None + iunit_temp = ct.c_int(iunit) + safe_close_h(ct.byref(iunit_temp)) + return + + def read_indata(self,filename): + """Reads a VMEC INDATA namelist + + This routine wrappers read_indata_namelist function in + vmec_input. To do this we wrapper safe_open_mod + + Parameters + ---------- + file : str + Path to wout file. + """ + import ctypes as ct + # Get constants + module_name = self.s1+'vsvd0_'+self.s2 + get_constant = getattr(self.libstell,module_name+'_getnigroup'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + nigroup = get_constant() + module_name = self.s1+'vparams_'+self.s2 + get_constant = getattr(self.libstell,module_name+'_getndatafmax'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + ndatafmax = get_constant() + get_constant = getattr(self.libstell,module_name+'_getmpol1d'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + mpol1d = get_constant() + get_constant = getattr(self.libstell,module_name+'_getntord'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + ntord = get_constant() + get_constant = getattr(self.libstell,module_name+'_getnsd'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + nsd = get_constant() + # We use an added routine as a helper + module_name = self.s1+'vmec_input_'+self.s2 + read_indata_namelist = getattr(self.libstell,module_name+'_read_indata_namelist_byfile'+self.s3) + read_indata_namelist.argtypes = [ct.c_char_p,ct.c_long] + read_indata_namelist.restype=None + read_indata_namelist(filename.encode('UTF-8'),len(filename)) + # Get vars + booList=['lpofr','lmac','lfreeb','lrecon','loldout','ledge_dump','lasym','lforbal','lrfp',\ + 'lmovie','lmove_axis','lwouttxt','ldiagno','lmoreiter','lfull3d1out','l_v3fit',\ + 'lspectrum_dump','loptim','lgiveup','lbsubs','lgiveup'] + booLen=[1]*len(booList) + intList=['nfp','ncurr','nsin','niter','nstep','nvacskip','mpol','ntor','ntheta','nzeta', \ + 'mfilter_fbdy','nfilter_fbdy','max_main_iterations','omp_num_threads',\ + 'imse','isnodes','itse','ipnodes','iopt_raxis','imatch_phiedge','nflxs'] + intLen=[1]*len(intList) + intList.extend(['ns_array','niter_array']) + intLen.extend([(100,1)]*2) + realList=['time_slice','curtor','delt','ftol','tcon0','gamma','phiedge','phidiam',\ + 'sigma_current','sigma_delphid','tensi','tensp','tensi2','fpolyi','presfac',\ + 'mseangle_offset','pres_offset','mseangle_offsetm','spres_ped','bloat',\ + 'pres_scale','prec2d_threshold','bcrit','fgiveup'] + realLen=[1]*len(realList) + realList.extend(['rbc','zbs','rbs','zbc']) + realLen.extend([(2*ntord+1,mpol1d+1)]*4) + realList.extend(['am_aux_s','am_aux_f','ai_aux_s','ai_aux_f','ac_aux_s','ac_aux_f']) + realLen.extend([(ndatafmax,1)]*6) + realList.extend(['am','ai','ac','aphi','ah','at']) + realLen.extend([(21,1)]*6) + realList.extend(['ah_aux_s','ah_aux_f','at_aux_s','at_aux_f']) + realLen.extend([(ndatafmax,1)]*4) + realList.extend(['raxis','zaxis','raxis_cc','raxis_cs','zaxis_cc','zaxis_cs']) + realLen.extend([(ntord+1,1)]*6) + realList.extend(['ftol_array','extcur']) + realLen.extend([(100,1),(nigroup,1)]) + charList=['pcurr_type','piota_type','pmass_type','pt_type','ph_type'] + charLen=[(20,1)]*6 + charList.extend(['mgrid_file','input_extension']) + charLen.extend([(200,1),(200,1)]) + out_data = self.get_module_vars(module_name,booList,booLen,intList,intLen,realList,realLen,charList,charLen,ldefined_size_arrays=True) + return out_data + + def write_indata(self,filename,out_dict=None): + """Wrappers writing of the VMEC INDATA namelist + + This routine wrappers write_indata_namelist in LIBSTELL + + Parameters + ---------- + file : str + Path to input file. + out_dict : dict (optional) + Dictionary of items to change. + """ + import ctypes as ct + module_name = self.s1+'vmec_input_'+self.s2 + # Check if we want to update values + if out_dict: + for key in out_dict: + self.set_module_var(module_name,key,out_dict[key]) + write_indata_namelist = getattr(self.libstell,module_name+'_write_indata_namelist_byfile'+self.s3) + write_indata_namelist.argtypes = [ct.c_char_p,ct.c_long] + write_indata_namelist.restype=None + write_indata_namelist(filename.encode('UTF-8'),len(filename)) + + def read_bootin(self,filename): + """Reads a BOOTSJ BOOTIN namelist + + This routine wrappers read_boot_namelist function in + bootsj_input. To do this we wrapper safe_open_mod + + Parameters + ---------- + file : str + Path to wout file. + """ + import ctypes as ct + # We use an added routine as a helper + module_name = self.s1+'bootsj_input_'+self.s2 + read_bootin_namelist = getattr(self.libstell,module_name+'_read_boot_namelist_byfile'+self.s3) + read_bootin_namelist.argtypes = [ct.c_char_p,ct.c_long] + read_bootin_namelist.restype=None + read_bootin_namelist(filename.encode('UTF-8'),len(filename)) + # Get vars + intList=['nrho','mbuse','nbuse','isymm0'] + intLen=[1]*len(intList) + realList=['tempres', 'zeff1', 'dens0', 'teti', 'damp', 'damp_bs'] + realLen=[1]*len(realList) + realList.extend(['ate','ati']) + realLen.extend([(12,1)]*2) + out_data = self.get_module_vars(module_name,intVar=intList,intLen=intLen,realVar=realList,realLen=realLen,ldefined_size_arrays=True) + return out_data + + def set_bootin(self,in_dict): + """Set the bootin namelist variables via a passed dict + + This routine passes variable information back to the module + for writing using a dict + 'rho': number of rho values to use (depricated) + 'mbuse': number of poloidal modes in B-field to use + 'nbuse': number of toroidal modes in B-field to use + 'zeff1': Effective ion charge + 'dens0': Central electron density in 1E20 m^-3 units + 'teti': Electron to ion temeprature ratio + 'tempres': Te(s) = P(s)**tempres or if -1 Te(s) = sqrt(p) + 'damp': Superceeded by damp_bs + 'damp_bs': Resonance damping factor + 'isymm0': if !=0 force symmetry + 'ate': Polynomial electron temperature + 'ati': Polynomial ion temperature + + Parameters + ---------- + in_dict : dict + Input dictionary + """ + import ctypes as ct + module_name = self.s1+'bootsj_input_'+self.s2 + for key in in_dict.keys(): + self.set_module_var(module_name,key,in_dict[key]) + + + def write_bootin(self,filename): + """Wrappers writing of the BOOTSJ BOOTIN namelist + + This routine wrappers write_bootsj_input in LIBSTELL + + Parameters + ---------- + file : str + Path to input file. + """ + import ctypes as ct + module_name = self.s1+'bootsj_input_'+self.s2 + write_bootin_namelist = getattr(self.libstell,module_name+'_write_boot_namelist_byfile'+self.s3) + write_bootin_namelist.argtypes = [ct.c_char_p,ct.c_long] + write_bootin_namelist.restype=None + write_bootin_namelist(filename.encode('UTF-8'),len(filename)) + + def read_beams3d_input(self,filename): + """Reads a BEAMS3D BEAMS3D_INPUT namelist + + This routine wrappers read_beams3d_input function in + beams3d_input_mod. + + Parameters + ---------- + file : str + Path to wout file. + """ + import ctypes as ct + # A few constants defined in globals + module_name = self.s1+'beams3d_globals_'+self.s2 + get_constant = getattr(self.libstell,module_name+'_getmaxparticles'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + maxparticles = get_constant() + get_constant = getattr(self.libstell,module_name+'_getmaxbeams'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + maxbeams = get_constant() + get_constant = getattr(self.libstell,module_name+'_getmaxproflen'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + maxproflen = get_constant() + get_constant = getattr(self.libstell,module_name+'_getnion'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + nion = get_constant() + # Call the initialization routine + module_name = self.s1+'beams3d_input_mod_'+self.s2 + init_beams3d_input = getattr(self.libstell,module_name+'_init_beams3d_input'+self.s3) + init_beams3d_input.argtypes = None + init_beams3d_input.restype = None + init_beams3d_input() + # We use an added routine as a helper + module_name = self.s1+'beams3d_input_mod_'+self.s2 + read_beams3d_input = getattr(self.libstell,module_name+'_read_beams3d_input'+self.s3) + read_beams3d_input.argtypes = [ct.c_char_p,ct.POINTER(ct.c_int),ct.c_long] + read_beams3d_input.restype = None + istat = ct.c_int(0) + read_beams3d_input(filename.encode('UTF-8'),ct.byref(istat),len(filename)) + if not (istat.value == 0): + return None + # Get vars + intList=['nr','nphi','nz','nparticles_start','npoinc', \ + 'duplicate_factor', 'ns_prof1','ns_prof2', \ + 'ns_prof3','ns_prof4','ns_prof5', 'nr_fida', \ + 'nphi_fida', 'nz_fida', 'nenergy_fida', 'npitch_fida'] + intLen=[1]*len(intList) + intList.extend(['dex_beams','ni_aux_z']) + intLen.extend([(maxbeams,1),(nion,1)]) + realList=['rmin', 'rmax', 'zmin', 'zmax', 'phimin', 'phimax', \ + 'follow_tol', 'vc_adapt_tol', \ + 'ne_scale', 'te_scale', 'ti_scale', 'zeff_scale', \ + 'fusion_scale', 'plasma_zmean', 'plasma_mass', \ + 'therm_factor', 'lendt_m', 'te_col_min', \ + 'b_kick_min', 'b_kick_max', 'freq_kick', 'e_kick', \ + 'rho_fullorbit', 'partvmax', 'rmin_fida', \ + 'rmax_fida', 'zmin_fida', 'zmax_fida', 'phimin_fida', \ + 'phimax_fida','t_fida'] + realLen=[1]*len(realList) + realList.extend(['r_start_in', 'phi_start_in', 'z_start_in',\ + 'vll_start_in', 'mu_start_in', 't_end_in', \ + 'charge_in', 'mass_in', 'zatom_in', \ + 'weight_in', 'vr_start_in', 'vphi_start_in', \ + 'vz_start_in']) + realLen.extend([(maxparticles,1)]*13) + realList.extend(['mass_beams', 'charge_beams', 'e_beams',\ + 'p_beams', 'div_beams', 'asize_beams', \ + 'adist_beams']) + realLen.extend([(maxbeams,1)]*7) + realList.extend(['r_beams', 'z_beams', 'phi_beams']) + realLen.extend([(maxbeams,2)]*3) + realList.extend(['ne_aux_s', 'te_aux_s', 'ti_aux_s', \ + 'ne_aux_f', 'te_aux_f', 'ti_aux_f', \ + 'pot_aux_s', 'pot_aux_f', 'zeff_aux_s', \ + 'zeff_aux_f']) + realLen.extend([(maxproflen,1)]*10) + realList.extend(['ni_aux_s', 'ni_aux_f', 'ni_aux_m']) + realLen.extend([(maxproflen,1),(nion,maxproflen),(nion,1)]) + module_name = self.s1+'beams3d_globals_'+self.s2 + out_data = self.get_module_vars(module_name,intVar=intList,intLen=intLen,realVar=realList,realLen=realLen,ldefined_size_arrays=True) + return out_data + + def write_beams3d_input(self,filename,out_dict=None): + """Wrappers writing of the BEAMS3D_INPUT namelist + + This routine wrappers write_beams3d_input in LIBSTELL + + Parameters + ---------- + file : str + Path to input file. + out_dict : dict (optional) + Dictionary of items to change. + """ + import ctypes as ct + module_name = self.s1+'beams3d_globals_'+self.s2 + # Check if we want to update values + if out_dict: + for key in out_dict: + self.set_module_var(module_name,key,out_dict[key]) + module_name = self.s1+'beams3d_input_mod_'+self.s2 + write_beams3d_namelist = getattr(self.libstell,module_name+'_write_beams3d_namelist_byfile'+self.s3) + write_beams3d_namelist.argtypes = [ct.c_char_p,ct.c_long] + write_beams3d_namelist.restype=None + write_beams3d_namelist(filename.encode('UTF-8'),len(filename)) + + def read_diagno_in(self,filename): + """Reads a DIAGNO_IN namelist + + This routine wrappers read_diagno_input function in + diagno_input_mod. + + Parameters + ---------- + filename : str + Path to input file. + Returns + ------- + out_data : dict + Dictionary of items. + """ + import ctypes as ct + # We use an added routine as a helper + module_name = self.s1+'diagno_input_mod_'+self.s2 + read_diagno_input = getattr(self.libstell,module_name+'_read_diagno_input'+self.s3) + read_diagno_input.argtypes = [ct.c_char_p, ct.POINTER(ct.c_int), ct.c_long] + read_diagno_input.restype=None + ierr = ct.c_int(0) + read_diagno_input(filename.encode('UTF-8'),ct.byref(ierr),len(filename)) + # Get vars + booList=['lrphiz','luse_mut','lvc_field','lapoints_accurate_output','lbpoints_accurate_output'] + booLen=[1]*len(booList) + booList.extend(['luse_extcur']) + booLen.extend([(512,1)]) + intList=['nu','nv'] + intLen=[1]*len(intList) + realList=['units','vc_adapt_tol','vc_adapt_rel','int_step'] + realLen=[1]*len(realList) + realList.extend(['bprobe_turns','flux_turns','segrog_turns']) + realLen.extend([(2048,1),(512,1),(256,1)]) + charList=['int_type','afield_points_file','bfield_points_file',\ + 'bprobes_file','mirnov_file', 'seg_rog_file','flux_diag_file',\ + 'bprobes_mut_file', 'mir_mut_file', 'rog_mut_file', 'flux_mut_file'] + charLen=[(256,1)]*11 + module_name = self.s1+'diagno_runtime_'+self.s2 + out_data = self.get_module_vars(module_name,booList,booLen,intList,intLen,realList,realLen,charList,charLen,ldefined_size_arrays=True) + return out_data + + def write_diagno_in(self,filename,out_dict=None): + """Wrappers writing of the DIAGNO_IN namelist + + This routine wrappers write_diagno_input in LIBSTELL + + Parameters + ---------- + filename : str + Path to input file. + out_dict : dict (optional) + Dictionary of items to change. + """ + import ctypes as ct + module_name = self.s1+'diagno_runtime_'+self.s2 + # Check if we want to update values + if out_dict: + for key in out_dict: + self.set_module_var(module_name,key,out_dict[key]) + module_name = self.s1+'diagno_input_mod_'+self.s2 + write_diagno_input = getattr(self.libstell,module_name+'_write_diagno_input_byfile'+self.s3) + write_diagno_input.argtypes = [ct.c_char_p, ct.c_long] + write_diagno_input.restype=None + write_diagno_input(filename.encode('UTF-8'),len(filename)) + + def read_fieldlines_input(self,filename): + """Reads a FIELDLINES_INPUT namelist + + This routine wrappers read_fieldlines_input function in + fieldlines_input_mod. + + Parameters + ---------- + filename : str + Path to input file. + Returns + ------- + out_data : dict + Dictionary of items. + """ + import ctypes as ct + # A few constants defined in globals + module_name = self.s1+'fieldlines_globals_'+self.s2 + get_constant = getattr(self.libstell,module_name+'_getmaxlines'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + maxlines = get_constant() + # We use an added routine as a helper + module_name = self.s1+'fieldlines_input_mod_'+self.s2 + read_fieldlines_input = getattr(self.libstell,module_name+'_read_fieldlines_input'+self.s3) + read_fieldlines_input.argtypes = [ct.c_char_p, ct.POINTER(ct.c_int), ct.c_long] + read_fieldlines_input.restype=None + ierr = ct.c_int(0) + read_fieldlines_input(filename.encode('UTF-8'),ct.byref(ierr),len(filename)) + # Get vars + intList=['nr','nphi','nz','npoinc','num_hcp'] + intLen=[1]*len(intList) + realList=['rmin','rmax','zmin','zmax','phimin','phimax','vc_adapt_tol','follow_tol','mu','delta_hc'] + realLen=[1]*len(realList) + realList.extend(['r_start','z_start','phi_start','phi_end','r_hc','z_hc','phi_hc']) + realLen.extend([(maxlines,1)]*7) + realList.extend(['errorfield_amp','errorfield_phase']) + realLen.extend([(20,1)]*2) + charList=['int_type'] + charLen=[(256,1)] + module_name = self.s1+'fieldlines_globals_'+self.s2 + out_data = self.get_module_vars(module_name,None,None,intList,intLen,realList,realLen,charList,charLen,ldefined_size_arrays=True) + return out_data + + def write_fieldlines_input(self,filename,out_dict=None): + """Wrappers writing of the FIELDLINES_INPUT namelist + + This routine wrappers write_fieldlines_input in LIBSTELL + + Parameters + ---------- + filename : str + Path to input file. + out_dict : dict (optional) + Dictionary of items to change. + """ + import ctypes as ct + module_name = self.s1+'fieldlines_globals_'+self.s2 + # Check if we want to update values + if out_dict: + for key in out_dict: + self.set_module_var(module_name,key,out_dict[key]) + module_name = self.s1+'fieldlines_input_mod_'+self.s2 + write_fieldlines_input = getattr(self.libstell,module_name+'_write_fieldlines_namelist_byfile'+self.s3) + write_fieldlines_input.argtypes = [ct.c_char_p, ct.c_long] + write_fieldlines_input.restype=None + write_fieldlines_input(filename.encode('UTF-8'),len(filename)) + + def read_stellopt_input(self,filename): + """Reads a STELLOPT OPTIMUM namelist + + This routine wrappers read_stellopt_input function in + stellopt_input_mod. + + Parameters + ---------- + filename : str + Path to input file. + Returns + ------- + out_data : dict + Dictionary of items. + """ + import ctypes as ct + # A few constants defined in globals + module_name = self.s1+'vsvd0_'+self.s2 + get_constant = getattr(self.libstell,module_name+'_getnigroup'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + nigroup = get_constant() + module_name = self.s1+'vparams_'+self.s2 + get_constant = getattr(self.libstell,module_name+'_getndatafmax'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + ndatafmax = get_constant() + get_constant = getattr(self.libstell,module_name+'_getmpol1d'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + mpol1d = get_constant() + get_constant = getattr(self.libstell,module_name+'_getntord'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + ntord = get_constant() + get_constant = getattr(self.libstell,module_name+'_getnsd'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + nsd = get_constant() + module_name = self.s1+'stellopt_globals_'+self.s2 + get_constant = getattr(self.libstell,module_name+'_getmaxwindsurf'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + maxwindsurf = get_constant() + get_constant = getattr(self.libstell,module_name+'_getbigno'+self.s3) + get_constant.argtypes = None + get_constant.restype=ct.c_int + bigno = get_constant() + # Call the initialization routine + module_name = self.s1+'stellopt_input_mod_'+self.s2 + init_stellopt_input = getattr(self.libstell,module_name+'_init_stellopt_input'+self.s3) + init_stellopt_input.argtypes = None + init_stellopt_input.restype = None + init_stellopt_input() + # We use an added routine as a helper + module_name = self.s1+'stellopt_input_mod_'+self.s2 + read_stellopt_input = getattr(self.libstell,module_name+'_read_stellopt_input'+self.s3) + read_stellopt_input.argtypes = [ct.c_char_p,ct.POINTER(ct.c_int),ct.c_long] + read_stellopt_input.restype = None + istat = ct.c_int(0) + read_stellopt_input(filename.encode('UTF-8'),ct.byref(istat),len(filename)) + if not (istat.value == 0): + return None + # Get vars Globals + module_name = self.s1+'stellopt_globals_'+self.s2 + booList=['lcentered_differences', 'lkeep_mins', 'lrefit', 'lcoil_geom', 'lno_restart', 'ltriangulate'] + booLen=[1]*len(booList) + intList=['cr_strategy', 'npopulation', 'noptimizers', 'mode', 'rho_exp'] + intLen=[1]*len(intList) + realList=['ftol', 'xtol', 'gtol', 'epsfcn', 'factor', 'refit_param'] + realLen=[1]*len(realList) + charList=['opt_type', 'axis_init_option'] + charLen=[(256,1),(256,1)] + global_data = self.get_module_vars(module_name,booList,booLen,intList,intLen,realList,realLen,charList,charLen,ldefined_size_arrays=True) + # Get VARS + module_name = self.s1+'stellopt_vars_'+self.s2 + booList=['lphiedge_opt', 'lcurtor_opt', 'lpscale_opt', \ + 'lbcrit_opt', 'lmix_ece_opt', 'lregcoil_winding_surface_separation_opt',\ + 'lregcoil_current_density_opt', 'lxval_opt', 'lyval_opt', \ + 'lxics_v0_opt','mango_bound_constraints'] + booLen=[1]*len(booList) + booList.extend(['lextcur_opt','laphi_opt', 'lam_opt', \ + 'lac_opt', 'lai_opt','lah_opt', 'lat_opt','lne_opt', \ + 'lte_opt', 'lti_opt','lth_opt', 'lzeff_opt']) + booLen.extend([(nigroup,1),(20,1)]) + booLen.extend([(21,1)]*10) + booList.extend(['lam_s_opt', 'lam_f_opt', 'lac_s_opt', 'lac_f_opt', 'lai_s_opt', 'lai_f_opt',\ + 'lne_f_opt', 'lte_f_opt', 'lti_f_opt', 'lth_f_opt', 'lphi_s_opt', 'lphi_f_opt', \ + 'lzeff_f_opt', 'lemis_xics_f_opt', 'lbootj_f_opt', 'lbeamj_f_opt', 'lah_f_opt', 'lat_f_opt']) + booLen.extend([(ndatafmax,1)]*18) + booList.extend(['laxis_opt','lbound_opt','lrho_opt','lmode_opt','ldeltamn_opt']) + booLen.extend([(ntord+1,1),(2*ntord+1,mpol1d+1),(2*ntord+1,mpol1d+1),(2*ntord+1,mpol1d+1),(2*ntord+1,2*mpol1d+1)]) + booList.extend(['lcoil_spline','lwindsurf']) + booLen.extend([(nigroup,40),(maxwindsurf,1)]) + booList.extend(['lregcoil_rcws_rbound_c_opt','lregcoil_rcws_rbound_s_opt',\ + 'lregcoil_rcws_zbound_c_opt','lregcoil_rcws_zbound_s_opt']) + booLen.extend([(65,65)]*4) + intList=['nfunc_max', 'regcoil_nlambda', 'regcoil_num_field_periods', \ + 'sfincs_min_procs', 'vboot_max_iterations'] + booList.extend(['lrosenbrock_x_opt']) + booLen.extend([(20,1)]) + intLen=[1]*len(intList) + intList.extend(['coil_nctrl']) + intLen.extend([(nigroup,1)]) + realList=['dphiedge_opt', 'dcurtor_opt', 'dbcrit_opt', \ + 'dpscale_opt', 'dmix_ece_opt', 'dxval_opt', 'dyval_opt', \ + 'dregcoil_winding_surface_separation_opt', \ + 'dregcoil_current_density_opt', 'dxics_v0_opt', \ + 'phiedge_min', 'curtor_min', 'bcrit_min', \ + 'pscale_min', 'mix_ece_min', 'xval_min', 'yval_min', + 'regcoil_winding_surface_separation_min', \ + 'regcoil_current_density_min', 'xics_v0_min', \ + 'phiedge_max', 'curtor_max', 'bcrit_max', \ + 'pscale_max', 'mix_ece_max', 'xval_max', 'yval_max', \ + 'regcoil_winding_surface_separation_max', \ + 'regcoil_current_density_max', 'xics_v0_max', \ + 'mix_ece', 'xval', 'yval', 'xics_v0', \ + 'regcoil_winding_surface_separation', \ + 'regcoil_current_density','vboot_tolerance'] + realLen=[1]*len(realList) + realList.extend(['dextcur_opt','extcur_min','extcur_max']) + realLen.extend([(nigroup,1)]*3) + realList.extend(['daphi_opt', 'aphi_min', 'aphi_max']) + realLen.extend([(20,1)]*3) + realList.extend(['dam_opt', 'dac_opt', 'dai_opt', 'dah_opt', 'dat_opt','dte_opt', 'dne_opt', 'dti_opt', 'dth_opt','dzeff_opt', \ + 'am_min', 'ac_min', 'ai_min', 'ah_min', 'at_min', 'am_max', 'ac_max', 'ai_max', 'ah_max', 'at_max',\ + 'te_min', 'ne_min', 'ti_min', 'th_min', 'te_max', 'ne_max', 'ti_max', 'th_max', 'zeff_max', 'zeff_min']) + realLen.extend([(21,1)]*30) + realList.extend(['bnfou']) + realLen.extend([(25,41)]) + realList.extend(['dregcoil_rcws_rbound_c_opt','dregcoil_rcws_rbound_s_opt','dregcoil_rcws_zbound_c_opt','dregcoil_rcws_zbound_s_opt']) + realLen.extend([(65,65)]*4) + realList.extend(['te_opt','ti_opt','ne_opt','th_opt','zeff_opt']) + realLen.extend([(21,1)]*5) + realList.extend(['ne_aux_s', 'te_aux_s', 'ti_aux_s', 'th_aux_s', 'zeff_aux_s', \ + 'phi_aux_s', 'beamj_aux_s', 'bootj_aux_s', 'sfincs_s', 'emis_xics_s',\ + 'ne_aux_f', 'te_aux_f', 'ti_aux_f', 'th_aux_f', 'zeff_aux_f', \ + 'phi_aux_f', 'beamj_aux_f', 'bootj_aux_f', 'emis_xics_f']) + realLen.extend([(ndatafmax,1)]*19) + realList.extend(['dam_s_opt', 'dam_f_opt', 'dac_s_opt', 'dac_f_opt', 'dai_s_opt', 'dai_f_opt', 'dphi_s_opt', 'dphi_f_opt', \ + 'dne_f_opt', 'dte_f_opt', 'dti_f_opt', 'dth_f_opt', 'dzeff_f_opt', 'dbeamj_f_opt', 'dbootj_f_opt','dat_f_opt', \ + 'dah_f_opt', 'demis_xics_f_opt']) + realLen.extend([(ndatafmax,1)]*18) + realList.extend(['am_f_min', 'ac_f_min', 'ai_f_min', 'phi_f_min', 'ne_f_min', \ + 'te_f_min', 'ti_f_min', 'th_f_min', 'zeff_f_min', 'emis_xics_f_min', \ + 'beamj_f_min', 'bootj_f_min', 'ah_f_min', 'at_f_min']) + realLen.extend([(ndatafmax,1)]*14) + realList.extend(['am_f_max', 'ac_f_max', 'ai_f_max', 'phi_f_max', 'ne_f_max', \ + 'te_f_max', 'ti_f_max', 'th_f_max', 'zeff_f_max', 'emis_xics_f_max', \ + 'beamj_f_max', 'bootj_f_max', 'ah_f_max', 'at_f_max']) + realLen.extend([(ndatafmax,1)]*14) + realList.extend(['daxis_opt','raxis_min','raxis_max','zaxis_min','zaxis_max']) + realLen.extend([(ntord+1,1)]*5) + realList.extend(['rhobc', 'modemn', 'dbound_opt', 'drho_opt', 'rbc_min', \ + 'rbc_max', 'zbs_min', 'zbs_max', 'bound_min', 'bound_max', 'zbc_min',\ + 'zbc_max', 'rbs_min', 'rbs_max']) + realLen.extend([(2*ntord+1,1+mpol1d)]*14) + realList.extend(['deltamn','ddeltamn_opt','delta_min','delta_max']) + realLen.extend([(2*ntord+1,2*mpol1d+1)]*4) + realList.extend(['coil_splinesx','coil_splinesy','coil_splinesz']) + realLen.extend([(nigroup,44)]*3) + realList.extend(['coil_splinefx','coil_splinefy','coil_splinefz','dcoil_spline', \ + 'coil_splinefx_min','coil_splinefy_min','coil_splinefz_min','coil_splinefx_max','coil_splinefy_max','coil_splinefz_max']) + realLen.extend([(nigroup,40)]*10) + realList.extend(['regcoil_rcws_rbound_c', 'regcoil_rcws_rbound_s','regcoil_rcws_rbound_c_min',\ + 'regcoil_rcws_rbound_s_min','regcoil_rcws_rbound_c_max', 'regcoil_rcws_rbound_s_max',\ + 'regcoil_rcws_zbound_c', 'regcoil_rcws_zbound_s','regcoil_rcws_zbound_c_min', \ + 'regcoil_rcws_zbound_s_min','regcoil_rcws_zbound_c_max', 'regcoil_rcws_zbound_s_max']) + realLen.extend([(65,65)]*12) + realList.extend(['drosenbrock_x_opt','rosenbrock_x','rosenbrock_x_min','rosenbrock_x_max']) + realLen.extend([(20,1)]*4) + charList=['sfincs_er_option', 'equil_type', 'te_type', 'ne_type', \ + 'ti_type', 'th_type', 'beamj_type','bootj_type','zeff_type','emis_xics_type',\ + 'fixedcoilname','regcoil_nescin_filename','bootcalc_type','phi_type','coil_type'] + charLen=[(256,1),(256,1),(256,1),(256,1),(256,1),(256,1),(256,1),\ + (256,1),(256,1),(256,1),(256,1),(256,1),(256,1),(256,1),(nigroup,1)] + var_data = self.get_module_vars(module_name,booList,booLen,intList,intLen,realList,realLen,charList,charLen,ldefined_size_arrays=True) + # Get target + module_name = self.s1+'stellopt_targets_'+self.s2 + booList=['lneed_magdiag', 'lglobal_txport'] + booLen=[1]*len(booList) + booList.extend(['lbooz','lmse_extcur']) + booLen.extend([(nsd,1),(512,1)]) + intList=['mboz', 'nboz', 'numjstar', 'nz_txport', 'nalpha_txport', 'nruns_dkes',\ + 'nu_orbit', 'nv_orbit', 'np_orbit', 'mlmnb_kink', 'ivac_kink', 'mmaxdf_kink', \ + 'nmaxdf_kink', 'nra_ece', 'nphi_ece', 'numws', 'nu_bnorm', 'nv_bnorm', \ + 'npts_biot', 'npts_clen', 'npts_torx', 'npts_curv', 'npts_csep', 'npts_cself', \ + 'npts_crect', 'npts_cpoly'] + intLen=[1]*len(intList) + intList.extend(['mlmns_kink', 'lssl_kink', 'lssd_kink','nj_kink','nk_kink']) + intLen.extend([(16,1)]*5) + realList=['target_phiedge', 'sigma_phiedge', 'target_curtor', 'sigma_curtor', 'target_curtor_max', 'sigma_curtor_max', \ + 'target_volume', 'sigma_volume', 'target_beta', 'sigma_beta', 'target_betator', 'sigma_betator', \ + 'target_betapol', 'sigma_betapol', 'target_wp', 'sigma_wp', 'target_aspect', 'sigma_aspect', \ + 'target_rbtor', 'sigma_rbtor', 'target_r0', 'sigma_r0', 'target_z0', 'sigma_z0', \ + 'target_b0', 'sigma_b0', 'target_aspect_max', 'sigma_aspect_max', 'width_aspect_max', 'target_gradp_max', \ + 'sigma_gradp_max', 'width_gradp_max', 'target_pmin', 'sigma_pmin', 'width_pmin', 'target_curvature', \ + 'sigma_curvature', 'target_kappa', 'sigma_kappa', 'phi_kappa', 'target_kappa_box', 'sigma_kappa_box', \ + 'phi_kappa_box', 'target_kappa_avg', 'sigma_kappa_avg', 'target_x', 'sigma_x' ,'target_y', \ + 'sigma_y', 'qm_ratio', 'cutoff_te_line', 'target_vessel', 'sigma_vessel', 'alpha_start_txport', \ + 'alpha_end_txport', 'nu_dkes_erdiff', 'ep_dkes_erdiff', 'em_dkes_erdiff', 'mass_orbit', 'z_orbit', \ + 'target_coil_bnorm', 'sigma_coil_bnorm', 'target_regcoil_winding_surface_separation', 'sigma_regcoil_winding_surface_separation',\ + 'target_regcoil_current_density', 'sigma_regcoil_current_density', 'target_curvature_p2', 'sigma_curvature_p2', \ + 'target_coilsep', 'sigma_coilsep', 'coilrectpfw'] + realLen=[1]*len(realList) + realList.extend(['target_rosenbrock_f','sigma_rosenbrock_f']) + realLen.extend([(20,1),(20,1)]) + realList.extend(['target_press', 'sigma_press', 'r_press', 'z_press', 'phi_press', \ + 's_press', 'target_pressprime', 'sigma_pressprime', 'r_pressprime', 'z_pressprime', \ + 'phi_pressprime', 's_pressprime', 'target_te', 'sigma_te', 'r_te', \ + 'z_te', 'phi_te', 's_te', 'target_ne', 'sigma_ne', \ + 'r_ne', 'z_ne', 'phi_ne', 's_ne', 'target_ne_line', \ + 'sigma_ne_line', 'r0_ne_line', 'phi0_ne_line', 'z0_ne_line', 'r1_ne_line', \ + 'phi1_ne_line', 'z1_ne_line', 'target_te_line', 'sigma_te_line', 'r0_te_line', \ + 'phi0_te_line', 'z0_te_line', 'r1_te_line', 'phi1_te_line', 'z1_te_line', \ + 'target_ti_line','sigma_ti_line', 'r0_ti_line', 'phi0_ti_line', 'z0_ti_line', \ + 'r1_ti_line', 'phi1_ti_line', 'z1_ti_line', 'target_zeff_line', 'sigma_zeff_line', \ + 'r0_zeff_line', 'phi0_zeff_line', 'z0_zeff_line', 'r1_zeff_line', 'phi1_zeff_line', \ + 'z1_zeff_line', 'target_visbrem_line', 'sigma_visbrem_line', 'lambda_visbrem_line', 'r0_visbrem_line', \ + 'phi0_visbrem_line', 'z0_visbrem_line', 'r1_visbrem_line', 'phi1_visbrem_line', 'z1_visbrem_line', \ + 'calib_visbrem_line', 'target_xics', 'sigma_xics', 'target_xics_bright', 'sigma_xics_bright', \ + 'target_xics_w3', 'sigma_xics_w3', 'target_xics_v', 'sigma_xics_v', 'r0_xics', \ + 'phi0_xics', 'z0_xics', 'r1_xics', 'phi1_xics', 'z1_xics', \ + 'target_faraday', 'sigma_faraday', 'r0_faraday', 'phi0_faraday', 'z0_faraday', \ + 'r1_faraday', 'phi1_faraday', 'z1_faraday', 'target_sxr','sigma_sxr', \ + 'r0_sxr', 'phi0_sxr', 'z0_sxr', 'r1_sxr', 'phi1_sxr', \ + 'z1_sxr', 'target_ti', 'sigma_ti', 'r_ti', 'z_ti', \ + 'phi_ti', 's_ti', 'target_vphi', 'sigma_vphi', 'r_vphi', \ + 'z_vphi', 'phi_vphi', 's_vphi', 'target_iota', 'sigma_iota', \ + 'r_iota', 'z_iota', 'phi_iota', 's_iota', 'target_vaciota', \ + 'sigma_vaciota', 'r_vaciota', 'z_vaciota', 'phi_vaciota', 's_vaciota', \ + 'target_mse', 'sigma_mse', 'r_mse', 'z_mse', 'phi_mse', \ + 's_mse', 'a1_mse', 'a2_mse', 'a3_mse', 'a4_mse', \ + 'a5_mse', 'a6_mse', 'a7_mse', 'vac_mse', 'target_segrog', \ + 'sigma_segrog', 'target_fluxloop', 'sigma_fluxloop', 'target_extcur', 'sigma_extcur', \ + 'balloon_theta', 'balloon_zeta', 'e_dkes', 'nu_dkes', 'nup_dkes_alpha', \ + 'num_dkes_alpha', 'ep_dkes_alpha', 'em_dkes_alpha']) + realLen.extend([(512,1)]*148) + realList.extend(['target_bmin', 'sigma_bmin', 'target_bmax', 'sigma_bmax', 'target_jcurv', \ + 'sigma_jcurv', 'target_jdotb', 'sigma_jdotb', 'target_balloon', 'sigma_balloon', \ + 'target_bootstrap', 'sigma_bootstrap', 'target_neo', 'sigma_neo', 'target_jstar', \ + 'sigma_jstar', 'target_magwell', 'sigma_magwell', 'target_helicity', 'sigma_helicity', \ + 'target_helicity_old', 'sigma_helicity_old', 'target_resjac', 'sigma_resjac', 'xm_resjac', \ + 'xn_resjac', 'target_txport', 'sigma_txport', 's_txport', 'target_dkes', \ + 'sigma_dkes', 'target_dkes_erdiff', 'sigma_dkes_erdiff', 'target_dkes_alpha', 'sigma_dkes_alpha', \ + 'target_gamma_c', 'sigma_gamma_c', 'target_orbit', 'sigma_orbit']) + realLen.extend([(nsd,1)]*39) + realList.extend(['target_bprobe', 'sigma_bprobe']) + realLen.extend([(2048,1)]*2) + realList.extend(['target_separatrix', 'sigma_separatrix', 'r_separatrix', 'z_separatrix', 'phi_separatrix', \ + 'target_limiter', 'sigma_limiter', 'r_limiter', 'z_limiter', 'phi_limiter']) + realLen.extend([(361,361)]*10) + realList.extend(['vll_orbit', 'mu_orbit', 'vperp_orbit']) + realLen.extend([(16384,1)]*3) + realList.extend(['target_kink', 'sigma_kink']) + realLen.extend([(16,1)]*2) + realList.extend(['target_ece', 'sigma_ece', 'freq_ece']) + realLen.extend([(16,512)]*3) + realList.extend(['antennaposition_ece', 'targetposition_ece', 'rbeam_ece', 'rfocus_ece']) + realLen.extend([(16,3)]*4) + realList.extend(['target_regcoil_chi2_b', 'sigma_regcoil_chi2_b']) + realLen.extend([(16900,1)]*4) + realList.extend(['target_coillen', 'sigma_coillen', 'target_coilsegvar', 'sigma_coilsegvar', 'target_coilcrv', \ + 'sigma_coilcrv', 'target_coilself', 'sigma_coilself', 'target_coiltorvar', 'sigma_coiltorvar', \ + 'thwt_coiltorvar', 'coilrectvmin', 'coilrectvmax', 'coilrectduu', 'coilrectdul', \ + 'target_coilrect', 'sigma_coilrect', 'target_coilpoly', 'sigma_coilpoly']) + realLen.extend([(nigroup,1)]*19) + realList.extend(['kopolyu', 'kopolyv']) + realLen.extend([(128,16)]*2) + charList=['magdiag_coil', 'vessel_string', 'txport_proxy', 'vessel_ece', 'mirror_ece', 'targettype_ece', 'antennatype_ece'] + charLen=[(256,1)]*7 + target_data = self.get_module_vars(module_name,booList,booLen,intList,intLen,realList,realLen,charList,charLen,ldefined_size_arrays=True) + return global_data, var_data, target_data + + def write_stellopt_input(self,filename,global_dict=None,var_dict=None,target_dict=None): + """Wrappers writing of the STELLOPT OPTIMUM namelist + + This routine wrappers write_stellopt_input in LIBSTELL + + Parameters + ---------- + filename : str + Path to input file. + out_dict : dict (optional) + Dictionary of items to change. + """ + import ctypes as ct + # Global module + if global_dict: + module_name = self.s1+'stellopt_globals_'+self.s2 + for key in global_dict: + self.set_module_var(module_name,key,global_dict[key]) + # var module + if var_dict: + module_name = self.s1+'stellopt_vars_'+self.s2 + for key in var_dict: + self.set_module_var(module_name,key,var_dict[key]) + # target module + if target_dict: + module_name = self.s1+'stellopt_targets_'+self.s2 + for key in target_dict: + self.set_module_var(module_name,key,target_dict[key]) + # Now write namelist + module_name = self.s1+'stellopt_input_mod_'+self.s2 + write_stellopt_input = getattr(self.libstell,module_name+'_write_optimum_namelist_byfile'+self.s3) + write_stellopt_input.argtypes = [ct.c_char_p, ct.c_long] + write_stellopt_input.restype=None + write_stellopt_input(filename.encode('UTF-8'),len(filename)) + + def read_wout(self,file): + """Reads a wout file and returns a dictionary + + This routine wrappers read_wout in LIBSTELL and returns + a dictionary of values + + Parameters + ---------- + file : str + Path to wout file. + Returns + ---------- + vars : dict + Dictionary of module variables + """ + import ctypes as ct + module_name = self.s1+'read_wout_mod_'+self.s2 + read_wout = getattr(self.libstell,module_name+'_readw_and_open'+self.s3) + read_wout.argtypes=[ct.c_char_p, ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.c_long] + read_wout.restype=None + ierr = ct.c_int(0) + iopen = ct.c_int(0) + read_wout(file.encode('UTF-8'), ct.byref(ierr), ct.byref(iopen), len(file)) + if not (ierr.value == 0): + return None + # Setup Arrays + out_data={} + # Get Scalars + booList = ['lasym','lthreed','lwout_opened'] + booLen = [1]*len(booList) + intList = ['ns','nfp','mpol','ntor','mnmax','mnmax_nyq','iasym','ierr_vmec'] + intLen = [1]*len(intList) + realList = ['wb','wp','gamma','pfac','rmax_surf','rmin_surf','zmax_surf',\ + 'aspect','betatot','betapol','betator','betaxis','b0','version_',\ + 'ionlarmor','volavgb','fsql','fsqr','fsqz','ftolv','aminor','rmajor',\ + 'volume','rbtor','rbtor0','itor','machsq'] + realLen = [1]*len(realList) + scalar_data = self.get_module_vars(module_name,booList,booLen,intList,intLen,realList,realLen) + ns = scalar_data['ns'] + # Get 1D Real Arrays + realList = ['iotas','iotaf','presf','phipf','chipf','chi','phi','mass',\ + 'pres','beta_vol','phip','buco','bvco','vp','overr','jcuru',\ + 'jcurv','specw','jdotb','dmerc','dwell','dcurr','dgeod','equif'] + realLen = [(scalar_data['ns'],1)]*len(realList) + realList.extend(['xm','xn','xm_nyq','xn_nyq']) + realLen.extend([(scalar_data['mnmax'],1)]*2) + realLen.extend([(scalar_data['mnmax_nyq'],1)]*2) + # Add 2D Arrays + realList.extend(['rmnc','zmns','lmns']) + realLen.extend([(scalar_data['ns'],scalar_data['mnmax'])]*3) + realList.extend([ 'bmnc','gmnc','bsupumnc','bsupvmnc',\ + 'bsubsmns','bsubumnc','bsubvmnc',\ + 'currumnc','currvmnc']) + realLen.extend([(scalar_data['ns'],scalar_data['mnmax_nyq'])]*9) + if scalar_data['iasym']: + realList.extend(['rmns','zmnc','lmnc']) + realLen.extend([(scalar_data['ns'],scalar_data['mnmax'])]*3) + realList.extend([ 'bmns','gmns','bsupumns','bsupvmns',\ + 'bsubsmnc','bsubumns','bsubvmns',\ + 'currumns','currvmns']) + realLen.extend([(scalar_data['ns'],scalar_data['mnmax_nyq'])]*9) + array_data = self.get_module_vars(module_name,realVar=realList,realLen=realLen) + # Try reading strings + charVar=['mgrid_file','input_extension','pmass_type','pcurr_type','piota_type'] + charLen=[(200,1),(100,1),(20,1),(20,1),(20,1)] + string_data = self.get_module_vars(module_name,charVar=charVar,charLen=charLen,ldefined_size_arrays=True) + # Return + return scalar_data | array_data | string_data + + def read_boozer(self,file): + """Reads a boozmn file and returns a dictionary + + This routine wrappers read_boozer in LIBSTELL and returns + a dictionary of values + + Parameters + ---------- + file : str + Path to wout file. + Returns + ---------- + vars : dict + Dictionary of module variables + """ + import ctypes as ct + module_name = self.s1+'read_boozer_mod_'+self.s2 + read_boozer = getattr(self.libstell,module_name+'_read_boozer_file'+self.s3) + read_boozer.argtypes=[ct.c_char_p, ct.POINTER(ct.c_int), ct.POINTER(ct.c_int), ct.c_long] + read_boozer.restype=None + ierr = ct.c_int(0) + iopen = ct.c_int(0) + read_boozer(file.encode('UTF-8'), ct.byref(ierr), ct.byref(iopen), len(file)) + if not (ierr.value == 0): + return None + # Setup Arrays + out_data={} + # Get Scalars + booList = ['lasym_b'] + booLen = [1]*len(booList) + intList = ['mnboz_b', 'mboz_b', 'nboz_b', 'nfp_b', 'ns_b'] + intLen = [1]*len(intList) + realList = ['aspect_b', 'rmax_b', 'rmin_b', 'betaxis_b'] + realLen = [1]*len(realList) + scalar_data = self.get_module_vars(module_name,booList,booLen,intList,intLen,realList,realLen) + ns = scalar_data['ns_b'] + mnmax = scalar_data['mnboz_b'] + # Get 1D Real Arrays + intList = ['idx_b', 'ixm_b', 'ixn_b'] + intLen = [(ns,1),(mnmax,1),(mnmax,1)] + realList = ['iota_b','pres_b','phip_b','phi_b','beta_b','buco_b','bvco_b'] + realLen = [(ns,1)]*len(realList) + # Add 2D Arrays + realList.extend(['bmnc_b','rmnc_b','zmns_b','pmns_b', 'gmnc_b']) + realLen.extend([(ns,mnmax)]*5) + if scalar_data['lasym_b']: + realList.extend(['bmns_b', 'rmns_b', 'zmnc_b', 'pmnc_b', 'gmns_b']) + realLen.extend([(ns,mnmax)]*5) + array_data = self.get_module_vars(module_name,intVar=intList,intLen=intLen,realVar=realList,realLen=realLen) + # Return + return scalar_data | array_data + + def get_module_vars(self,modName,booVar=None,booLen=None,\ + intVar=None,intLen=None,realVar=None,realLen=None,\ + charVar=None,charLen=None,\ + ldefined_size_arrays=False): + """Reads module variables into a python dictionary + + This rountine helps to streamline reading of module variables + into a python dictionary. The variable lists (booVar, intVar, + and realVar) are lists of strings referencing the variable names. + The length lists (booLen,intLen,realLen) are a list of tupules + defining the size of the variable. + + Parameters + ---------- + modName : str + Name of the module eg 'read_wout_mod' + booVar : list (optional) + List of strings referencing boolean variables to pull + booLen : list (optional) + List of tuples defining array size + intVar : list (optional) + List of strings referencing integer variables to pull + intLen : list (optional) + List of tuples defining array size + realVar : list (optional) + List of strings referencing integer variables to pull + realLen : list (optional) + List of tuples defining array size + ldefined_size_arrays : logical (optional) + Set to true when reading a predefined size arrays temp(0:20) + Returns + ------- + out_data : dict + Dictionary of module variables + """ + import ctypes as ct + import numpy.ctypeslib as npct + from math import prod + out_data={} + # Booleans + if booVar: + ftemp = ct.POINTER(ct.c_bool) + for i,temp in enumerate(booVar): + #print(temp,booLen[i]) + if booLen[i]==1: + out_data[temp]=ct.c_bool.in_dll(self.libstell,modName+'_'+temp+self.s3).value + else: + if ldefined_size_arrays : ftemp=ct.c_bool*prod(booLen[i]) + out_data[temp]=npct.as_array(ftemp.in_dll(self.libstell,modName+'_'+temp+self.s3),booLen[i]) + # Integers + if intVar: + ftemp = ct.POINTER(ct.c_int) + for i,temp in enumerate(intVar): + #print(temp,intLen[i]) + if intLen[i]==1: + out_data[temp]=ct.c_int.in_dll(self.libstell,modName+'_'+temp+self.s3).value + else: + if ldefined_size_arrays : ftemp=ct.c_int*prod(intLen[i]) + out_data[temp]=npct.as_array(ftemp.in_dll(self.libstell,modName+'_'+temp+self.s3),intLen[i]) + # Reals + if realVar: + ftemp = ct.POINTER(ct.c_double) + for i,temp in enumerate(realVar): + #print(temp,realLen[i]) + if realLen[i]==1: + out_data[temp]=ct.c_double.in_dll(self.libstell,modName+'_'+temp+self.s3).value + else: + if ldefined_size_arrays : ftemp=ct.c_double*prod(realLen[i]) + out_data[temp]=npct.as_array(ftemp.in_dll(self.libstell,modName+'_'+temp+self.s3),realLen[i]) + # Characters + if charVar: + ftemp = ct.POINTER(ct.c_char) + for i,temp in enumerate(charVar): + #print(temp,charLen[i]) + if charLen[i]==1: + out_data[temp]=ct.c_char.in_dll(self.libstell,modName+'_'+temp+self.s3).value.decode('UTF-8') + else: + if ldefined_size_arrays : ftemp=ct.c_char*prod(charLen[i]) + out_data[temp]=ftemp.in_dll(self.libstell,modName+'_'+temp+self.s3).value.decode('UTF-8') + return out_data + + def set_module_var(self,modName,var,val): + import ctypes as ct + import numpy as np + import numpy.ctypeslib as npct + if type(val) == bool: + f = ct.c_bool + elif type(val) == int: + f = ct.c_int + elif type(val) == float: + f = ct.c_double + elif type(val) == str: + n = len(val) + f = ct.c_char*n + elif type(val) in (np.ndarray,list): + if type(val[0]) == bool: + tt = ct.c_bool + elif type(val[0]) == np.bool_: + tt = ct.c_bool + elif type(val[0]) == np.int32: + tt = ct.c_int + elif type(val[0]) == np.int64: + tt = ct.c_int + elif type(val[0]) == np.float64: + tt = ct.c_double + else: + print(f' Unrecognized type ({var}):',type(val[0])) + return + n = val.ndim + f = tt*val.size + elif type(val) == type(self): + return # Do nothing + else: + print(f' Unrecognized type ({var}):',type(val)) + return + temp=f.in_dll(self.libstell,modName+'_'+var+self.s3) + if type(val) == np.ndarray: + if n==1: + for i,col in enumerate(val): + temp[i] = val[i] + elif type(val) == str: + temp.value = val.encode('UTF-8') + else: + temp.value = val + return + + def pcurr(self,s): + """Wrapper to the PCURR function + + This routine wrappers the PCURR function which + returns either the I'(s) or I(s) depending on the + choice of pcurr_type. + + Parameters + ---------- + s : real + Value of normalized toroidal flux. + Returns + ------- + val : real + Value of I'(s) or I(s) + """ + import ctypes as ct + # Load Libraries + pcurr_func = getattr(self.libstell,'pcurr_') + pcurr_func.argtypes = [ct.POINTER(ct.c_double)] + pcurr_func.restype=ct.c_double + s_temp = ct.c_double(s) + val = pcurr_func(ct.byref(s_temp)) + return val + + def piota(self,s): + """Wrapper to the PIOTA function + + This routine wrappers the PIOTA function which + returns the iota(s) rotational transform. + + Parameters + ---------- + s : real + Value of normalized toroidal flux + Returns + ------- + val : real + Value of iota(s) + """ + import ctypes as ct + # Load Libraries + pcurr_func = getattr(self.libstell,'piota_') + pcurr_func.argtypes = [ct.POINTER(ct.c_double)] + pcurr_func.restype=ct.c_double + s_temp = ct.c_double(s) + val = pcurr_func(ct.byref(s_temp)) + return val + + def pmass(self,s): + """Wrapper to the PMASS function + + This routine wrappers the PMASS function which + returns the mass(s) pressure function. + + Parameters + ---------- + s : real + Value of normalized toroidal flux + Returns + ------- + val : real + Value of mass(s) + """ + import ctypes as ct + # Load Libraries + pcurr_func = getattr(self.libstell,'pmass_') + pcurr_func.argtypes = [ct.POINTER(ct.c_double)] + pcurr_func.restype=ct.c_double + s_temp = ct.c_double(s) + val = pcurr_func(ct.byref(s_temp)) + return val + + def parse_coils_file(self,filename): + """Parses a coils file + + This routine wrappers parsecoils in LIBSTELL biotsavart and returns + a dictionary of values + + Parameters + ---------- + file : str + Path to coils file. + Returns + ---------- + vars : dict + Dictionary of module variables + """ + import ctypes as ct + module_name = self.s1+'biotsavart_'+self.s2 + parse_coils_file = getattr(self.libstell,module_name+'_parse_coils_file'+self.s3) + parse_coils_file.argtypes=[ct.c_char_p, ct.c_bool, ct.c_long] + parse_coils_file.restype=None + lgrps = ct.c_bool(False) + parse_coils_file(file.encode('UTF-8'), ct.byref(lgrps), len(file)) + if not (ierr.value == 0): + return None + +class FourierRep(): + def __init__(self, parent=None): + self.test = None + + def cfunct(self,theta,phi,fmnc,xm,xn): + """Cos transformation + + This routine performs the cosine transformation of the + kernel (m*theta+n*phi). + + Parameters + ---------- + theta : ndarray + Poloidal grid in radians. + phi : ndarray + Toroidal grid in radians. + fmnc : ndarray + Array to transform (radial,fourier) + xm : ndarray + Poloidal harmonic array. + xn : ndarray + Toroidal harmonic array. + Returns + ---------- + f : ndarray + Fourier transformed quantity (radial,poloidal,toroidal) + """ + import numpy as np + f=0 + (ns,mn)=fmnc.shape + lt = len(theta) + lz = len(phi) + mt=np.matmul(xm,theta.T) + nz=np.matmul(xn,phi.T) + cosmt=np.cos(mt) + sinmt=np.sin(mt) + cosnz=np.cos(nz) + sinnz=np.sin(nz) + f = np.zeros((ns,lt,lz)) + fmn = np.ndarray((mn,lt)) + for k in range(ns): + fmn = np.broadcast_to(fmnc[k,:],(lt,mn)).T + f[k,:,:]=np.matmul((fmn*cosmt).T, cosnz)-np.matmul((fmn*sinmt).T, sinnz) + return f + + def sfunct(self,theta,phi,fmnc,xm,xn): + """Sine transformation + + This routine performs the sine transformation of the + kernel (m*theta+n*phi). + + Parameters + ---------- + theta : ndarray + Poloidal grid in radians. + phi : ndarray + Toroidal grid in radians. + fmnc : ndarray + Array to transform (radial,fourier) + xm : ndarray + Poloidal harmonic array. + xn : ndarray + Toroidal harmonic array. + Returns + ---------- + f : ndarray + Fourier transformed quantity (radial,poloidal,toroidal) + """ + import numpy as np + f=0 + (ns,mn)=fmnc.shape + lt = len(theta) + lz = len(phi) + mt=np.matmul(xm,theta.T) + nz=np.matmul(xn,phi.T) + cosmt=np.cos(mt) + sinmt=np.sin(mt) + cosnz=np.cos(nz) + sinnz=np.sin(nz) + f = np.zeros((ns,lt,lz)) + fmn = np.ndarray((mn,lt)) + for k in range(ns): + fmn = np.broadcast_to(fmnc[k,:],(lt,mn)).T + f[k,:,:]=np.matmul((fmn*sinmt).T, cosnz)+np.matmul((fmn*cosmt).T, sinnz) + return f + + def isotoro(self,r,z,zeta,svals,*args,**kwargs): + import numpy as np + import matplotlib.pyplot as pyplot + import mpl_toolkits.mplot3d as mplot3d + import math as math + import matplotlib.tri as mtri + #from mayavi import mlab + nr = np.size(svals) + if (nr == 1): + s= [svals] + nr = 1 + else: + s=svals + nt = np.size(r,1) + nz = np.size(r,2) + vertex = np.zeros((nt*nz,3,nr)) + for k in range(0,nr): + ivertex = 0 + ifaces = 0 + for j in range(0,nz): + for i in range(0,nt): + vertex[ivertex,0,k]=r[s[k],i,j]*math.cos(zeta[j]) + vertex[ivertex,1,k]=r[s[k],i,j]*math.sin(zeta[j]) + vertex[ivertex,2,k]=z[s[k],i,j] + ivertex = ivertex + 1 + u = np.linspace(0, 1, endpoint=True, num=nt) + v = np.linspace(0, 1, endpoint=True, num=nz) + u, v = np.meshgrid(u, v) + u, v = u.flatten(), v.flatten() + tri = mtri.Triangulation(u, v) + test=len(kwargs) + fig=kwargs.pop('fig',pyplot.figure()) + h=kwargs.pop('axes',fig.add_subplot(111,projection='3d')) + for k in range(0,nr): + if (len(args)==0): + tsurf=h.plot_trisurf(vertex[:,0,k],vertex[:,1,k],vertex[:,2,k], triangles=tri.triangles,color='red',shade='yes',linewidth=0.0,alpha=1) + #tsurf=mlab.triangular_mesh(vertex[:,0,k],vertex[:,1,k],vertex[:,2,k], tri.triangless) + else: + # Matplotlib way (SLOW) + vals = args[0][s[k],:,:].T.flatten() + colors = np.mean(vals[tri.triangles], axis=1) + tsurf=h.plot_trisurf(vertex[:,0,k],vertex[:,1,k],vertex[:,2,k], triangles=tri.triangles,cmap='jet',shade=False,linewidth=0.0,alpha=1) + tsurf.set_array(colors) + tsurf.autoscale() + #MAYAVI Way (need to figure out how to embed) + #h = mlab.figure() + #vals = args[0][s[k],:,:].T.flatten() + #tsurf=mlab.triangular_mesh(vertex[:,0,k],vertex[:,1,k],vertex[:,2,k], tri.triangles, scalars=vals, colormap='jet',figure=h) + #print(type(tsurf)) + if (test==0): + pyplot.show() + return h + + def blenderSurface(self,r,z,phi,surface=None): + """Generates the lists Blender needs to render a flux surface + + This routine generates the verticies and faces lists which + Blender needs to render a surface. It assumes + that datapoints are not repeated in the theta or + phi direction, but those coordinates are periodic. + + Parameters + ---------- + r : ndarray + Ordered list of R verticies [m] (ns,nu,nv) + z : ndarray + Ordered list of Z verticies [m] (ns,nu,nv) + phi : ndarray + Ordered list of phi coordiantes [rad] (nv) + surface : int (optional) + Surface to generate in ns (default: outermost) + + Returns + ---------- + vertices : list + List of tuples defining verticies + faces: list + List of tubles defining faces + """ + import numpy as np + # Generate volumetric coil rendering + vertices = [] + faces = [] + if surface: + k = surface + else: + k = r.shape[0]-1 + nu = np.size(r,1) + nv = np.size(r,2) + # Loop and construct + for v in range(nv): + for u in range(nu): + x = r[k,u,v] * np.cos(phi[v]) + y = r[k,u,v] * np.sin(phi[v]) + vertices.append((x,y,z[k,u,v])) + # Now do faces + i1 = u + v * nu + # Catch special case #1 + if u == nu-1: + i2 = i1 + nu + i3 = i1 + 1 + i4 = i1 - nu + 1 + if v == nv - 1: + i2 = u + i3 = 0 + elif u < nu-1: + i2 = i1 + nu + i3 = i1 + nu +1 + i4 = i1 + 1 + if v == nv -1: + i2 = u + i3 = u + 1 + faces.append((i1,i2,i4)) + faces.append((i2,i3,i4)) + return vertices,faces + + +# Main routine +if __name__=="__main__": + import sys + temp = LIBSTELL() + val=temp.read_indata('input.ORBITS') + temp.set_module_var('vmec_input','mpol',12) + temp.set_module_var('vmec_input','niter_array',[1,2,3,4,5]) + temp.write_indata('input.test') + #wout=temp.read_wout('wout_W7X_AIM_n04_e30_i15_8SH2_slow.nc') + sys.exit(0) \ No newline at end of file diff --git a/pySTEL/libstell/stellopt.py b/pySTEL/libstell/stellopt.py index db6ef2acf..3063ea3ff 100644 --- a/pySTEL/libstell/stellopt.py +++ b/pySTEL/libstell/stellopt.py @@ -1,397 +1,288 @@ -def read_stellopt_namelist(iunit,istat): - import os, sys - import numpy.ctypeslib as npct - import numpy as np - # Load Libraries - # Setup Arrays - stellopt_namelist={} - # Will delete this just using for testing - stellopt_namelist['NFUNC_MAX'] = 5000 - stellopt_namelist['OPT_TYPE'] = 'LMDIF' - stellopt_namelist['EQUIL_TYPE'] = 'VMEC2000' - stellopt_namelist['FTOL'] = 1.0E-6 - stellopt_namelist['XTOL'] = 1.0E-6 - stellopt_namelist['GTOL'] = 1.0E-30 - stellopt_namelist['EPSFCN'] = 1.0E-4 - stellopt_namelist['MODE'] = 1 - stellopt_namelist['FACTOR'] = 100 - stellopt_namelist['CR_STRATEGY'] = 0 - stellopt_namelist['NPOPULATION'] = -1 - stellopt_namelist['NOPTIMIZERS'] = -1 - # Vars - for name in ['PHIEDGE','PRES_SCALE','CURTOR']: - stellopt_namelist['L'+name+'_OPT'] = 0 - stellopt_namelist['D'+name+'_OPT'] = 1.0 - stellopt_namelist[ name+'_MIN'] = -1E30 - stellopt_namelist[ name+'_MAX'] = +1E30 - # Arrays - for name in ['AM','AC','AI','EXTCUR']: - stellopt_namelist['L'+name+'_OPT'] = np.ndarray(20) - stellopt_namelist['D'+name+'_OPT'] = np.ndarray(20) - stellopt_namelist[ name+'_MIN'] = np.ndarray(20) - stellopt_namelist[ name+'_MAX'] = np.ndarray(20) - for i in range(20): - stellopt_namelist['L'+name+'_OPT'][i] = 0 - stellopt_namelist['D'+name+'_OPT'][i] = 1.0 - stellopt_namelist[ name+'_MIN'][i] = -1E10 - stellopt_namelist[ name+'_MAX'][i] = +1E10 - # Matrices - arr_size1=2*101+1 - arr_size2=100+1 - stellopt_namelist['LBOUND_OPT'] = np.ndarray((arr_size1,arr_size2)) - stellopt_namelist['DBOUND_OPT'] = np.ndarray((arr_size1,arr_size2)) - stellopt_namelist['BOUND_MIN'] = np.ndarray((arr_size1,arr_size2)) - stellopt_namelist['BOUND_MAX'] = np.ndarray((arr_size1,arr_size2)) - stellopt_namelist['LRHO_OPT'] = np.ndarray((arr_size1,arr_size2)) - stellopt_namelist['DRHO_OPT'] = np.ndarray((arr_size1,arr_size2)) - stellopt_namelist['LDELTAMN_OPT'] = np.ndarray((arr_size1,arr_size1)) - stellopt_namelist['DDELTAMN_OPT'] = np.ndarray((arr_size1,arr_size1)) - stellopt_namelist['DELTA_MIN'] = np.ndarray((arr_size1,arr_size1)) - stellopt_namelist['DELTA_MAX'] = np.ndarray((arr_size1,arr_size1)) - for n in range(arr_size1): - for m in range(arr_size2): - stellopt_namelist['LBOUND_OPT'][n,m]=0 - stellopt_namelist['DBOUND_OPT'][n,m]=1.0 - stellopt_namelist['BOUND_MIN'][n,m]=-1.0E10 - stellopt_namelist['BOUND_MAX'][n,m]=+1.0E10 - stellopt_namelist['LRHO_OPT'][n,m]=0 - stellopt_namelist['DRHO_OPT'][n,m]=1.0 - for n in range(arr_size1): - for m in range(arr_size1): - stellopt_namelist['LDELTAMN_OPT'][n,m]=0 - stellopt_namelist['DDELTAMN_OPT'][n,m]=1.0 - stellopt_namelist['DELTA_MIN'][n,m]=-1.0E10 - stellopt_namelist['DELTA_MAX'][n,m]=+1.0E10 - - return stellopt_namelist; - -def write_stellopt_namelist(filename,stellopt_namelist): - import os, sys - import ctypes as ct - import numpy.ctypeslib as npct - import numpy as np - # Load Libraries - try: - libstell = ct.cdll.LoadLibrary(os.environ["STELLOPT_PATH"]+"/LIBSTELL/Release/libstell.so") - except KeyError: - print("Please set environment variable STELLOPT_PATH") - sys.exit(1) - # Handle interface - #read_stellopt_input = getattr(libstell,'__vmec_input_MOD_read_indata_namelist') - #SUBROUTINE read_stellopt_input (iunit, istat) - #read_stellopt_input.argtypes = [ct.POINTER(ct.c_int),ct.POINTER(ct.c_int)] - #read_stellopt_input.restype=None - #iunit_temp = ct.c_int(iunit) - #istat_temp = ct.c_int(istat) - #read_stellopt_input(ct.byref(iunit_temp),ct.byref(istat_temp)) - #istat = istat_temp - #iunit = iunit_temp - # Setup Arrays - stellopt_namelist={} - # Will delete this just using for testing - for i,item in enumerate(stellopt_namelist): - print(item) - return stellopt_namelist; - -def read_stellopt(filename): - import numpy as np - # import numpy as np - file_handle = open(filename,'r') - stel_data={} - niter = 0 - for line in file_handle: - if 'ITER' in line: - niter=niter+1 - if 'MIN' in line: - niter=niter-1 - stel_data['ITER'] = np.ndarray((niter,1)); - file_handle.seek(0) - line = file_handle.readline() - ttype,wh=line.split() - stel_data[ttype] = float(wh) - - # Enter Loop - citer = -1 - while True: - line = file_handle.readline() - if line == '': - break - ttype,hw = line.split(' ',1) - if ttype == 'ITER': - if 'MIN' in hw: - break - citer = citer+1 - stel_data[ttype][citer] = int(hw) - continue - elif ttype == 'VERSION': - stel_data[ttype][citer] = float(hw) - continue - elif ttype == 'TARGETS': - h,w = hw.split() - h = int(h) - w = int(w) - if h == 1: - h=w - w=1 - line = file_handle.readline() - elif ttype == 'SIGMAS': - h,w = hw.split() - h = int(h) - w = int(w) - if h == 1: - h=w - w=1 - line = file_handle.readline() - elif ttype == 'VALS': - h,w = hw.split() - h = int(h) - w = int(w) - if h == 1: - h=w - w=1 - line = file_handle.readline() - else: - h,w = hw.split() - h = int(h) - w = int(w) - line = file_handle.readline() - if ttype not in stel_data: - stel_data[ttype]=np.ndarray((niter,h,w)) - for i in range(h): - line = file_handle.readline() - val = np.fromstring(line,sep=' ') - stel_data[ttype][citer,i,:] = val - file_handle.close() - for item in list(stel_data): - #print(item) - if 'VERSION' == item: - continue - elif 'ITER' == item: - continue - elif item in ['ASPECT','ASPECT_MAX','BETA','CURTOR','KAPPA','PHIEDGE', \ - 'VOLUME','WP','RBTOR','R0','Z0','BETATOR','BETAPOL','TEST_X',\ - 'TEST_Y']: - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - elif item == 'BALLOON': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_grate'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_theta'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_zeta'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_k'] = np.squeeze(stel_data[item][:,:,6]) - elif item == 'B_PROBES': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,6]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_X'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_Y'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_Z'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_MODB'] = np.squeeze(stel_data[item][:,:,3]) - elif item in ['FLUXLOOPS','SEGROG']: - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - elif item == 'EXTCUR': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_dex'] = np.squeeze(stel_data[item][:,:,3]) - elif item in ['SEPARATRIX','LIMITER']: - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_R'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_PHI'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_Z'] = np.squeeze(stel_data[item][:,:,5]) - elif item in ['NE','TI','TE','IOTA','VPHI','PRESS','VACIOTA','PRSSPRIME']: - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,6]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_R'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_PHI'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_Z'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_s'] = np.squeeze(stel_data[item][:,:,3]) - elif item in ['NELINE','TELINE','TILINE','ZEFFLINE','FARADAY','SXR','XICS','XICS_BRIGHT','XICS_W3','XICS_V']: - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_R0'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_PHI0'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_Z0'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_R1'] = np.squeeze(stel_data[item][:,:,6]) - stel_data[item+'_PHI1'] = np.squeeze(stel_data[item][:,:,7]) - stel_data[item+'_Z1'] = np.squeeze(stel_data[item][:,:,8]) - elif item == 'VISBREMLINE': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_LAMBDA'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_CALIB'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil']*stel_data[item+'_CALIB'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_R0'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_PHI0'] = np.squeeze(stel_data[item][:,:,6]) - stel_data[item+'_Z0'] = np.squeeze(stel_data[item][:,:,7]) - stel_data[item+'_R1'] = np.squeeze(stel_data[item][:,:,8]) - stel_data[item+'_PHI1'] = np.squeeze(stel_data[item][:,:,9]) - stel_data[item+'_Z1'] = np.squeeze(stel_data[item][:,:,10]) - elif item == 'MSE': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,8]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_R'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_PHI'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_Z'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_s'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_ER'] = np.squeeze(stel_data[item][:,:,6]) - stel_data[item+'_EZ'] = np.squeeze(stel_data[item][:,:,7]) - elif item == 'BOOTSTRAP': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_s'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_avg_jdotb'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_beam_jdotb'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_boot_jdotb'] = np.squeeze(stel_data[item][:,:,6]) - stel_data[item+'_jBbs'] = np.squeeze(stel_data[item][:,:,7]) - stel_data[item+'_facnu'] = np.squeeze(stel_data[item][:,:,8]) - stel_data[item+'_bsnorm'] = np.squeeze(stel_data[item][:,:,9]) - elif item == 'HELICITY': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_bnorm'] = np.squeeze(stel_data[item][:,:,3]) - elif item == 'HELICITY_FULL': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_bnorm'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_k'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_m'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_n'] = np.squeeze(stel_data[item][:,:,6]) - elif item == 'TXPORT': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_s'] = np.squeeze(stel_data[item][:,:,3]) - elif item == 'KINK': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_wp'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_wk'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_omega'] = np.squeeze(stel_data[item][:,:,5]) - elif item == 'COIL_BNORM': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_U'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_V'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_BNEQ'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_BNF'] = np.squeeze(stel_data[item][:,:,6]) - elif item == 'ORBIT': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_s'] = np.squeeze(stel_data[item][:,:,3]) - elif item == 'J_STAR': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_AVGJSTAR'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_TRAPSJSTAR'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_UJSTAR'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_K'] = np.squeeze(stel_data[item][:,:,6]) - stel_data[item+'_IJSTAR'] = np.squeeze(stel_data[item][:,:,7]) - elif item == 'NEO': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_k'] = np.squeeze(stel_data[item][:,:,3]) - elif item == 'JDOTB': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_s'] = np.squeeze(stel_data[item][:,:,3]) - elif item == 'JTOR': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_s'] = np.squeeze(stel_data[item][:,:,3]) - elif item == 'DKES': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_s'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_nu'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_er'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_L11p'] = np.squeeze(stel_data[item][:,:,6]) - stel_data[item+'_L11m'] = np.squeeze(stel_data[item][:,:,7]) - stel_data[item+'_L33p'] = np.squeeze(stel_data[item][:,:,8]) - stel_data[item+'_L33m'] = np.squeeze(stel_data[item][:,:,9]) - stel_data[item+'_L31p'] = np.squeeze(stel_data[item][:,:,10]) - stel_data[item+'_L31m'] = np.squeeze(stel_data[item][:,:,11]) - stel_data[item+'_scal11'] = np.squeeze(stel_data[item][:,:,12]) - stel_data[item+'_scal33'] = np.squeeze(stel_data[item][:,:,13]) - stel_data[item+'_scal31'] = np.squeeze(stel_data[item][:,:,14]) - elif item == 'ECEREFLECT': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_freq'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_tradx'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_trado'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_mix'] = np.squeeze(stel_data[item][:,:,6]) - elif item == 'MAGWELL': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_Bsqav'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_p'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_pp'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_k'] = np.squeeze(stel_data[item][:,:,6]) - elif item == 'CURVATURE_KERT': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_kurtosis'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_kappa_avg'] = np.squeeze(stel_data[item][:,:,4]) - stel_data[item+'_kappa_max'] = np.squeeze(stel_data[item][:,:,5]) - stel_data[item+'_phi'] = np.squeeze(stel_data[item][:,:,6]) - elif item == 'CURVATURE_P2': - stel_data[item+'_target'] = np.squeeze(stel_data[item][:,:,0]) - stel_data[item+'_sigma'] = np.squeeze(stel_data[item][:,:,1]) - stel_data[item+'_equil'] = np.squeeze(stel_data[item][:,:,2]) - stel_data[item+'_chisq'] = ((stel_data[item+'_target'] - stel_data[item+'_equil'])/stel_data[item+'_sigma'])**2 - stel_data[item+'_p1'] = np.squeeze(stel_data[item][:,:,3]) - stel_data[item+'_p2'] = np.squeeze(stel_data[item][:,:,4]) - - return stel_data; +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for reading and handling +STELLOPT data. +""" + +# Libraries +from libstell.libstell import LIBSTELL + +# Constants + +# STELLOPT Class +class STELLOPT(): + """Class for working with BOOTSJ data + + """ + def __init__(self): + test = 0 + self.target_names=['TEST_X', \ + 'TEST_Y', 'ROSENBROCK_X', 'PHIEDGE', 'CURTOR', \ + 'CURTOR_MAX', 'RBTOR', 'R0', 'Z0', 'B0', 'VOLUME', 'BETA', \ + 'BETAPOL', 'BETATOR', 'WP', 'ASPECT', 'CURVATURE', 'KAPPA',\ + 'KAPPA_BOX', 'KAPPA_AVG', 'ASPECT_MAX', 'PMIN', 'EXTCUR', \ + 'LINE_NE', 'LINE_TE', 'LINE_TI', 'LINE_ZEFF', \ + 'XICS_BRIGHT', 'XICS', 'XICS_W3', 'XICS_V', 'SXR', \ + 'FARADAY', 'LINE_VISBREM', 'ECE', 'PRESS', 'PRESSPRIME', \ + 'NE', 'TE', 'TI', 'VPHI', 'IOTA', 'VACIOTA', 'JDOTB', \ + 'MAGWELL', 'BMIN', 'BMAX', 'MSE', 'JCURV', 'COILLEN', \ + 'COILSEP', 'COILCRV', 'COILSELF', 'COILTORVAR', \ + 'COILRECT', 'COILPOLY', 'BPROBES', 'FLUXLOOPS', 'SEGROG', \ + 'VESSEL', 'SPEARATRIX', 'LIMITER', 'BALLOON', 'BOOTSTRAP', \ + 'NEO', 'DKES', 'DKES_ERDIFF', 'DKES_ALPHA', 'TXPORT', \ + 'ORBIT', 'HELICITY', 'HELICITY_FULL', 'JSTAR', 'RESJAC', \ + 'COIL_BNORM', 'REGCOIL_CHI2_B', 'CURVATURE_P2', 'GAMMA_C', \ + 'KINK'] + + def read_stellopt_map(self,filename='map.dat'): + """Reads a STELLOPT MAP output file + + This routine reads the STELLOPT map.dat output file. + + Parameters + ---------- + filename : str + Path to STELLOPT file. + """ + import numpy as np + import re + f = open(filename,'r') + content = f.read() + f.close() + numbers = re.findall(r'-?\d+\.?\d*(?:[eE][+-]?\d+)?', content) + numbers = [float(num) for num in numbers] + mtargets = int(numbers[0]) + nvars = int(numbers[1]) + ndiv = int(numbers[2]) + numsearch = int(numbers[3]) + nnext = nvars * numsearch + 4 + x = numbers[4:nnext] + fval = numbers[nnext:] + x2d = np.reshape(x,(numsearch,nvars)).T + f2d = np.reshape(fval,(numsearch,mtargets)).T + self.x_map = x2d + self.f_map = f2d + + def read_stellopt_profile(self,filename): + """Reads a STELLOPT tprof output file + + This routine reads the STELLOPT tprof output file. + + Parameters + ---------- + file : str + Path to tprof file. + Returns + ------- + s : ndarray + Array of normalized toroidal flux (s). + ne : ndarray + Array of electron density [m^-3] + te : ndarray + Array of electron temperature [eV] + ti : ndarray + Array of ion temperatures [eV] + zeff : ndarray + Effective ion charge. + p : ndarray + Pressure [Pa] + """ + import numpy as np + f = open(filename,'r') + line = f.readline() # header + s = [] + ne = [] + te = [] + ti = [] + zeff = [] + p = [] + for line in f: # read rest of lines + [txt1,txt2,txt3,txt4,txt5,txt6] = line.split() + s.append(float(txt1)) + ne.append(float(txt2)) + te.append(float(txt3)) + ti.append(float(txt4)) + zeff.append(float(txt5)) + p.append(float(txt6)) + f.close() + return np.array(s),np.array(ne),np.array(te),np.array(ti),np.array(zeff),np.array(p) + + + + def read_stellopt_varlabels(self,filename='var_labels'): + """Reads a STELLOPT var_labels output file + + This routine reads the STELLOPT var_labels output file. + + Parameters + ---------- + file : str + Path to var_labels file. (default 'var_labels') + """ + f = open(filename,'r') + line = f.readline() + nvars = int(line) + var = [] + varnames = [] + for i in range(nvars): + line = f.readline() + line.replace('\n','') + [var1,var2] = line.split(':') + var.append(var1.strip()) + varnames.append(var2.strip()) + line = f.readline() + mtargets = int(line) + targetnames = [] + for i in range(mtargets): + line = f.readline() + line.replace('\n','') + targetnames.append(line.strip()) + f.close() + self.varnames = varnames + self.var = var + self.targetnames = targetnames + + def read_stellopt_output(self,filename): + """Reads a STELLOPT output file + + This routine reads the STELLOPT output file. + + Parameters + ---------- + file : str + Path to STELLOPT file. + """ + import numpy as np + f = open(filename,'r') + lines = f.readlines() + f.close() + i = 0 + temp_dict={} + self.niter = len([line for line in lines if 'ITER' in line]) + while (i < len(lines)): + if 'VERSION' in lines[i]: + [temp,version_txt] = lines[i].split() + self.stellopt_version = float(version_txt) + i = i +1 + continue + elif 'ITER' in lines[i]: + [temp,iter_txt] = lines[i].split() + iter_val = int(iter_txt) + #print(f'-- ITERATION: {lines[i]}') + i = i +1 + continue + if any(x in lines[i] for x in self.target_names): + [targ_name,nrow_txt,ncol_txt] = lines[i].split() + nrow = int(nrow_txt) + ncol = int(ncol_txt) + # Header line i+1 + header = lines[i+1].split() + # Get data + i1 = i+2 + #print(f'---- TARGET: {targ_name} {nrow} {ncol}') + for j in range(nrow): + temp_txt = lines[i1+j].split() + for k in range(ncol): + # Fix the header name if bad. + header_fix = header[k].replace('#','K') + header_fix = header_fix.replace('|B|','MODB') + header_fix = header_fix.replace('EPS_EFF^(3/2)','EPS_EFF32') + header_fix = header_fix.replace('','BSQAVG') + header_fix = header_fix.replace('+','p') + header_fix = header_fix.replace('-','m') + header_fix = header_fix.replace('/','') + #print(f'------ HEADER: {header_fix}') + targ_name_full = targ_name+'_'+header_fix + if targ_name_full not in temp_dict.keys(): + temp_dict[targ_name_full] = np.zeros((self.niter,nrow)) + temp_dict[targ_name_full][iter_val,j] = float(temp_txt[k]) + # Add VAL if not explicitly named + if 'VAL' not in header: + if targ_name+'_VAL' not in temp_dict.keys(): + temp_dict[targ_name+'_VAL'] = np.zeros((self.niter,nrow)) + k = header.index('SIGMA')+1 + for j in range(nrow): + temp_txt = lines[i1+j].split() + temp_dict[targ_name+'_VAL'][iter_val,j] = float(temp_txt[k]) + i = i + 2 + nrow - 1 + i = i + 1 + #print(temp_dict.keys()) + # Convert to attributes + for key in temp_dict: + setattr(self, key, temp_dict[key]) + # Calculate Chisq for each value + for targ_name in self.target_names: + if hasattr(self,targ_name+'_TARGET'): + targ = getattr(self,targ_name+'_TARGET') + sigma = getattr(self,targ_name+'_SIGMA') + val = getattr(self,targ_name+'_VAL') + chisq = (targ-val)/sigma + setattr(self,targ_name+'_CHISQ',chisq*chisq) + +# STELLOPT Input Class +class STELLOPT_INPUT(): + """Class for working with STELLOPT INPUT data + + """ + def __init__(self, parent=None): + self.libStell = LIBSTELL() + self.global_data = STELLOPT_INPUT_GLOBAL() + self.var_data = STELLOPT_INPUT_VAR() + self.target_data = STELLOPT_INPUT_TARGET() + + def read_input(self,filename): + """Reads STELLOPT_INPUT namelist from a file + + This routine wrappers the stellopt_input_mod module reading routine. + Parameters + ---------- + filename : string + Input file name with OPTIMUM namelist + """ + # there are three separate module we need to deal with + global_dict, var_dict, target_dict = self.libStell.read_stellopt_input(filename) + for key in global_dict: + setattr(self.global_data, key, global_dict[key]) + for key in var_dict: + setattr(self.var_data, key, var_dict[key]) + for key in target_dict: + setattr(self.target_data, key, target_dict[key]) + + def write_input(self,filename): + """Writes STELLOPT_INPUT namelist to a file + + This routine wrappers the stellopt_input_mod module writing routine. + Parameters + ---------- + filename : string + Input file name to write OPTIMUM namelist to + """ + # there are three separate module we need to deal with + global_dict = vars(self.global_data) + var_dict = vars(self.var_data) + target_dict = vars(self.target_data) + self.libStell.write_stellopt_input(filename,global_dict,var_dict,target_dict) + +class STELLOPT_INPUT_GLOBAL(): + def __init__(self): + pass + +class STELLOPT_INPUT_VAR(): + def __init__(self): + pass + +class STELLOPT_INPUT_TARGET(): + def __init__(self): + pass + + + + +# Main routine +if __name__=="__main__": + import sys + sys.exit(0) + diff --git a/pySTEL/libstell/vmec.py b/pySTEL/libstell/vmec.py new file mode 100644 index 000000000..7311d4f3d --- /dev/null +++ b/pySTEL/libstell/vmec.py @@ -0,0 +1,578 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for reading and handling VMEC +equilibrium data. +""" + +# Libraries +from libstell.libstell import LIBSTELL, FourierRep + +# Constants + +# VMEC Class +class VMEC(FourierRep): + """Class for working with VMEC equilibria + + """ + def __init__(self): + super().__init__() + self.nfp = None + self.libStell = LIBSTELL() + + def read_wout(self,filename): + """Reads a VMEC wout_file + + This routine reads and initilizes the VMEC class + with variable information from a VMEC wout file. + + Parameters + ---------- + file : str + Path to wout file. + """ + import numpy as np + wout_dict = self.libStell.read_wout(filename) + for key in wout_dict: + setattr(self, key, wout_dict[key]) + # (mu-nv) -> (mu+nv) + self.xn = -self.xn + # Half to full grid + self.buco = self.h2f(self.buco) + self.bvco = self.h2f(self.bvco) + self.vp = self.h2f(self.vp) + self.overr = self.h2f(self.overr) + self.specw = self.h2f(self.specw) + for mn in range(self.mnmax): + self.lmns[:,mn] = self.h2f(self.lmns[:,mn]) + for mn in range(self.mnmax_nyq): + self.bmnc[:,mn] = self.h2f(self.bmnc[:,mn]) + self.gmnc[:,mn] = self.h2f(self.gmnc[:,mn]) + self.bsupumnc[:,mn] = self.h2f(self.bsupumnc[:,mn]) + self.bsupvmnc[:,mn] = self.h2f(self.bsupvmnc[:,mn]) + self.bsubsmns[:,mn] = self.h2f(self.bsubsmns[:,mn]) + self.bsubumnc[:,mn] = self.h2f(self.bsubumnc[:,mn]) + self.bsubvmnc[:,mn] = self.h2f(self.bsubvmnc[:,mn]) + if self.iasym==1: + for mn in range(self.mnmax): + self.lmnc[:,mn] = self.h2f(self.lmnc[:,mn]) + for mn in range(self.mnmax_nyq): + self.bmns[:,mn] = self.h2f(self.bmns[:,mn]) + self.gmns[:,mn] = self.h2f(self.gmns[:,mn]) + self.bsupumns[:,mn] = self.h2f(self.bsupumns[:,mn]) + self.bsupvmns[:,mn] = self.h2f(self.bsupvmns[:,mn]) + self.bsubsmnc[:,mn] = self.h2f(self.bsubsmnc[:,mn]) + self.bsubumns[:,mn] = self.h2f(self.bsubumns[:,mn]) + self.bsubvmns[:,mn] = self.h2f(self.bsubvmns[:,mn]) + # Calc Eplasma + self.eplasma = 1.5*4*np.pi*np.pi*sum( self.vp * self.presf ) / self.ns + # Get mn00 + self.mn00 = None + for mn in range(self.mnmax): + if self.xm[mn]==0 and self.xn[mn]==0: + self.mn00 = mn + + + def h2f(self,var_half): + """Half to full grid + + This routine takes a 1D field and interpolates it from the half + to the full grid. For an ns sized array we assumes that the + first index [0]=0 and is just a placeholder. + + Parameters + ---------- + var_half : list + Variable on half grid + Returns + ---------- + var_full : list + Variable on full grid + """ + temp = var_half.copy() + temp[0] = 1.5 * temp[1] - 0.5 * temp[2] + temp[1:-1] = 0.5 * (temp[1:-1] + temp[2:]) + temp[-1] = 2.0 * temp[-1] - 1.0 * temp[-2] + return temp + + def calc_jll(self, theta, phi ): + """Compute parallel current density + + This routine computes the paralle current density + + Parameters + ---------- + theta : ndarray + Polidal angle grid [rad] + phi : ndarray + Toroidal angle grid [rad] + Returns + ---------- + jll : ndarray + Parallel current density [A/m^2] + """ + b = self.cfunct(theta,phi,self.bmnc,self.xm_nyq,self.xn_nyq) + g = self.cfunct(theta,phi,self.gmnc,self.xm_nyq,self.xn_nyq) + bu = self.cfunct(theta,phi,self.bsubumnc,self.xm_nyq,self.xn_nyq) + bv = self.cfunct(theta,phi,self.bsubvmnc,self.xm_nyq,self.xn_nyq) + ju = self.cfunct(theta,phi,self.currumnc,self.xm_nyq,self.xn_nyq) + jv = self.cfunct(theta,phi,self.currvmnc,self.xm_nyq,self.xn_nyq) + + if (self.iasym==1): + b = b + self.sfunct(theta,phi,self.bmns,self.xm_nyq,self.xn_nyq) + g = g + self.sfunct(theta,phi,self.gmns,self.xm_nyq,self.xn_nyq) + bu = bu + self.sfunct(theta,phi,self.bsubumns,self.xm_nyq,self.xn_nyq) + bv = bv + self.sfunct(theta,phi,self.bsubvmns,self.xm_nyq,self.xn_nyq) + ju = ju + self.sfunct(theta,phi,self.currumns,self.xm_nyq,self.xn_nyq) + jv = jv + self.sfunct(theta,phi,self.currvmns,self.xm_nyq,self.xn_nyq) + jll = (bu*ju+bv*jv)/(g*b) + return jll + + def calc_grad_rhosq(self): + """Compute <|grad(rho)|^2> + This routine flux surface average of |grad(rho)|^2 + + Parameters + ---------- + theta : ndarray + Polidal angle grid [rad] + phi : ndarray + Toroidal angle grid [rad] + Returns + ---------- + avgrho2 : ndarray + Flux surface average of |grad(rho)|^2 + """ + import numpy as np + nu = 64 + nv = 128 + theta = np.linspace(0,2*np.pi,nu) + phi = np.linspace(0,2*np.pi,nv) + # Create derivatives + xm2d = np.broadcast_to(self.xm,(self.ns,self.mnmax)) + xn2d = np.broadcast_to(self.xn,(self.ns,self.mnmax)) + rumns = - xm2d * self.rmnc + rvmns = - xn2d * self.rmnc + zumnc = xm2d * self.zmns + zvmnc = xn2d * self.zmns + if self.iasym==1: + rumnc = xm2d * self.rmns + rvmnc = xn2d * self.rmns + zumns = - xm2d * self.zmnc + zvmns = - xn2d * self.zmnc + r = self.cfunct(theta,zeta,self.rmnc,self.xm,self.xn) + g = self.cfunct(theta,zeta,self.gmnc,self.xm_nyq,self.xn_nyq) + ru = self.sfunct(theta,zeta,rumns,self.xm,self.xn) + rv = self.sfunct(theta,zeta,rvmns,self.xm,self.xn) + zu = self.cfunct(theta,zeta,zumnc,self.xm,self.xn) + zv = self.cfunct(theta,zeta,zvmnc,self.xm,self.xn) + if self.iasym==1: + r = r + self.sfunct(theta,zeta,self.rmns,self.xm,self.xn) + g = g + self.sfunct(theta,zeta,self.gmns,self.xm_nyq,self.xn_nyq) + ru = ru + self.cfunct(theta,zeta,rumnc,self.xm,self.xn) + rv = rv + self.cfunct(theta,zeta,rvmnc,self.xm,self.xn) + zu = zu + self.sfunct(theta,zeta,zumns,self.xm,self.xn) + zv = zv + self.sfunct(theta,zeta,zvmns,self.xm,self.xn) + # Calc metrics + gsr = - zu * r + gsp = zu * rv - ru * zv + gsz = ru * r + gs = ( gsr * gsr + gsp * gsp + gsz * gsz ) / ( g * g ) + for i in range(self.ns): + gs[i,:,:] = 0.25 * gs[i,:,:] / ( rho[i] * rho[i] ) + vp = np.sum(g,axis=(1,2)) + avgrho2 = np.sum(gs * g,axis=(1,2)) / vp + avgrho2[1] = 2.0 * avgrho2[1] - avgrho2[2] + return avgrho2 + + def calc_susceptance(self): + """Compute susceptance matrix elements + This routine calculates the susceptance matrix elements + S11, S12, S21, S22. + + Returns + ---------- + S11 : ndarray + Susceptance matrix elements S11 + S12 : ndarray + Susceptance matrix elements S11 + S21 : ndarray + Susceptance matrix elements S11 + S22 : ndarray + Susceptance matrix elements S11 + """ + import numpy as np + nu = 64 + nv = 128 + theta = np.linspace(0,2*np.pi,nu) + phi = np.linspace(0,2*np.pi,nv) + # Create derivatives + xm2d = np.broadcast_to(self.xm,(self.ns,self.mnmax)) + xn2d = np.broadcast_to(self.xn,(self.ns,self.mnmax)) + rumns = - xm2d * self.rmnc + rvmns = - xn2d * self.rmnc + zumnc = xm2d * self.zmns + zvmnc = xn2d * self.zmns + lumnc = xm2d * self.lmns + lvmnc = xn2d * self.lmns + if self.iasym==1: + rumnc = xm2d * self.rmns + rvmnc = xn2d * self.rmns + zumns = - xm2d * self.zmnc + zvmns = - xn2d * self.zmnc + lumns = - xm2d * self.lmnc + lvmns = - xn2d * self.lmnc + r = self.cfunct(theta,zeta,self.rmnc,self.xm,self.xn) + g = self.cfunct(theta,zeta,self.gmnc,self.xm_nyq,self.xn_nyq) + ru = self.sfunct(theta,zeta,rumns,self.xm,self.xn) + rv = self.sfunct(theta,zeta,rvmns,self.xm,self.xn) + zu = self.cfunct(theta,zeta,zumnc,self.xm,self.xn) + zv = self.cfunct(theta,zeta,zvmnc,self.xm,self.xn) + lu = self.cfunct(theta,zeta,lumnc,self.xm,self.xn) + lv = self.cfunct(theta,zeta,lvmnc,self.xm,self.xn) + if self.iasym==1: + r = r + self.sfunct(theta,zeta,self.rmns,self.xm,self.xn) + g = g + self.sfunct(theta,zeta,self.gmns,self.xm_nyq,self.xn_nyq) + ru = ru + self.cfunct(theta,zeta,rumnc,self.xm,self.xn) + rv = rv + self.cfunct(theta,zeta,rvmnc,self.xm,self.xn) + zu = zu + self.sfunct(theta,zeta,zumns,self.xm,self.xn) + zv = zv + self.sfunct(theta,zeta,zvmns,self.xm,self.xn) + lu = lu + self.sfunct(theta,zeta,lumns,self.xm,self.xn) + lv = lv + self.sfunct(theta,zeta,lvmns,self.xm,self.xn) + # Calc suscpetance matrices + scale_fact = 1.0 / ( 4 * np.pi * np.pi ) + S11 = ( ru * ru + zu * zu) + S21 = ( ru * rv + zu * zv) + S12 = ( S12 * ( 1.0 + lu ) - S11 * lv ) + S22 = ( ( rv * rv + zv * zv + r * r ) * ( 1.0 + lu ) - S21 * lv ) + S11 = np.trapz(S11 / g, x=zeta, axis=2) + S12 = np.trapz(S12 / g, x=zeta, axis=2) + S21 = np.trapz(S21 / g, x=zeta, axis=2) + S22 = np.trapz(S22 / g, x=zeta, axis=2) + S11 = np.trapz(S11, x=theta, axis=1)*scale_fact + S12 = np.trapz(S12, x=theta, axis=1)*scale_fact + S21 = np.trapz(S21, x=theta, axis=1)*scale_fact + S22 = np.trapz(S22, x=theta, axis=1)*scale_fact + return S11,S12,S21,S22 + + def getCurrentPoloidal(self): + """Returns the poloidal total current + This routine returns the total poloidal current as used by the + BNORM code. + + Returns + ---------- + curpol : float + Total poloidal current B_v*2*pi/nfp (m=0,n=0) + """ + import numpy as np + curpol = 1.0 + for mn in range(self.mnmax_nyq): + if (self.xm_nyq[mn]==0 and self.xn_nyq[mn]==0): + curpol = 2.0*self.bsubvmnc[self.ns-1,mn]*np.pi/self.nfp + return curpol + + def extrapSurface(self,surf=None,dist=0.1): + """Returns an extrapolated surface. + This routine extrapolates a surface a given distance using the + VMEC scaling for modes. The surface to extrapolate (default ns) + and distance to extrapolate (default 0.1 [m]) are optional + inputs. + + Parameters + ---------- + surf : int (optional) + Surface to extrapolate (default: ns) + dist : float (optional) + Distance to extrapolate [m] (default 0.1) + + Returns + ---------- + rmnc : ndarray + R cosine harmonics of extrapolated surface + zmns : ndarray + Z sine harmonics of extrapolated surface + zmns : ndarray + R sine harmonics of extrapolated surface + rmnc : ndarray + Z cosine harmonics of extrapolated surface + """ + import numpy as np + if surf: + k=surf-1 + else: + k=self.ns-1 + rho = np.sqrt(float(k)/(self.ns-1)) + rmnc = self.rmnc[k,:] + zmns = self.zmns[k,:] + r0c = np.where(self.xm==0,self.rmnc[0,:],0) + z0s = np.where(self.xm==0,self.zmns[0,:],0) + rmnc = rmnc - r0c + zmns = zmns - z0s + if self.iasym==1: + rmns = self.rmns[k,:] + zmnc = self.zmnc[k,:] + r0s = np.where(self.xm==0,self.rmns[0,:],0) + z0c = np.where(self.xm==0,self.zmnc[0,:],0) + rmns = rmns - r0s + zmnc = zmnc - z0c + scale = (self.aminor+dist)/self.aminor + scale = scale*scale + #scalemn = np.ones((self.mnmax))*scale + scalemn = np.where(self.xm%2==1, rho*scale, scale) + rmnc = rmnc * scalemn + zmns = zmns * scalemn + rmnc = rmnc + r0c + zmns = zmns + z0s + if self.iasym == 1: + rmns = rmns * scalemn + zmnc = zmns * scalemn + rmns = rmns + r0s + zmnc = zmnc + z0c + else: + rmns = np.zeros((self.mnmax)) + zmnc = np.zeros((self.mnmax)) + return rmnc, zmns, rmns, zmnc + + def offsetCurve(self, R, Z, distance=0.1): + """Returns points an offset distance from a curve + The routine takes a set of points in R and Z and calculates a + set of offset points. + + Parameters + ---------- + R : ndarray + Array of points in R [m] + Z : ndarray + Array of points in Z [m] + dist : float (optional) + Distance to extrapolate [m] (default 0.1) + + Returns + ---------- + R : ndarray + Offset points in R [m] + Z : ndarray + Offset points in Z [m] + """ + import numpy as np + + # Calculate the tangents + dx = np.diff(R, append=R[0]) + dy = np.diff(Z, append=Z[0]) + + # Calculate the normals + lengths = np.sqrt(dx**2 + dy**2) + normals_x = -dy / lengths + normals_y = dx / lengths + + # Offset the points + offset_x = R + distance * normals_x + offset_y = Z + distance * normals_y + return offset_x, offset_y + + def fitSurface(self,surf=None,dist=0.1): + """Returns Fourier Harmonics of a fitted surface + This routine calculates a fit of Fourier coefficients to + a supplied surface or a surface a uniform distance from the + VMEC equilibrium boundary. If a surface is provided it must be + provided as a set of ordered points x,y,z [3,nu,nv]. + + Parameters + ---------- + surf : ndarray [3,nu,nv] (optional) + Surface to fit (default: use dist) + dist : float (optional) + Distance to extrapolate [m] (default 0.1) + + Returns + ---------- + rmnc : ndarray + R cosine harmonics of extrapolated surface + zmns : ndarray + Z sine harmonics of extrapolated surface + zmns : ndarray + R sine harmonics of extrapolated surface + rmnc : ndarray + Z cosine harmonics of extrapolated surface + """ + import numpy as np + from scipy.optimize import minimize + ns1 = self.ns-1 + if surf: + theta = surf[0] + phi = surf[1] + boundr = surf[3] + boundz = surf[4] + nu = len(theta) + nv = len(phi) + else: + nu = 64 + nv = 16 + theta = np.ndarray((nu,1)) + phi = np.ndarray((nv,1)) + for j in range(nu): theta[j]=2.0*np.pi*j/float(nu) + if self.iasym == 1: + for j in range(nv): phi[j] = 2.0*np.pi*j/float(nv-1) + else: + for j in range(nv): phi[j] = np.pi*j/float(nv-1) + phi = phi / self.nfp + r = self.cfunct(theta,phi,self.rmnc,self.xm,self.xn) + z = self.sfunct(theta,phi,self.zmns,self.xm,self.xn) + if self.iasym==1: + r = r + self.sfunct(theta,phi,self.rmns,self.xm,self.xn) + z = z + self.cfunct(theta,phi,self.zmnc,self.xm,self.xn) + boundr = np.squeeze(r[ns1,:,:]) + boundz = np.squeeze(z[ns1,:,:]) + for v in range(nv): + x = boundr[:,v] + y = boundz[:,v] + x,y = self.offsetCurve(x,y,dist) + boundr[:,v] = x + boundz[:,v] = y + opts = (nu,nv,self.xm,self.xn,theta,phi,boundr,boundz) + self.fitFactor = (1.0+np.squeeze(self.xm)) + r_temp = np.squeeze(self.rmnc[ns1,:])*self.fitFactor + z_temp = np.delete(self.zmns[ns1,:]*self.fitFactor,self.mn00) + x0 = np.concatenate((r_temp,z_temp)) + if self.iasym == 1: + r1_temp = np.delete(self.rmns[ns1,:]*self.fitFactor,self.mn00) + z1_temp = np.squeeze(self.zmnc[ns1,:],self.mn00)*self.fitFactor + x0 = np.concatenate((r_temp,z_temp,r1_temp,z1_temp)) + self.Nfeval = 0 + self.Rfit = boundr + self.Zfit = boundz + res = minimize(self.fit_func, x0, method='CG', + args=opts, options={'disp': True}, + callback=self.callbackF,tol=1.0E-1) + xf = res.x + i1 = 0; i2 = i1+self.mnmax + rmnc = np.broadcast_to(xf[i1:i2],(1,self.mnmax))/self.fitFactor + i1 = i2; i2 = i1+self.mnmax-1 + xtemp = xf[i1:i2] + zmns = np.broadcast_to(np.insert(xtemp,self.mn00,0.0),(1,self.mnmax))/self.fitFactor + if self.iasym==1: + i1 = i2; i2 = i1+self.mnmax-1 + xtemp = xf[i1:i2] + rmns = np.broadcast_to(np.insert(xtemp,self.mn00,0.0),(1,self.mnmax))/self.fitFactor + i1 = i2; i2 = i1+self.mnmax + zmnc = np.broadcast_to(xf[i1:i2],(1,self.mnmax))/self.fitFactor + else: + rmns = np.zeros((self.mnmax)) + zmnc = np.zeros((self.mnmax)) + return np.squeeze(rmnc),np.squeeze(zmns),np.squeeze(rmns),np.squeeze(zmnc) + + def fit_func(self,x,*args): + import numpy as np + nu = args[0] + nv = args[1] + xm = args[2] + xn = args[3] + theta = args[4] + phi = args[5] + boundr = args[6] + boundz = args[7] + mnmax = xm.shape[0] + i1 = 0; i2 = i1+mnmax + rmnc = np.broadcast_to(x[i1:i2],(1,mnmax))/self.fitFactor + i1 = i2; i2 = i1+mnmax-1 + xtemp = x[i1:i2] + zmns = np.broadcast_to(np.insert(xtemp,self.mn00,0.0),(1,mnmax))/self.fitFactor + r = self.cfunct(theta,phi,rmnc,xm,xn) + z = self.sfunct(theta,phi,zmns,xm,xn) + if x.shape[0] > 2*mnmax: + i1 = i2; i2 = i1+mnmax-1 + xtemp = x[i1:i2] + rmns = np.broadcast_to(np.insert(xtemp,self.mn00,0.0),(1,mnmax))/self.fitFactor + i1 = i2; i2 = i1+mnmax + zmnc = np.broadcast_to(x[i1:i2],(1,mnmax))/self.fitFactor + r = r + self.sfunct(theta,phi,rmns,xm,xn) + z = z + self.cfunct(theta,phi,zmnc,xm,xn) + # Calc distance + d = 0 + for u in range(nu): + for v in range(nv): + dr = boundr[u,v] - np.squeeze(r[0,:,v]) + dz = boundz[u,v] - np.squeeze(z[0,:,v]) + dl2 = dr*dr + dz*dz + d = d + min(dl2) + return d + def callbackF(self,intermediate_result): + print(f'ITER: {self.Nfeval} -- dval: {intermediate_result.fun}') + self.Nfeval += 1 + + def callbackF_plot(self,Xi): + import numpy as np + import matplotlib.pyplot as pyplot + mnmax = self.mnmax + nu = 32 + nv = 3 + theta = np.ndarray((nu,1)) + phi = np.ndarray((nv,1)) + for j in range(nu): theta[j]=2.0*np.pi*j/float(nu-1) + for j in range(nv): phi[j] = np.pi*j/float(nv-1) + i1 = 0; i2 = i1+mnmax + rmnc = np.broadcast_to(Xi[i1:i2],(1,mnmax))/self.fitFactor + i1 = i2; i2 = i1+mnmax + xtemp = Xi[i1:i2] + zmns = np.broadcast_to(np.insert(xtemp,self.mn00,0.0),(1,mnmax))/self.fitFactor + r = self.cfunct(theta,phi,rmnc,self.xm,self.xn/self.nfp) + z = self.sfunct(theta,phi,zmns,self.xm,self.xn/self.nfp) + px = 1/pyplot.rcParams['figure.dpi'] + fig,ax = pyplot.subplots(1,1,figsize=(1024*px,768*px)) + ax.plot(self.Rfit[:,0],self.Zfit[:,0],'ko') + ax.plot(self.Rfit[:,-1],self.Zfit[:,-1],'ko') + ax.plot(r[0,:,0],z[0,:,0],'r') + ax.plot(r[0,:,1],z[0,:,1],'g') + ax.plot(r[0,:,2],z[0,:,2],'b') + pyplot.show(block=False) + pyplot.pause(0.1) + print('{0:4d} {1: 3.6f} {2: 3.6f} {3: 3.6f}'.format(self.Nfeval, Xi[0], Xi[1], Xi[2])) + self.Nfeval += 1 + pyplot.close(fig) + +# VMEC INDATA Class +class VMEC_INDATA(): + """Class for working with VMEC equilibria + + """ + def __init__(self, parent=None): + self.nfp = None + self.libStell = LIBSTELL() + + def read_indata(self,filename): + """Reads INDATA namelist from a file + + This routine wrappers the vmec_input module reading routine. + Parameters + ---------- + filename : string + Input file name with INDATA namelist + """ + indata_dict = self.libStell.read_indata(filename) + for key in indata_dict: + setattr(self, key, indata_dict[key]) + # generate helpers + #print(self.rbc.shape) + + def write_indata(self,filename): + """Writes INDATA namelist to a file + + This routine wrappers the vmec_input module writing routine. + Parameters + ---------- + filename : string + Input file name to write INDATA namelist to + """ + #print(self.__dict__) + out_dict = vars(self) + #del out_dict['libStell'] + #print(d(self)) + self.libStell.write_indata(filename,out_dict) + + + +# Main routine +if __name__=="__main__": + import sys + sys.exit(0) \ No newline at end of file diff --git a/pySTEL/libstell/wall.py b/pySTEL/libstell/wall.py new file mode 100644 index 000000000..bad2a3c10 --- /dev/null +++ b/pySTEL/libstell/wall.py @@ -0,0 +1,216 @@ +##!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This library provides a python class for working with wall_data +""" + +# Libraries +from libstell.libstell import LIBSTELL + +# Constants + +# VMEC Class +class WALL(LIBSTELL): + """Class for working with wall files + + """ + def __init__(self): + self.name = None + self.date = None + self.nfaces = None + self.nvertex = None + self.vertex = None + self.faces = None + self.laccel = False + + def read_wall(self,filename): + """Directly reads a wall file + + This routine reads a wall file into the class. + + Parameters + ---------- + filename : str + Path to wall file. + """ + import numpy as np + f = open(filename,'r') + lines = f.readlines() + f.close() + if 'MACHINE:' in lines[0]: + self.name = lines[0][8:] + else: + print("Bad Synatx line 1 in wall file") + if 'DATE:' in lines[1]: + self.date = lines[1][6:] + else: + print("Bad Synatx line 2 in wall file") + n1, n2 = lines[2].split() + i1 = 3 + if (n1 == 0 and n2 == 0): + self.laccel = True + n1, n2 = lines[3].split() + i1 = 4 + self.nvertex = int(n1) + self.nfaces = int(n2) + self.vertex = np.zeros((self.nvertex,3)) + self.faces = np.zeros((self.nfaces,3)) + for i in range(self.nvertex): + line = lines[i+i1].split() + self.vertex[0,i] = float(line[0]) + self.vertex[1,i] = float(line[1]) + self.vertex[2,i] = float(line[2]) + i1 = i1 + self.nvertex + for i in range(self.nfaces): + line = lines[i+i1].split() + # note we convert to python indexing + self.faces[0,i] = int(line[0])-1 + self.faces[1,i] = int(line[1])-1 + self.faces[2,i] = int(line[2])-1 + + def write_wall(self,filename): + """Directly writes a wall file + + This routine writes a wall file from the class. + + Parameters + ---------- + filename : str + Path to wall file. + """ + f = open(filename,'w') + f.write(f"MACHINE: {self.name}\n") + f.write(f"DATE: {self.date}\n") + f.write(f"{self.nvertex} {self.nfaces}\n") + for i in range(self.nvertex): + f.write(f"{self.vertex[i,0]:20.10E} {self.vertex[i,1]:20.10E} {self.vertex[i,2]:20.10E}\n") + # Note we convert back to matlab indexing + for i in range(self.nfaces): + f.write(f"{int(self.faces[i,0])+1} {int(self.faces[i,1])+1} {int(self.faces[i,2])+1}\n") + f.close() + + def plot_wall_cloud(self,ax=None): + """Plots the vertices of the wall + + This routine plots the vertices of a wall at a point cloud. + It takes an axis as an optional argument. + + Parameters + ---------- + ax : axis object (optional) + Axis onto which to plot + """ + import matplotlib.pyplot as pyplot + lplotnow = False + if not ax: + ax = pyplot.axes(projection='3d') + lplotnow = True + ax.scatter(self.vertex[:,0],self.vertex[:,1],self.vertex[:,2],marker='.') + if lplotnow: pyplot.show() + + def plot_wall_3D(self,*args,**kwargs): + import numpy as np + import matplotlib.pyplot as pyplot + import mpl_toolkits.mplot3d as mplot3d + import math as math + import matplotlib.tri as mtri + #fig=kwargs.pop('fig',pyplot.figure()) + #ax=kwargs.pop('axes',fig.add_subplot(111,projection='3d')) + # Create the mesh + #vectors = np.zeros() + #wall_mesh = mesh.Mesh(np.zeros(self.faces.shape[0], dtype=mesh.Mesh.dtype)) + #for i, f in enumerate(self.faces): + # for j in range(3): + # wall_mesh.vectors[i][j] = self.vertex[f[j],:] + #ax.add_collection3d(mplot3d.art3d.Poly3DCollection(wall_mesh.vectors)) + #tsurf=ax.plot_trisurf(self.vertex[0,:],self.vertex[1,:],self.vertex[2,:], triangles=self.faces,color='red',shade='yes',linewidth=0.0,alpha=1) + #if len(kwargs) == 0: pyplot.show() + + def blenderWall(self): + """Generates the lists Blender needs to render a wall + + This routine generates the verticies and faces lists which + Blender needs to render a wall. + + Returns + ---------- + vertices : list + List of tuples defining verticies + faces: list + List of tubles defining faces + """ + vertices = [] + faces = [] + for i in range(self.nvertex): + vertices.append((self.vertex[i,0],self.vertex[i,1],self.vertex[i,2])) + for i in range(self.nfaces): + faces.append((int(self.faces[i,0]),int(self.faces[i,1]),int(self.faces[i,2]))) + return vertices,faces + + def genWallfromOrdered(self,vertex): + """Generates a wall from an orderer array + + This routine generates a wall from an ordered set of points + where the array size is (3,nphi,ntheta). It assumes + that datapoints are not repeated in the theta or + phi direction, but those coordinates are periodic. + + Parameters + ---------- + vertex : ndarray + Ordered set of verticies + """ + import numpy as np + from datetime import datetime + temp,nphi,ntheta = vertex.shape + nvertex = nphi*ntheta + nfaces = 2*nphi*ntheta + x = np.zeros((nvertex)) + y = np.zeros((nvertex)) + z = np.zeros((nvertex)) + faces = np.zeros((nfaces,3)) + # Do Vertices + k=0 + for v in range(nphi): + for u in range(ntheta): + x[k] = vertex[0,v,u] + y[k] = vertex[1,v,u] + z[k] = vertex[2,v,u] + k = k + 1 + # Do faces + n = 0 + for v in range(nphi): + for u in range(ntheta): + i1 = u + v * ntheta + # Catch special case #1 + if u == ntheta-1: + i2 = i1 + ntheta + i3 = i1 + 1 + i4 = i1 - ntheta + 1 + if v == nphi - 1: + i2 = u + i3 = 0 + elif u < ntheta-1: + i2 = i1 + ntheta + i3 = i1 + ntheta +1 + i4 = i1 + 1 + if v == nphi -1: + i2 = u + i3 = u + 1 + faces[n] = [i1, i2, i4] + n = n + 1 + faces[n] = [i2, i3, i4] + n = n + 1 + self.name = f"Generated using genWallfromOrdered in Python." + self.date = datetime.today().strftime('%Y-%m-%d') + self.nvertex = nvertex + self.nfaces = nfaces + self.vertex = np.column_stack((x,y,z)) + self.faces = faces + +if __name__=="__main__": + import sys + wall_data = WALL() + wall_data.read_wall('QSM.dat') + wall_data.plot_wall_3D() + sys.exit(0) diff --git a/pySTEL/setup.py b/pySTEL/setup.py new file mode 100644 index 000000000..dd0860f9d --- /dev/null +++ b/pySTEL/setup.py @@ -0,0 +1,18 @@ +#from distutils.core import setup +from setuptools import setup, find_packages + +setup(name='pySTEL', + version = '1.0.0', + description = 'Python library for interfacing with STELLOPT', + long_description = 'This software package contains python '+ \ + 'software for interfacing with the STELLOPT'+\ + 'package of codes.', + author = 'Samuel A. Lazerson', + author_email = 'lazersos@gmail.com', + url = 'https://github.com/PrincetonUniversity/STELLOPT', + packages=['libstell'], + scripts = ['VMECplot.py','FIELDLINESplot.py','vmec_util.py',\ + 'boozer_util.py','coils_util.py','fieldlines_util.py'], + install_requires=['numpy','matplotlib','PyQt5','scipy', \ + 'contourpy'] + ) diff --git a/pySTEL/vmec_util.py b/pySTEL/vmec_util.py new file mode 100644 index 000000000..43879a5c4 --- /dev/null +++ b/pySTEL/vmec_util.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# Main routine +if __name__=="__main__": + import sys + from argparse import ArgumentParser + import numpy as np + import matplotlib.pyplot as pyplot + from libstell.vmec import VMEC, VMEC_INDATA + from libstell.libstell import LIBSTELL + parser = ArgumentParser(description= + '''Provides class for accessing vmec data also serves as a + simple tool for assessing vmec wout or input files.''') + parser.add_argument("-v", "--vmec", dest="vmec_ext", + help="VMEC file extension", default = None) + parser.add_argument("-p", "--plot", dest="lplot", action='store_true', + help="Plot the VMEC file.", default = False) + parser.add_argument("-b", "--boozer", dest="lbooz", action='store_true', + help="Output the in_booz file.", default = False) + args = parser.parse_args() + vmec_wout = VMEC() + vmec_input = VMEC_INDATA() + libStell = LIBSTELL() + if args.vmec_ext: + linput = False + loutput = False + try: + vmec_input.read_indata('input.'+args.vmec_ext) + linput = True + except: + print(f'Could not file input file: input.{args.vmec_ext}') + try: + vmec_wout.read_wout(args.vmec_ext) + loutput = True + except: + print(f'Could not file input file: wout_{args.vmec_ext}.nc or wout.{args.vmec_ext}') + if not (linput or loutput): sys.exit(-1) + # Write in_booz file + if (loutput and args.lbooz): + filename = 'in_booz.'+args.vmec_ext + f = open(filename,'w') + f.write(f'{vmec_wout.mpol*4} {vmec_wout.ntor*2}\n') + f.write(f'{args.vmec_ext}\n') + for i in range(vmec_wout.ns): + f.write(f' {i+1}') + f.write('\n') + f.close() + # Do Input file plot + if (args.lplot and linput): + px = 1/pyplot.rcParams['figure.dpi'] + fig=pyplot.figure(figsize=(1024*px,768*px)) + ax=fig.add_subplot(221) + pyplot.subplots_adjust(hspace=0.4,wspace=0.3) + s = np.linspace(0.0,1.0,128) + f = np.zeros(128) + for i,x in enumerate(s): + f[i] = libStell.pmass(x) + ax.plot(s,f/1E3,'k') + ax.text(0.02,0.19,rf'PHIEDGE={vmec_input.phiedge:4.3f} [Wb]', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.12,rf'PRESS_SCALE={vmec_input.pres_scale}', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.05,rf'MGRID_FILE: {vmec_input.mgrid_file}', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.98,0.95,f'PMASS_TYPE: {vmec_input.pmass_type}', horizontalalignment='right',\ + verticalalignment='center', transform=ax.transAxes) + ax.set_xlim(0,1) + ax.set_xlabel('Norm. Tor. Flux (s)') + ax.set_ylabel("Pressure [kPa]") + ax.set_title(f'VMEC Input: {args.vmec_ext}') + ax=fig.add_subplot(222) + if vmec_input.ncurr==1: + for i,x in enumerate(s): + f[i] = libStell.pcurr(x) + ax.set_ylabel("Current I(s)") + temp_str='PCURR' + temp_type = vmec_input.pcurr_type + else: + for i,x in enumerate(s): + f[i] = libStell.piota(x) + ax.set_ylabel(r"$\iota$") + temp_str='PIOTA' + temp_type = vmec_input.piota_type + ax.plot(s,f,'k') + ax.set_xlabel('Norm. Tor. Flux (s)') + ax.text(0.98,0.95,f'{temp_str}_TYPE: {temp_type}', horizontalalignment='right',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.12,rf'CURTOR: {vmec_input.curtor:6.1f}', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.05,rf'NCURR: {vmec_input.ncurr}', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + pyplot.show() + + # Do wout file plot + if (args.lplot and loutput): + px = 1/pyplot.rcParams['figure.dpi'] + fig=pyplot.figure(figsize=(1024*px,768*px)) + ax=fig.add_subplot(221) + pyplot.subplots_adjust(hspace=0.4,wspace=0.3) + ax.plot(np.linspace(0.0,1.0,vmec_wout.ns),vmec_wout.presf/1E3,'k') + ax.text(0.02,0.47,rf'$B_0$={vmec_wout.b0:4.3f} [T]', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.40,rf'$R/a$={vmec_wout.aspect:4.3f}', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.33,rf'$R$={vmec_wout.rmajor:4.3f}', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.26,rf'$a$={vmec_wout.aminor:4.3f}', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.19,rf'$W_p$={vmec_wout.eplasma[0]/1000:4.3f} [kJ]', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.12,rf'$<\beta>$={vmec_wout.betatot*100:3.2f} %', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.02,0.05,rf'MGRID_FILE: {vmec_wout.mgrid_file}', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.98,0.95,f'PMASS_TYPE: {vmec_wout.pmass_type}', horizontalalignment='right',\ + verticalalignment='center', transform=ax.transAxes) + ax.set_xlim(0,1) + ax.set_xlabel('Norm. Tor. Flux (s)') + ax.set_ylabel("Pressure [kPa]") + ax.set_title(f'VMEC Ouput: {args.vmec_ext}') + ax=fig.add_subplot(222) + ax2 = ax.twinx() + ax.plot(np.linspace(0.0,1.0,vmec_wout.ns),vmec_wout.iotaf,'k') + ax2.plot(np.linspace(0.0,1.0,vmec_wout.ns),vmec_wout.jcurv/1E3,'r') + ax.text(0.05,0.05,rf'$I$={vmec_wout.itor/1000:4.2f} [kA]', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.98,0.95,f'PCURR_TYPE: {vmec_wout.pcurr_type}', horizontalalignment='right',\ + verticalalignment='center', transform=ax.transAxes) + ax.text(0.98,0.88,f'PIOTA_TYPE: {vmec_wout.piota_type}', horizontalalignment='right',\ + verticalalignment='center', transform=ax.transAxes) + ax.set_xlim(0,1) + ax.set_xlabel('Norm. Tor. Flux (s)') + ax.set_ylabel(r"$\iota$",color='k') + ax2.set_ylabel(r"$$ [$kA/m^2$]",color='r') + ax=fig.add_subplot(223) + theta = np.ndarray((360,1)) + zeta = np.ndarray((3,1)) + for j in range(360): theta[j]=2.0*np.pi*j/359.0 + for j in range(3): zeta[j]= np.pi*j/2.0 + r = vmec_wout.cfunct(theta,zeta,vmec_wout.rmnc,vmec_wout.xm,vmec_wout.xn/vmec_wout.nfp) + z = vmec_wout.sfunct(theta,zeta,vmec_wout.zmns,vmec_wout.xm,vmec_wout.xn/vmec_wout.nfp) + ax.plot(r[1,1,0],z[1,1,0],'+r') + ax.plot(r[1,1,1],z[1,1,1],'+g') + ax.plot(r[1,1,2],z[1,1,2],'+b') + j = vmec_wout.ns-1 + ax.plot(r[j,:,0],z[j,:,0],'r') + ax.plot(r[j,:,1],z[j,:,1],'g') + ax.plot(r[j,:,2],z[j,:,2],'b') + j = int(vmec_wout.ns/4) + ax.plot(r[j,:,0],z[j,:,0],'--r') + ax.plot(r[j,:,1],z[j,:,1],'--g') + ax.plot(r[j,:,2],z[j,:,2],'--b') + ax.set_aspect('equal', adjustable='box') + ax.text(0.02,0.05,rf'NFP: {vmec_wout.nfp}', horizontalalignment='left',\ + verticalalignment='center', transform=ax.transAxes) + ax=fig.add_subplot(224) + theta = np.ndarray((256,1)) + zeta = np.ndarray((256,1)) + for j in range(256): theta[j]=2.0*np.pi*j/255.0 + for j in range(256): zeta[j]=2.0*np.pi*j/255.0 + b = vmec_wout.cfunct(theta,zeta,vmec_wout.bmnc,vmec_wout.xm_nyq,vmec_wout.xn_nyq/vmec_wout.nfp) + j = int(vmec_wout.ns/4) + h=ax.pcolormesh(np.squeeze(b[j,:,:]),cmap='jet',shading='gouraud') + ax.set_xlabel(r"$\zeta [rad]$") + ax.set_ylabel(r"$\theta_{VMEC}$ [rad]") + ax.set_title("|B| at mid radius") + fig.colorbar(h,label='[T]') + pyplot.show() + sys.exit(0) \ No newline at end of file