Compare commits

..

1 Commits
master ... next

Author SHA1 Message Date
Michele Guerini Rocco
83a9ca1c9a
src/gray_core.f90: refactor [wip] 2025-01-14 17:12:41 +01:00
10 changed files with 667 additions and 1217 deletions

View File

@ -33,7 +33,7 @@ let
src = builtins.filterSource sieve ./.; src = builtins.filterSource sieve ./.;
format = "other"; format = "other";
propagatedBuildInputs = with pkgs.python3Packages; [ numpy scipy matplotlib ]; propagatedBuildInputs = with pkgs.python3Packages; [ numpy matplotlib ];
makeFlags = [ "PREFIX=$(out)" ]; makeFlags = [ "PREFIX=$(out)" ];
dontConfigure = true; dontConfigure = true;

View File

@ -58,7 +58,7 @@ def read_eqdsk(filepath: Path) -> Eqdsk:
skip(file, nr * 4) skip(file, nr * 4)
# read flux and safety factor # read flux and safety factor
psi = read(file, nr * nz).reshape((nr, nz), order='F').T psi = read(file, nr * nz).reshape(nr, nz)
q = read(file, nr) q = read(file, nr)
# normalise flux # normalise flux

View File

@ -39,20 +39,6 @@ def cli_args() -> argparse.Namespace:
return parser.parse_args() return parser.parse_args()
def placeholder(ax: plt.Axes, text: str):
'''
Puts a placeholder text at the center of an axis
'''
left, width = .25, .5
bottom, height = .25, .5
right = left + width
top = bottom + height
ax.text(0.5*(left+right), 0.5*(top+bottom), text,
horizontalalignment='center',
verticalalignment='center')
def align_yaxis(*axes: [plt.Axes]): def align_yaxis(*axes: [plt.Axes]):
''' '''
Aligns the origins of two axes Aligns the origins of two axes
@ -130,7 +116,6 @@ def plot_poloidal(inputs: Path, outputs: Path, ax: plt.Axes):
ax.set_ylabel('$z$ / m') ax.set_ylabel('$z$ / m')
# load flux surfaces # load flux surfaces
try:
surfaces = gray.read_table(outputs / 'flux-surfaces.71.txt') surfaces = gray.read_table(outputs / 'flux-surfaces.71.txt')
surfaces = surfaces.reshape(-1, int(surfaces['i'].max())) surfaces = surfaces.reshape(-1, int(surfaces['i'].max()))
@ -155,8 +140,6 @@ def plot_poloidal(inputs: Path, outputs: Path, ax: plt.Axes):
fontsize=10, fmt={1: label}) fontsize=10, fmt={1: label})
ax.plot(np.nan, np.nan, '--', color='xkcd:ocean blue', ax.plot(np.nan, np.nan, '--', color='xkcd:ocean blue',
label='rational surfaces') label='rational surfaces')
except FileNotFoundError:
pass
# load limiter # load limiter
limiter = gray.get_limiter(conf, inputs) limiter = gray.get_limiter(conf, inputs)
@ -203,15 +186,12 @@ def plot_toroidal(inputs: Path, outputs: Path, ax: plt.Axes):
limiter = gray.get_limiter(conf, inputs) limiter = gray.get_limiter(conf, inputs)
# plot plasma boundary # plot plasma boundary
try:
surfaces = gray.read_table(outputs / 'flux-surfaces.71.txt') surfaces = gray.read_table(outputs / 'flux-surfaces.71.txt')
boundary = surfaces[np.isclose(surfaces['ψ_n'], 1, 1e-3)] boundary = surfaces[np.isclose(surfaces['ψ_n'], 1, 1e-3)]
# plot plasma boundary # plot plasma boundary
plot_circle(ax, radius=boundary['R'].min(), color='xkcd:slate gray') plot_circle(ax, radius=boundary['R'].min(), color='xkcd:slate gray')
plot_circle(ax, radius=boundary['R'].max(), color='xkcd:slate gray') plot_circle(ax, radius=boundary['R'].max(), color='xkcd:slate gray')
except FileNotFoundError:
pass
# plot limiter # plot limiter
if limiter[0].size > 0: if limiter[0].size > 0:
@ -394,30 +374,23 @@ def plot_inputs(inputs: Path, outputs: Path, axes: [plt.Axes]):
''' '''
from matplotlib.colors import TwoSlopeNorm from matplotlib.colors import TwoSlopeNorm
conf = gray.read_conf(inputs / 'gray.ini')
try:
maps = gray.read_table(outputs / 'inputs-maps.72.txt') maps = gray.read_table(outputs / 'inputs-maps.72.txt')
# filter valid points # filter valid points
maps = maps[maps['ψ_n'] > 0] maps = maps[maps['ψ_n'] > 0]
flux = maps['R'], maps['z'], maps['ψ_n'] flux = maps['R'], maps['z'], maps['ψ_n']
except FileNotFoundError:
maps = None
placeholder(axes['B'], 'inputs-maps.72.txt not found')
# contour levels # contour levels
ψ_max = maps['ψ_n'].max() if maps is not None else 1.2
inner_levels = np.linspace(0, 0.99, 8) inner_levels = np.linspace(0, 0.99, 8)
outer_levels = np.linspace(0.9991, ψ_max*0.99, 6) outer_levels = np.linspace(0.9991, maps['ψ_n'].max()*0.99, 6)
all_levels = np.concatenate([inner_levels, outer_levels]) all_levels = np.concatenate([inner_levels, outer_levels])
# contour style # contour style
norm = TwoSlopeNorm(vmin=0, vcenter=1, vmax=ψ_max) norm = TwoSlopeNorm(vmin=0, vcenter=1, vmax=maps['ψ_n'].max())
cmap = plt.cm.RdYlGn_r cmap = plt.cm.RdYlGn_r
borders = dict(colors='xkcd:grey', linestyles='-', linewidths=0.8) borders = dict(colors='xkcd:grey', linestyles='-', linewidths=0.8)
# interpolated equilibrium # interpolated equilibrium
if maps is not None:
interp = axes['B'] interp = axes['B']
interp.set_title('poloidal flux', loc='right') interp.set_title('poloidal flux', loc='right')
interp.set_xlabel('$R$ / m') interp.set_xlabel('$R$ / m')
@ -428,6 +401,7 @@ def plot_inputs(inputs: Path, outputs: Path, axes: [plt.Axes]):
interp.plot(np.nan, np.nan, c='xkcd:slate gray', label='plasma boundary') interp.plot(np.nan, np.nan, c='xkcd:slate gray', label='plasma boundary')
# add limiter # add limiter
conf = gray.read_conf(inputs / 'gray.ini')
limiter = gray.get_limiter(conf, inputs) limiter = gray.get_limiter(conf, inputs)
interp.plot(*limiter, c='xkcd:black', label='limiter') interp.plot(*limiter, c='xkcd:black', label='limiter')
@ -444,18 +418,14 @@ def plot_inputs(inputs: Path, outputs: Path, axes: [plt.Axes]):
orig.plot(*eqdsk.limiter, c='xkcd:black') orig.plot(*eqdsk.limiter, c='xkcd:black')
orig.plot(*eqdsk.boundary, c='xkcd:slate gray') orig.plot(*eqdsk.boundary, c='xkcd:slate gray')
else: else:
placeholder(orig, 'not an EQDSK') orig.axis('off')
# colorbar # colorbar
bar = plt.colorbar(plt.cm.ScalarMappable(norm, cmap), cax=axes['C']) bar = plt.colorbar(plt.cm.ScalarMappable(norm, cmap), cax=axes['C'])
bar.set_label(label='normalised poloidal flux', labelpad=10) bar.set_label(label='normalised poloidal flux', labelpad=10)
# Plasma radial profiles # Plasma radial profiles
try:
profiles = gray.read_table(outputs / 'kinetic-profiles.55.txt') profiles = gray.read_table(outputs / 'kinetic-profiles.55.txt')
except FileNotFoundError:
placeholder(axes['D'], 'kinetic-profiles.55.txt not found')
return
axes['D'].set_title('plasma profiles', loc='right') axes['D'].set_title('plasma profiles', loc='right')
add_alt_axis(axes['D'], profiles['ρ_t'], profiles['ψ_n']**0.5, add_alt_axis(axes['D'], profiles['ρ_t'], profiles['ψ_n']**0.5,

File diff suppressed because it is too large Load Diff

View File

@ -138,7 +138,7 @@ module gray_params
real(wp_) :: dst ! Integration step size real(wp_) :: dst ! Integration step size
real(wp_) :: rwmax = 1 ! Normalized maximum radius of beam power real(wp_) :: rwmax = 1 ! Normalized maximum radius of beam power
integer :: nray, nrayr, nrayth ! Total/radial/angular number of rays integer :: nray, nrayr, nrayth ! Total/radial/angular number of rays
integer :: igrad = 0 ! Complex eikonal switch logical :: igrad = .false. ! Complex eikonal switch
integer :: nstep = 12000 ! Max number of integration steps integer :: nstep = 12000 ! Max number of integration steps
integer(kind(step_enum)) :: idst = STEP_TIME ! Choice of the integration variable integer(kind(step_enum)) :: idst = STEP_TIME ! Choice of the integration variable
integer :: ipass = 1 ! Number of plasma passes integer :: ipass = 1 ! Number of plasma passes
@ -341,7 +341,7 @@ contains
call append(header, line) call append(header, line)
! code parameters ! code parameters
write(line, '("# COD igrad idst ipass ipol:",3(1x,i4),1x,l4)') & write(line, '("# COD igrad idst ipass ipol:",l4,2(1x,i4),1x,l4)') &
params%raytracing%igrad, params%raytracing%idst, & params%raytracing%igrad, params%raytracing%idst, &
params%raytracing%ipass, params%raytracing%ipol params%raytracing%ipass, params%raytracing%ipol
call append(header, line) call append(header, line)

View File

@ -21,7 +21,7 @@ module gray_plasma
end type end type
abstract interface abstract interface
subroutine density_sub(self, psin, dens, ddens) pure subroutine density_sub(self, psin, dens, ddens)
! Computes the density its first derivative as a function of ! Computes the density its first derivative as a function of
! normalised poloidal flux. ! normalised poloidal flux.
! !
@ -32,7 +32,7 @@ module gray_plasma
real(wp_), intent(out) :: dens, ddens ! density and first derivative real(wp_), intent(out) :: dens, ddens ! density and first derivative
end subroutine density_sub end subroutine density_sub
function temp_fun(self, psin) result(temp) pure function temp_fun(self, psin) result(temp)
! Computes the temperature as a function of the ! Computes the temperature as a function of the
! normalised poloidal flux. ! normalised poloidal flux.
! !
@ -43,7 +43,7 @@ module gray_plasma
real(wp_) :: temp real(wp_) :: temp
end function temp_fun end function temp_fun
function zeff_fun(self, psin) result(zeff) pure function zeff_fun(self, psin) result(zeff)
! Computes the effective charge Z_eff as a ! Computes the effective charge Z_eff as a
! function of the normalised poloidal flux. ! function of the normalised poloidal flux.
import :: abstract_plasma, wp_ import :: abstract_plasma, wp_
@ -97,7 +97,7 @@ module gray_plasma
contains contains
subroutine analytic_density(self, psin, dens, ddens) pure subroutine analytic_density(self, psin, dens, ddens)
! subroutine arguments ! subroutine arguments
class(analytic_plasma), intent(in) :: self class(analytic_plasma), intent(in) :: self
real(wp_), intent(in) :: psin ! normalised poloidal flux real(wp_), intent(in) :: psin ! normalised poloidal flux
@ -116,7 +116,7 @@ contains
end subroutine analytic_density end subroutine analytic_density
function analytic_temp(self, psin) result(temp) pure function analytic_temp(self, psin) result(temp)
! function arguments ! function arguments
class(analytic_plasma), intent(in) :: self class(analytic_plasma), intent(in) :: self
real(wp_), intent(in) :: psin real(wp_), intent(in) :: psin
@ -139,7 +139,7 @@ contains
end function analytic_temp end function analytic_temp
function analytic_zeff(self, psin) result(zeff) pure function analytic_zeff(self, psin) result(zeff)
! function arguments ! function arguments
class(analytic_plasma), intent(in) :: self class(analytic_plasma), intent(in) :: self
real(wp_), intent(in) :: psin real(wp_), intent(in) :: psin
@ -155,7 +155,7 @@ contains
end function analytic_zeff end function analytic_zeff
subroutine numeric_density(self, psin, dens, ddens) pure subroutine numeric_density(self, psin, dens, ddens)
use logger, only : log_error use logger, only : log_error
! subroutine arguments ! subroutine arguments
@ -221,16 +221,16 @@ contains
end block end block
end if end if
if (dens < 0) then ! if (dens < 0) then
write (msg, '("negative density:", 2(x,a,"=",g0.3))') & ! write (msg, '("negative density:", 2(x,a,"=",g0.3))') &
'ne', dens, 'ψ', psin ! 'ne', dens, 'ψ', psin
call log_error(msg, mod='coreprofiles', proc='density') ! call log_error(msg, mod='coreprofiles', proc='density')
end if ! end if
end subroutine numeric_density end subroutine numeric_density
function numeric_temp(self, psin) result(temp) pure function numeric_temp(self, psin) result(temp)
! function arguments ! function arguments
class(numeric_plasma), intent(in) :: self class(numeric_plasma), intent(in) :: self
real(wp_), intent(in) :: psin real(wp_), intent(in) :: psin
@ -246,7 +246,7 @@ contains
end function numeric_temp end function numeric_temp
function numeric_zeff(self, psin) result(zeff) pure function numeric_zeff(self, psin) result(zeff)
! function arguments ! function arguments
class(numeric_plasma), intent(in) :: self class(numeric_plasma), intent(in) :: self
real(wp_), intent(in) :: psin real(wp_), intent(in) :: psin

View File

@ -121,7 +121,7 @@ contains
real(wp_) :: rho_t, J_phi, dens, ddens real(wp_) :: rho_t, J_phi, dens, ddens
real(wp_) :: psi_n, rho_p, drho_p real(wp_) :: psi_n, rho_p, drho_p
call tbl%init(title='kinetic-profiles', id=55, active=is_active(params, 55), & call tbl%init(title='kinetic-profiles', id=55, active=is_active(params, 25), &
labels=[character(64) :: 'ψ_n', 'ρ_t', 'n_e', 'T_e', 'q', 'J_φ']) labels=[character(64) :: 'ψ_n', 'ρ_t', 'n_e', 'T_e', 'q', 'J_φ'])
if (.not. tbl%active) return if (.not. tbl%active) return

View File

@ -77,10 +77,10 @@ program main
! Do some checks on the inputs ! Do some checks on the inputs
associate (p => params%raytracing) associate (p => params%raytracing)
if (p%igrad == 1 .and. p%nrayr < 5) then if (p%igrad .and. p%nrayr < 5) then
p%igrad = 0 p%igrad = .false.
call log_message(level=WARNING, mod='main', & call log_message(level=WARNING, mod='main', &
msg='igrad = 1 but nrayr < 5: disabling beamtracing') msg='igrad = .true. but nrayr < 5: disabling beamtracing')
end if end if
if (p%nrayr == 1) p%nrayth = 1 if (p%nrayr == 1) p%nrayth = 1

View File

@ -156,8 +156,8 @@ contains
write(u, fmt) "nrayth", params%raytracing%nrayth write(u, fmt) "nrayth", params%raytracing%nrayth
if (params%raytracing%rwmax /= defaults%raytracing%rwmax) & if (params%raytracing%rwmax /= defaults%raytracing%rwmax) &
write(u, fmt) "rwmax", params%raytracing%rwmax write(u, fmt) "rwmax", params%raytracing%rwmax
if (params%raytracing%igrad /= defaults%raytracing%igrad) & if (params%raytracing%igrad .neqv. defaults%raytracing%igrad) &
write(u, fmt) "igrad", params%raytracing%igrad write(u, fmt) "igrad", format_bool(params%raytracing%igrad)
if (params%raytracing%ipass /= defaults%raytracing%ipass) & if (params%raytracing%ipass /= defaults%raytracing%ipass) &
write(u, fmt) "ipass", params%raytracing%ipass write(u, fmt) "ipass", params%raytracing%ipass
if (params%raytracing%ipol .neqv. defaults%raytracing%ipol) & if (params%raytracing%ipol .neqv. defaults%raytracing%ipol) &

View File

@ -1,7 +1,7 @@
[raytracing] [raytracing]
nrayr = 11 nrayr = 11
nrayth = 16 nrayth = 16
igrad = 1 igrad = true
dst = 0.1 dst = 0.1
nstep = 8000 nstep = 8000