add gray-convert tool

This is a command line tool to convert between different GRAY
configuration file formats.
This commit is contained in:
Michele Guerini Rocco 2024-04-22 12:04:25 +02:00
parent 44e957f8d6
commit a596b0dff2
Signed by: rnhmjoj
GPG Key ID: BFBAF4C975F76450
4 changed files with 355 additions and 5 deletions

View File

@ -47,9 +47,10 @@ MODULES = $(filter-out $(OBJDIR)/main%,$(OBJECTS))
# Build outputs # Build outputs
GRAY = $(BINDIR)/gray GRAY = $(BINDIR)/gray
LIBGRAY = $(LIBDIR)/libgray.so LIBGRAY = $(LIBDIR)/libgray.so
BINARIES = $(GRAY) BINARIES = $(GRAY) $(GRAY)-convert
LIBRARIES = $(LIBGRAY) LIBRARIES = $(LIBGRAY)
MANPAGES = $(addprefix $(SHAREDIR)/,gray.1 gray.ini.5 profiles.txt.5 beamdata.txt.5 magneticdata.txt.5) MANPAGES = $(addprefix $(SHAREDIR)/,gray.1 gray-convert.1 gray.ini.5 \
profiles.txt.5 beamdata.txt.5 magneticdata.txt.5)
## ##
## Git information (used in the version string) ## Git information (used in the version string)
@ -149,6 +150,10 @@ $(OBJDIR)/%.o: $(OBJDIR)/%.d
$(GRAY): $(OBJDIR)/main.o $(LIBGRAY) | $(BINDIR) $(GRAY): $(OBJDIR)/main.o $(LIBGRAY) | $(BINDIR)
$(LD) $(LDFLAGS) -o '$@' $< -lgray $(LD) $(LDFLAGS) -o '$@' $< -lgray
# gray-convert binary
$(GRAY)-convert: $(OBJDIR)/main_convert.o $(LIBGRAY) | $(BINDIR)
$(LD) $(LDFLAGS) -o '$@' $< -lgray
# GRAY shared library # GRAY shared library
$(LIBDIR)/libgray.so: $(MODULES) | $(LIBDIR) $(LIBDIR)/libgray.so: $(MODULES) | $(LIBDIR)
$(LD) -shared $(LDFLAGS) -o '$@' $^ $(LD) -shared $(LDFLAGS) -o '$@' $^
@ -173,6 +178,8 @@ $(SHAREDIR)/doc: | $(SHAREDIR)
# Generated man pages # Generated man pages
$(SHAREDIR)/gray.1: $(GRAY) doc/man/gray.1 | $(SHAREDIR) $(SHAREDIR)/gray.1: $(GRAY) doc/man/gray.1 | $(SHAREDIR)
help2man '$<' -i doc/man/gray.1 -N -n 'beam-tracing code for EC waves' > '$@' help2man '$<' -i doc/man/gray.1 -N -n 'beam-tracing code for EC waves' > '$@'
$(SHAREDIR)/gray-convert.1: $(GRAY)-convert | $(SHAREDIR)
help2man '$<' -N -n 'configuration format converter' > '$@'
$(SHAREDIR)/%: doc/man/%.md $(GRAY) | $(SHAREDIR) $(SHAREDIR)/%: doc/man/%.md $(GRAY) | $(SHAREDIR)
pandoc -s '$<' -t man \ pandoc -s '$<' -t man \

View File

@ -13,7 +13,8 @@ GRAY main configuration file
Legacy configuration file Legacy configuration file
This file allows configuring all the parameters of a GRAY simulation, including This file allows configuring all the parameters of a GRAY simulation, including
all other input files. all other input files. Existing files can be upgraded to the gray.ini format
using the \fBgray-convert\fR(1) tool.
.TP .TP
.I beamdata.txt .I beamdata.txt
Beam description file Beam description file
@ -41,4 +42,5 @@ location can be changed with the \fB-o\fR option.
For a list of the unit numbers and their descriptions see the GRAY user manual. For a list of the unit numbers and their descriptions see the GRAY user manual.
[SEE ALSO] [SEE ALSO]
\fBgray.ini\fR(5), \fBgray_params.data\fR(5), \fBbeamdata.txt\fR(5), \fBprofiles.txt\fR(5) \fBgray-convert\fR(1), \fBgray.ini\fR(5), \fBgray_params.data\fR(5),
\fBbeamdata.txt\fR(5), \fBprofiles.txt\fR(5)

View File

@ -24,7 +24,8 @@ module gray_cli
private private
public :: cli_options, print_cli_options, parse_cli_options, & public :: cli_options, print_cli_options, parse_cli_options, &
deinit_cli_options, parse_param_overrides deinit_cli_options, parse_param_overrides, &
print_version, get_next_command
contains contains

340
src/main_convert.f90 Normal file
View File

@ -0,0 +1,340 @@
program gray_convert
use gray_cli, only: print_version, get_next_command
use gray_params, only: gray_parameters, read_gray_params, read_gray_config, &
step_enum, absorption_enum, current_drive_enum, &
polar_enum, beam_enum, equil_enum, x_point_enum, &
scaling_enum, rho_enum, profiles_enum
implicit none
! Configuration formats
enum, bind(c)
enumerator :: config_format = -1
enumerator :: FORMAT_PARAMS = 1 ! the legacy gray_params.data format
enumerator :: FORMAT_INI = 2 ! the current INI format
end enum
! Command line options
! See print_help() for a description.
type cli_options
character(len=:), allocatable :: input_file ! file to read
character(len=:), allocatable :: output_file ! file to write
integer(kind(config_format)) :: format ! output file format
end type
type(cli_options) :: opts
type(gray_parameters) :: params
integer :: err
call parse_cli_options(opts)
! Reading
if (index(opts%input_file, ".data") /= 0) &
call read_gray_params(opts%input_file, params, err)
if (index(opts%input_file, ".ini") /= 0) &
call read_gray_config(opts%input_file, params, err)
if (err /= 0) call exit(2)
! Writing
select case (opts%format)
case (FORMAT_PARAMS)
print '(a)', 'gray_params.data output not implemented!'
call exit(1)
case (FORMAT_INI)
call write_gray_config(opts%output_file, params)
end select
call exit(0)
contains
subroutine print_help()
! Prints the usage screen
print '(a)', 'Usage: gray-convert [options] INFILE OUTFILE'
print '(a)', ''
print '(a)', 'Converts between different GRAY configuration formats.'
print '(a)', ''
print '(a)', 'Options:'
print '(a)', ' -h, --help display this help and exit'
print '(a)', ' -V, --version display version information and exit'
print '(a)', ' -f, --format set the output file format (default: ini)'
print '(a)', ' valid formats are: `ini`, `params`.'
print '(a)', ''
print '(a)', '*Exit status*'
print '(a)', ' 0 if OK,'
print '(a)', ' 1 if technical problems (e.g., invalid arguments, missing input files),'
print '(a)', ' 2 if serious trouble (e.g., invalid input file).'
end subroutine
subroutine parse_cli_options(opts)
! Parses the CLI arguments and initialise the options
! subroutine arguments
type(cli_options), intent(out) :: opts
! local variables
character(len=:), allocatable :: argument
integer :: i, nargs
! Default option values
opts%format = FORMAT_INI
nargs = command_argument_count()
i = 1
do
if (i > nargs) exit
call get_next_command(i, argument)
! parse an argument (and possibly a value)
select case (argument)
! parse optional arguments
case ('-h', '--help')
call print_help()
deallocate(argument)
call exit(0)
case ('-V', '--version')
call print_version()
deallocate(argument)
call exit(0)
case ('-f', '--format')
call get_next_command(i, argument)
select case (argument)
case ('params')
opts%format = FORMAT_PARAMS
case ('ini')
opts%format = FORMAT_INI
case default
print '(a)', 'unknown format: ', argument
end select
case default
! read positional arguments
if (i - nargs == 0) then
opts%input_file = argument
cycle
else if (i - nargs == 1) then
opts%output_file = argument
cycle
end if
print '(a,a,/)', 'Unknown option: ', argument
call print_help()
deallocate(argument)
call exit(1)
end select
end do
! free temporary string
if (nargs > 0) deallocate(argument)
end subroutine
subroutine write_gray_config(filename, params)
! Generates a gray.ini configuration file
! subroutine arguments
character(len=*), intent(in) :: filename
type(gray_parameters), intent(in) :: params
! local variables
type(gray_parameters) :: defaults
character(*), parameter :: fmt = '(a, " = ", g0.6)'
integer :: err, u
open(u, file=filename, action='write', iostat=err)
if (err /= 0) then
print '("opening output file (",a,") failed!")', filename
return
end if
write(u, '(a)') "[raytracing]"
write(u, fmt) "nrayr", params%raytracing%nrayr
write(u, fmt) "nrayth", params%raytracing%nrayth
if (params%raytracing%rwmax /= defaults%raytracing%rwmax) &
write(u, fmt) "rwmax", params%raytracing%rwmax
if (params%raytracing%igrad /= defaults%raytracing%igrad) &
write(u, fmt) "igrad", params%raytracing%igrad
if (params%raytracing%ipass /= defaults%raytracing%ipass) &
write(u, fmt) "ipass", params%raytracing%ipass
if (params%raytracing%ipol .neqv. defaults%raytracing%ipol) &
write(u, fmt) "ipol", format_bool(params%raytracing%ipol)
write(u, fmt) "dst", params%raytracing%dst
if (params%raytracing%nstep /= defaults%raytracing%nstep) &
write(u, fmt) "nstep", params%raytracing%nstep
if (params%raytracing%idst /= defaults%raytracing%idst) &
write(u, fmt) "idst", format_step(params%raytracing%idst)
write(u, '(/,a)') "[ecrh_cd]"
if (params%ecrh_cd%iwarm /= defaults%ecrh_cd%iwarm) &
write(u, fmt) "iwarm", format_absorp(params%ecrh_cd%iwarm)
if (params%ecrh_cd%ieccd /= defaults%ecrh_cd%ieccd) &
write(u, fmt) "ieccd", format_current(params%ecrh_cd%ieccd)
if (params%ecrh_cd%ilarm /= defaults%ecrh_cd%ilarm) &
write(u, fmt) "ilarm", params%ecrh_cd%ilarm
if (params%ecrh_cd%imx /= defaults%ecrh_cd%imx) &
write(u, fmt) "imx", params%ecrh_cd%imx
write(u, '(/,a)') "[antenna]"
write(u, fmt) "alpha", params%antenna%alpha
write(u, fmt) "beta", params%antenna%beta
if (params%antenna%power /= defaults%antenna%power) &
write(u, fmt) "power", params%antenna%power
write(u, fmt) "iox", format_polar(params%antenna%iox)
write(u, fmt) "ibeam", format_beam(params%antenna%ibeam)
if (params%raytracing%ipol) then
write(u, fmt) "psi", params%antenna%psi
write(u, fmt) "chi", params%antenna%chi
end if
write(u, fmt) "filenm", quote(params%antenna%filenm)
write(u, '(/,a)') "[equilibrium]"
if (params%equilibrium%iequil /= defaults%equilibrium%iequil) &
write(u, fmt) "iequil", format_equil(params%equilibrium%iequil)
write(u, fmt) "filenm", quote(params%equilibrium%filenm)
if (params%equilibrium%icocos /= defaults%equilibrium%icocos) &
write(u, fmt) "icocos", params%equilibrium%icocos
if (params%equilibrium%ipsinorm .neqv. defaults%equilibrium%ipsinorm) &
write(u, fmt) "ipsinorm", format_bool(params%equilibrium%ipsinorm)
if (params%equilibrium%idesc .neqv. defaults%equilibrium%idesc) &
write(u, fmt) "idesc", format_bool(params%equilibrium%idesc)
if (params%equilibrium%ifreefmt .neqv. defaults%equilibrium%ifreefmt) &
write(u, fmt) "ifreefmt", format_bool(params%equilibrium%ifreefmt)
if (params%equilibrium%ixp /= defaults%equilibrium%ixp) &
write(u, fmt) "ixp", format_x_point(params%equilibrium%ixp)
if (params%equilibrium%ssplps /= defaults%equilibrium%ssplps) &
write(u, fmt) "ssplps", params%equilibrium%ssplps
if (params%equilibrium%ssplf /= defaults%equilibrium%ssplf) &
write(u, fmt) "ssplf", params%equilibrium%ssplf
if (params%equilibrium%sgnb /= defaults%equilibrium%sgnb) &
write(u, fmt) "sgnb", params%equilibrium%sgnb
if (params%equilibrium%sgni /= defaults%equilibrium%sgni) &
write(u, fmt) "sgni", params%equilibrium%sgni
if (params%equilibrium%factb /= defaults%equilibrium%factb) &
write(u, fmt) "factb", params%equilibrium%factb
write(u, '(/,a)') "[profiles]"
write(u, fmt) "iprof", format_profiles(params%profiles%iprof)
write(u, fmt) "irho", format_rho(params%profiles%irho)
write(u, fmt) "filenm", quote(params%profiles%filenm)
if (params%profiles%sspld /= defaults%profiles%sspld) &
write(u, fmt) "sspld", params%profiles%sspld
if (params%profiles%factne /= defaults%profiles%factne) &
write(u, fmt) "factne", params%profiles%factne
if (params%profiles%factte /= defaults%profiles%factte) &
write(u, fmt) "factte", params%profiles%factte
if (params%profiles%iscal /= defaults%profiles%iscal) &
write(u, fmt) "iscal", format_scaling(params%profiles%iscal)
if (params%profiles%psnbnd /= defaults%profiles%psnbnd) &
write(u, fmt) "psnbnd", params%profiles%psnbnd
write(u, '(/,a)') "[output]"
if (params%output%ipec /= defaults%output%ipec) &
write(u, fmt) "ipec", format_rho(params%output%ipec)
if (params%output%nrho /= defaults%output%nrho) &
write(u, fmt) "nrho", params%output%nrho
if (params%output%istpr /= defaults%output%istpr) &
write(u, fmt) "istpr", params%output%istpr
if (params%output%istpl /= defaults%output%istpl) &
write(u, fmt) "istpl", params%output%istpl
write(u, '(/,a)') "[misc]"
write(u, fmt) "rwall", params%misc%rwall
end subroutine write_gray_config
! Helper functions for formatting values
pure function format_bool(p) result(str)
logical, intent(in) :: p
character(len=:), allocatable :: str
str = trim(merge("true ", "false", p))
end function
pure function format_step(val) result(str)
integer(kind(step_enum)), intent(in) :: val
character(len=:), allocatable :: str
character(len=*), parameter :: choices(0:2) = &
[character(len=11) :: "ARCLEN", "TIME", "PHASE"]
str = "STEP_" // trim(choices(val))
end function
pure function format_absorp(val) result(str)
integer(kind(absorption_enum)), intent(in) :: val
character(len=:), allocatable :: str
character(len=*), parameter :: choices(0:3) = &
[character(len=8) :: "OFF", "WEAK", "FULL", "FULL_ALT"]
str = "ABSORP_" // trim(choices(val))
end function
pure function format_current(val) result(str)
integer(kind(current_drive_enum)), intent(in) :: val
character(len=:), allocatable :: str
character(len=*), parameter :: choices(0:3) = &
[character(len=10) :: "OFF", "COHEN", "NO_TRAP", "NEOCLASSIC"]
str = "CD_" // trim(choices(val))
end function
pure function format_polar(val) result(str)
integer(kind(polar_enum)), intent(in) :: val
character(len=:), allocatable :: str
str = merge("MODE_O", "MODE_X", val == 1)
end function
pure function format_beam(val) result(str)
integer(kind(beam_enum)), intent(in) :: val
character(len=:), allocatable :: str
character(len=*), parameter :: choices(0:2) = ["0D", "1D", "2D"]
str = "BEAM_" // choices(val)
end function
pure function format_equil(val) result(str)
integer(kind(equil_enum)), intent(in) :: val
character(len=:), allocatable :: str
character(len=*), parameter :: choices(0:3) = &
[character(len=13) :: "VACUUM", "ANALYTICAL", &
"EQDSK_FULL", "EQDSK_PARTIAL"]
str = "EQ_" // trim(choices(val))
end function
pure function format_x_point(val) result(str)
integer(kind(x_point_enum)), intent(in) :: val
character(len=:), allocatable :: str
character(len=*), parameter :: choices(-1:+1) = &
[character(len=10) :: "AT_BOTTOM", "IS_MISSING", "AT_TOP"]
str = "X_" // trim(choices(val))
end function
pure function format_scaling(val) result(str)
integer(kind(scaling_enum)), intent(in) :: val
character(len=:), allocatable :: str
character(len=*), parameter :: choices(0:2) = &
[character(len=9) :: "COLLISION", "GREENWALD", "OFF"]
str = "SCALE_" // trim(choices(val))
end function
pure function format_rho(val) result(str)
integer(kind(rho_enum)), intent(in) :: val
character(len=:), allocatable :: str
character(len=*), parameter :: choices(0:2) = ["TOR", "POL", "PSI"]
str = "RHO_" // trim(choices(val))
end function
pure function format_profiles(val) result(str)
integer(kind(profiles_enum)), intent(in) :: val
character(len=:), allocatable :: str
str = "PROF_" // trim(merge("ANALYTIC", "NUMERIC ", val == 0))
end function
pure function quote(str) result(quoted)
character(*), intent(in) :: str
character(len=:), allocatable :: quoted
quoted = '"' // trim(str) // '"'
end function
end program