Input file
This should not have been a single commit. Now we have input files. Also, I've restructured the code and renamed modules.
This commit is contained in:
parent
0c27b98e2e
commit
50b4258c8f
22 changed files with 446 additions and 251 deletions
16
src/makefile
Normal file
16
src/makefile
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
OBJECTS = $(OBJDIR)/constantParameters.o \
|
||||
$(OBJDIR)/input.o \
|
||||
$(OBJDIR)/output.o \
|
||||
$(OBJDIR)/referenceValues.o \
|
||||
$(OBJDIR)/tableBoundary.o \
|
||||
$(OBJDIR)/tableTNZ.o
|
||||
|
||||
|
||||
all: $(OUTPUT)
|
||||
|
||||
$(OUTPUT): modules.o $(OUTPUT).f90
|
||||
$(FC) $(FCFLAGS) -o $(OBJDIR)/$(OUTPUT).o -c $(OUTPUT).f90
|
||||
$(FC) $(FCFLAGS) -o $(TOPDIR)/$(OUTPUT) $(OBJECTS) $(OBJDIR)/$(OUTPUT).o -lopenblas
|
||||
|
||||
modules.o:
|
||||
$(MAKE) -C modules all
|
||||
18
src/modules/constantParameters.f90
Normal file
18
src/modules/constantParameters.f90
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
!Physical and mathematical constants
|
||||
module constantParameters
|
||||
implicit none
|
||||
|
||||
public
|
||||
|
||||
integer, parameter:: dp = kind(0.d0) ! Precision
|
||||
real(dp), parameter:: PI = 4.0_dp*ATAN(1.0_dp) ! Number pi
|
||||
real(dp), parameter:: qe = 1.60217662e-19_dp ! Elementary charge
|
||||
real(dp), parameter:: kb = 1.38064852e-23_dp ! Boltzmann constants SI
|
||||
real(dp), parameter:: eV2J = qe ! Electron volt to Joule conversion
|
||||
real(dp), parameter:: eps_0 = 8.8542e-12_dp ! Epsilon_0
|
||||
|
||||
real(dp), parameter:: eV_to_K = 11604.5_dp ! Convert eV to K
|
||||
real(dp), parameter:: cm3_to_m3 = 1.0e6_dp ! Convert cm^-3 to m^-3
|
||||
|
||||
end module constantParameters
|
||||
|
||||
142
src/modules/input.f90
Normal file
142
src/modules/input.f90
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
module input
|
||||
use constantParameters, only: dp
|
||||
implicit none
|
||||
|
||||
character(:), allocatable:: inputFile
|
||||
integer:: inputFile_id, inputFile_io
|
||||
|
||||
|
||||
contains
|
||||
subroutine openInputFile()
|
||||
|
||||
inquire(file=inputFile, iostat=inputfile_io)
|
||||
|
||||
if (inputFile_io /= 0) then
|
||||
write (*, '("Error: input file ", a, " does not exist")') inputFile
|
||||
return
|
||||
|
||||
end if
|
||||
|
||||
open(action='read', file=inputFile, iostat=inputFile_io, newunit=inputFile_id)
|
||||
|
||||
end subroutine openInputFile
|
||||
|
||||
subroutine readReference()
|
||||
use constantParameters, only: dp, kb, qe, eps_0, ev_to_K, cm3_to_m3, PI
|
||||
use referenceValues
|
||||
|
||||
namelist /reference/ m_ref, Temp_ref, n_ref
|
||||
|
||||
read(nml=reference, unit=inputFile_id, iostat=inputFile_io)
|
||||
|
||||
! Set reference numbers (in SI units)
|
||||
Temp_ref = Temp_ref * eV_to_K
|
||||
n_ref = n_ref
|
||||
t_ref = sqrt(eps_0 * m_ref / (n_ref * 1.0_dp * qe**2)) ! 1.0_dp represents Z = 1 for reference values
|
||||
u_ref = sqrt(kb * Temp_ref / m_ref)
|
||||
L_ref = u_ref * t_ref
|
||||
phi_ref = kb * Temp_ref / qe
|
||||
|
||||
end subroutine readReference
|
||||
|
||||
subroutine readGrid(r0, rf, dr, v0, vf, nv)
|
||||
use referenceValues, only: L_ref, u_ref
|
||||
|
||||
real(dp), intent(out):: r0, rf, dr
|
||||
real(dp), intent(out):: v0, vf
|
||||
integer, intent(out):: nv
|
||||
namelist /grid/ r0, rf, dr, v0, vf, nv
|
||||
|
||||
read(nml=grid, unit=inputFile_id, iostat=inputFile_io)
|
||||
|
||||
r0 = r0/L_ref
|
||||
rf = rf/L_ref
|
||||
dr = dr/L_ref
|
||||
|
||||
v0 = v0/u_ref
|
||||
vf = vf/u_ref
|
||||
|
||||
end subroutine readGrid
|
||||
|
||||
subroutine readTime(t0, tf, CFL)
|
||||
use referenceValues, only: t_ref
|
||||
|
||||
real(dp), intent(out):: t0, tf, CFL
|
||||
|
||||
namelist /time/ t0, tf, CFL
|
||||
|
||||
read(nml=time, unit=inputFile_id, iostat=inputFile_io)
|
||||
|
||||
t0 = t0/t_ref
|
||||
tf = tf/t_ref
|
||||
|
||||
end subroutine readTime
|
||||
|
||||
subroutine readDetector(rCum)
|
||||
use referenceValues, only: L_ref
|
||||
|
||||
real(dp), intent(out):: rCum
|
||||
namelist /detector/ rCum
|
||||
|
||||
read(nml=detector, unit=inputFile_id, iostat=inputFile_io)
|
||||
|
||||
! Set position to calculate cumulative sum of f (non-dimensional units)
|
||||
rCum = rCum/L_ref
|
||||
|
||||
end subroutine readDetector
|
||||
|
||||
subroutine readBoundary(bc)
|
||||
use tableBoundary
|
||||
|
||||
type(tableBC), intent(out):: bc
|
||||
character(len=128):: filename
|
||||
character(:), allocatable:: filename_dynamic ! Needed to pass as an argument, might delete
|
||||
namelist /boundary/ filename
|
||||
|
||||
read(nml=boundary, unit=inputFile_id, iostat=inputFile_io)
|
||||
|
||||
filename_dynamic = trim(filename)
|
||||
|
||||
call bc%init(filename_dynamic)
|
||||
|
||||
end subroutine readBoundary
|
||||
subroutine readZ(Zlist, nz, Tene_to_Z)
|
||||
use tableTNZ
|
||||
|
||||
real(dp), allocatable, intent(out):: Zlist(:)
|
||||
integer, intent(out):: nz
|
||||
type(tableTn_to_Z), intent(out):: Tene_to_Z
|
||||
real(dp), allocatable:: ZList_dummy(:)
|
||||
character(len=128):: filename
|
||||
character(:), allocatable:: filename_dynamic ! Needed to pass as an argument, might delete
|
||||
namelist /Zbins/ ZList, filename
|
||||
|
||||
! List of dummy size
|
||||
allocate(ZList(1:99))
|
||||
ZList = -1.0_dp
|
||||
|
||||
! Read namelist
|
||||
read(nml=Zbins, unit=inputFile_id, iostat=inputFile_io)
|
||||
|
||||
! Get the real Z bins
|
||||
nz = count(ZList > 0.0_dp)
|
||||
allocate(ZList_dummy(1:nz))
|
||||
ZList_dummy = ZList(1:nz)
|
||||
|
||||
! Copy to final list
|
||||
deallocate(ZList)
|
||||
ZList = ZList_dummy
|
||||
deallocate(ZList_dummy)
|
||||
|
||||
filename_dynamic = trim(filename)
|
||||
call Tene_to_Z%init(filename_dynamic)
|
||||
|
||||
end subroutine readZ
|
||||
|
||||
subroutine closeInputFile()
|
||||
|
||||
close(inputFile_id)
|
||||
|
||||
end subroutine closeInputFile
|
||||
|
||||
end module input
|
||||
15
src/modules/makefile
Normal file
15
src/modules/makefile
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
OBJS = constantParameters.o \
|
||||
input.o \
|
||||
output.o \
|
||||
referenceValues.o \
|
||||
tableBoundary.o \
|
||||
tableTNZ.o
|
||||
|
||||
all: $(OBJS)
|
||||
|
||||
input.o: referenceValues.o tableBoundary.o tableTNZ.o input.f90
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
||||
|
||||
%.o: %.f90
|
||||
$(FC) $(FCFLAGS) -c $< -o $(OBJDIR)/$@
|
||||
|
||||
310
src/modules/output.f90
Normal file
310
src/modules/output.f90
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
module output
|
||||
use constantParameters, only: dp
|
||||
implicit none
|
||||
|
||||
public
|
||||
private:: dataRef_id, dataBC_id, dataF_id, dataPhi_id, dataCum_id
|
||||
private:: formatFloat, formatSep, formatTime
|
||||
|
||||
integer:: everyOutput, everyWrite
|
||||
character(:), allocatable:: pathOutput
|
||||
integer, parameter:: dataRef_id = 10
|
||||
integer, parameter:: dataBC_id = 20
|
||||
integer, parameter:: dataF_id = 30
|
||||
integer, parameter:: dataPhi_id = 40
|
||||
integer, parameter:: dataCum_id = 50
|
||||
integer, parameter:: dataTime_id = 60
|
||||
character(len=*), parameter :: formatInt = 'I0'
|
||||
character(len=7), parameter:: formatFloat = 'ES0.6e3'
|
||||
character(len=3), parameter:: formatSep = '","'
|
||||
character(len=7):: formatTime
|
||||
|
||||
contains
|
||||
subroutine setTimeFormat(nt)
|
||||
integer, intent(in):: nt
|
||||
integer:: l
|
||||
|
||||
l=max(1,ceiling(log10(real(nt))))
|
||||
write(formatTime, '(A2,I0,".",I0,A1)') '(I',l,l,')'
|
||||
|
||||
end subroutine setTimeFormat
|
||||
|
||||
function setZFormat(Z) result(ZString)
|
||||
real(dp), intent(in):: Z
|
||||
character(len=4):: ZString
|
||||
|
||||
write(ZString, '(F4.1)') Z
|
||||
|
||||
end function setZFormat
|
||||
|
||||
subroutine createPath()
|
||||
character(8) :: date_now
|
||||
character(10) :: time_now
|
||||
|
||||
call date_and_time(date_now, time_now)
|
||||
|
||||
!Compose the folder name
|
||||
pathOutput = date_now(1:4) // '-' // date_now(5:6) // '-' // date_now(7:8) // '_' // &
|
||||
time_now(1:2) // '.' // time_now(3:4) // '.' // time_now(5:6) // '/'
|
||||
|
||||
call system('mkdir ' // pathOutput)
|
||||
|
||||
end subroutine createPath
|
||||
|
||||
subroutine writeOutputF(t, dt, nz, nr, r, nv, v, f, Z_list)
|
||||
use referenceValues, only: L_ref, n_ref, u_ref, t_ref
|
||||
|
||||
integer, intent(in):: t
|
||||
integer, intent(in):: nz, nr, nv
|
||||
real(dp), intent(in):: dt
|
||||
real(dp), intent(in):: r(1:nr)
|
||||
real(dp), intent(in):: v(1:nv)
|
||||
real(dp), intent(in):: f(1:nr,1:nv)
|
||||
real(dp), intent(in):: Z_list(1:nz)
|
||||
character(len=30) :: myfmt
|
||||
character(:), allocatable:: filename
|
||||
integer:: i, j
|
||||
character(len=10):: timeString
|
||||
character(len=4) :: ZString
|
||||
|
||||
do j = 1, nz
|
||||
write (timeString, formatTime) t
|
||||
ZString = setZFormat(Z_list(j))
|
||||
|
||||
filename = 'time_' // trim(timeString) // '_Z_' // trim(adjustl(ZString)) // '_f_i.csv'
|
||||
write (*, '(A, A)') 'Writing: ', filename
|
||||
|
||||
open(unit=dataF_id, file=pathOutput // filename)
|
||||
write(dataF_id, '(A)') "t (s)"
|
||||
write(dataF_id, '('//formatFloat//')') t*dt*t_ref
|
||||
write(dataF_id, '(A)') "Z"
|
||||
write(dataF_id, '('//formatFloat//')') Z_list(j)
|
||||
write(myfmt, "(I0)") nr
|
||||
myfmt = '(A,' // trim(myfmt) // '(' // formatSep // ',' // formatFloat // '))'
|
||||
write(dataF_id, myfmt) "v (m/s) / r (m)", r*L_ref
|
||||
write(myfmt, "(I0)") nr
|
||||
myfmt = '(' // formatFloat // ',' // trim(myfmt) // '(' // formatSep // ',' // formatFloat // '))'
|
||||
do i = 1, nv
|
||||
write(dataF_id, myfmt) v(i)*u_ref, f(:,i)*n_ref/u_ref
|
||||
|
||||
end do
|
||||
|
||||
close(unit=dataF_id)
|
||||
end do
|
||||
|
||||
end subroutine writeOutputF
|
||||
|
||||
subroutine writeOutputPhi(t, dt, nr, r, phi, E, n_e)
|
||||
use constantParameters, only: eV_to_K
|
||||
use referenceValues, only: L_ref, phi_ref, t_ref, n_ref
|
||||
|
||||
integer, intent(in):: t
|
||||
integer, intent(in):: nr
|
||||
real(dp), intent(in):: dt
|
||||
real(dp), intent(in):: r(1:nr)
|
||||
real(dp), intent(in):: phi(1:nr)
|
||||
real(dp), intent(in):: E(1:nr)
|
||||
real(dp), intent(in):: n_e(1:nr)
|
||||
character(:), allocatable:: filename
|
||||
integer:: i
|
||||
character(len=10):: timeString
|
||||
|
||||
write (timeString, formatTime) t
|
||||
filename = 'time_' // trim(timeString)//'_phi.csv'
|
||||
write (*, '(A, A)') 'Writing: ', filename
|
||||
|
||||
open(unit=dataPhi_id, file=pathOutput//filename)
|
||||
write(dataPhi_id, '(A)') "t (s)"
|
||||
write(dataPhi_id, '('//formatFloat//')') t*dt*t_ref
|
||||
write(dataPhi_id, '(A,3('//formatSep//',A))') "r (m)","phi (V)","E (V m^-1)","n_e (m^-3)"
|
||||
do i = 1, nr
|
||||
write(dataPhi_id, '('//formatFloat//',3('//formatSep //','//formatFloat//'))') &
|
||||
r(i)*L_ref, &
|
||||
phi(i)*phi_ref, &
|
||||
E(i)*phi_ref/L_ref, &
|
||||
n_e(i)*n_ref
|
||||
|
||||
end do
|
||||
|
||||
close(unit=dataPhi_id)
|
||||
|
||||
end subroutine writeOutputPhi
|
||||
|
||||
subroutine writeOutputMom(t, dt, nz, nr, r, n_i, u_i, T_i, Z_list)
|
||||
use constantParameters, only: eV_to_K
|
||||
use referenceValues, only: L_ref, t_ref, n_ref, u_ref, Temp_ref
|
||||
|
||||
integer, intent(in):: t
|
||||
integer, intent(in):: nr
|
||||
integer, intent(in):: nz
|
||||
real(dp), intent(in):: dt
|
||||
real(dp), intent(in):: r(1:nr)
|
||||
real(dp), intent(in):: n_i(1:nz,1:nr)
|
||||
real(dp), intent(in):: u_i(1:nz,1:nr)
|
||||
real(dp), intent(in):: T_i(1:nz,1:nr)
|
||||
real(dp), intent(in):: Z_list(1:nz)
|
||||
character(:), allocatable:: filename
|
||||
integer:: i
|
||||
integer:: j
|
||||
character(len=10):: timeString
|
||||
character(len=4) :: ZString
|
||||
|
||||
do j = 1, nz
|
||||
write (timeString, formatTime) t
|
||||
ZString = setZFormat(Z_list(j))
|
||||
|
||||
filename = 'time_' // trim(timeString) // '_Z_' // trim(adjustl(ZString)) // '_mom_i.csv'
|
||||
write (*, '(A, A)') 'Writing: ', filename
|
||||
|
||||
open(unit=dataPhi_id, file=pathOutput//filename)
|
||||
write(dataPhi_id, '(A)') "t (s)"
|
||||
write(dataPhi_id, '('//formatFloat//')') t*dt*t_ref
|
||||
write(dataPhi_id, '(A)') "Z"
|
||||
write(dataPhi_id, '('//formatFloat//')') Z_list(j)
|
||||
write(dataPhi_id, '(A,3('//formatSep//',A))') "r (m)","n_i (m^-3)","u_i (m s^-1)", "T_i (eV)"
|
||||
do i = 1, nr
|
||||
write(dataPhi_id, '('//formatFloat//',3('//formatSep //','//formatFloat//'))') &
|
||||
r(i)*L_ref, &
|
||||
n_i(j,i)*n_ref, &
|
||||
u_i(j,i)*u_ref, &
|
||||
T_i(j,i)*Temp_ref/ev_to_K
|
||||
|
||||
end do
|
||||
|
||||
close(unit=dataPhi_id)
|
||||
end do
|
||||
end subroutine writeOutputMom
|
||||
|
||||
subroutine writeOutputBoundary(t, dt, n, u, Temp, Z_Tne, Zinj)
|
||||
use constantParameters, only: eV_to_K
|
||||
use referenceValues, only: t_ref, n_ref, u_ref, Temp_ref
|
||||
|
||||
integer, intent(in):: t
|
||||
real(dp), intent(in):: dt
|
||||
real(dp), intent(in):: n, u, Temp, Z_Tne, Zinj
|
||||
character(len=6), parameter:: filename = 'bc.csv'
|
||||
logical:: res
|
||||
|
||||
inquire(file=pathOutput // filename, exist=res)
|
||||
if (.not. res) then
|
||||
write (*, '(A, A)') 'Writing: ', filename
|
||||
open(unit=dataBC_id, file=pathOutput // filename, action='write', position='append')
|
||||
write(dataBC_id, '(A,5(' // formatSep // ',A))') 't (s)', 'n_i (m^-3)', 'u_i (m s^-1)', 'T_i (eV)', 'Zinj','Z_Tne'
|
||||
close(dataBC_id)
|
||||
|
||||
end if
|
||||
|
||||
open(unit=dataBC_id, file=pathOutput // filename, action='write', position='append')
|
||||
write(dataBC_id, '(' // formatFloat // ',5('// formatSep // ',' // formatFloat // '))') &
|
||||
t*dt*t_ref, n*n_ref, u*u_ref, Temp*Temp_ref/eV_to_K, Zinj, Z_Tne
|
||||
|
||||
close(dataBC_id)
|
||||
|
||||
end subroutine writeOutputBoundary
|
||||
|
||||
! JG: What is this procedure?
|
||||
! subroutine writeOutputTime(t, time, bins)
|
||||
! integer, intent(in):: t
|
||||
! real(dp), intent(in):: time
|
||||
! real(dp), intent(in):: bins
|
||||
! character(len=8), parameter:: filename = 'time.csv'
|
||||
! logical:: res
|
||||
!
|
||||
! inquire(file=pathOutput // filename, exist=res)
|
||||
! if (.not. res) then
|
||||
! write (*, '(A, A)') 'Writing: ', filename
|
||||
! open(unit=dataTime_id, file=pathOutput // filename, action='write', position='append')
|
||||
! write(dataTime_id, '(A,2(' // formatSep // ',A))') 'timestep', 'duration (s)', '#bins'
|
||||
! close(dataTime_id)
|
||||
!
|
||||
! end if
|
||||
!
|
||||
! open(unit=dataTime_id, file=pathOutput // filename, action='write', position='append')
|
||||
! write(dataTime_id, '(' // formatInt // ',2('// formatSep // ',' // formatFloat // '))') &
|
||||
! t, time, bins
|
||||
!
|
||||
! close(dataTime_id)
|
||||
!
|
||||
! end subroutine writeOutputTime
|
||||
|
||||
subroutine writeOutputZList(nz, Z_list)
|
||||
integer, intent(in):: nz
|
||||
real(dp), intent(in):: Z_list(1:nz)
|
||||
character(:), allocatable:: filename
|
||||
integer:: i
|
||||
|
||||
filename = 'ZList.csv'
|
||||
write (*, '(A, A)') 'Writing: ', filename
|
||||
open(unit=dataPhi_id, file=pathOutput//filename)
|
||||
write(dataPhi_id, '(A)') "Z_list"
|
||||
do i = 1, nz
|
||||
write(dataPhi_id, '('//formatFloat//')') Z_list(i)
|
||||
|
||||
end do
|
||||
close(unit=dataPhi_id)
|
||||
|
||||
end subroutine writeOutputZList
|
||||
|
||||
subroutine writeOutputRef()
|
||||
use referenceValues, only: t_ref, L_ref, n_ref, u_ref, Temp_ref, phi_ref
|
||||
use constantParameters, only: eV_to_K
|
||||
|
||||
character(len=7), parameter:: filename = 'ref.csv'
|
||||
|
||||
write (*, '(A, A)') 'Writing: ', filename
|
||||
open(unit=dataRef_id, file=pathOutput // filename)
|
||||
write(dataRef_id, '(A,5(' // formatSep // ',A))') 't_ref (s)', 'L_ref (m)', 'n_ref (m^-3)', &
|
||||
'u_ref (m s^-1)', 'T_ref (eV)', 'phi_ref (V)'
|
||||
write(dataRef_id, '(' // formatFloat // ',5('// formatSep // ',' // formatFloat // '))') &
|
||||
t_ref, L_ref, n_ref, &
|
||||
u_ref, Temp_ref/eV_to_K, phi_ref
|
||||
|
||||
close(dataRef_id)
|
||||
|
||||
end subroutine writeOutputRef
|
||||
|
||||
subroutine writeOutputFCum(t, dt, nz, r, nv, v, f, Z_list)
|
||||
use referenceValues, only: L_ref, n_ref, u_ref, t_ref
|
||||
|
||||
integer, intent(in):: t
|
||||
real(dp), intent(in):: dt
|
||||
integer, intent(in):: nz, nv
|
||||
real(dp), intent(in):: r
|
||||
real(dp), intent(in):: v(1:nv)
|
||||
real(dp), intent(in):: f(1:nz, 1:nv)
|
||||
real(dp), intent(in):: Z_list(1:nz)
|
||||
character(len=30) :: myfmt
|
||||
character(:), allocatable:: filename
|
||||
integer:: i, j
|
||||
character(len=10):: timeString
|
||||
character(len=4) :: ZString
|
||||
|
||||
|
||||
do j = 1, nz
|
||||
write (timeString, formatTime) t
|
||||
ZString = setZFormat(Z_list(j))
|
||||
|
||||
filename = 'time_' // trim(timeString) // '_Z_' // trim(adjustl(ZString)) // '_fCum_i.csv'
|
||||
write (*, '(A, A)') 'Writing: ', filename
|
||||
|
||||
open(unit=dataCum_id, file=pathOutput // filename)
|
||||
write(dataCum_id, '(A)') "t (s)"
|
||||
write(dataCum_id, '('//formatFloat//')') t*dt*t_ref
|
||||
write(dataCum_id, '(A)') "Z"
|
||||
write(dataCum_id, '('//formatFloat//')') Z_list(j)
|
||||
write(myfmt, "(I0)") 1
|
||||
myfmt = '(A,' // trim(myfmt) // '(' // formatSep // ',' // formatFloat // '))'
|
||||
write(dataCum_id, myfmt) "v (m/s) / r (m)", r*L_ref
|
||||
write(myfmt, "(I0)") 1
|
||||
myfmt = '(' // formatFloat // ',' // trim(myfmt) // '(' // formatSep // ',' // formatFloat // '))'
|
||||
do i = 1, nv
|
||||
write(dataCum_id, myfmt) v(i)*u_ref, f(j,i)*n_ref/u_ref
|
||||
|
||||
end do
|
||||
|
||||
close(unit=dataCum_id)
|
||||
end do
|
||||
end subroutine writeOutputFCum
|
||||
|
||||
end module output
|
||||
|
||||
10
src/modules/referenceValues.f90
Normal file
10
src/modules/referenceValues.f90
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
module referenceValues
|
||||
use constantParameters, only: dp
|
||||
implicit none
|
||||
|
||||
real(dp):: m_ref ! Reference values
|
||||
real(dp):: L_ref, t_ref, n_ref, u_ref, Temp_ref ! Reference values
|
||||
real(dp):: phi_ref ! Reference values
|
||||
|
||||
end module referenceValues
|
||||
|
||||
136
src/modules/tableBoundary.f90
Normal file
136
src/modules/tableBoundary.f90
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
module tableBoundary
|
||||
use constantParameters, only: dp
|
||||
|
||||
type:: tableBC
|
||||
real(dp):: t_min, t_max
|
||||
real(dp):: n_min, n_max
|
||||
real(dp):: u_min, u_max
|
||||
real(dp):: Temp_min, Temp_max
|
||||
real(dp), allocatable, dimension(:):: t
|
||||
real(dp), allocatable, dimension(:):: n, u, Temp
|
||||
real(dp), allocatable, dimension(:):: n_k, u_k, Temp_k
|
||||
contains
|
||||
procedure, pass:: init => initTableBC
|
||||
procedure, pass:: get => getValueTableBC
|
||||
|
||||
end type tableBC
|
||||
|
||||
contains
|
||||
subroutine initTableBC(self, tableFile)
|
||||
use constantParameters, only: eV_to_K
|
||||
use referenceValues, only: t_ref, n_ref, u_ref, Temp_ref
|
||||
implicit none
|
||||
|
||||
class(tableBC), intent(inout):: self
|
||||
character(:), allocatable, intent(in):: tableFile
|
||||
character(100):: dummy
|
||||
integer:: amount
|
||||
integer:: i
|
||||
integer:: stat
|
||||
integer:: id = 20
|
||||
|
||||
open(id, file = tableFile)
|
||||
amount = -1 ! Remove header
|
||||
do
|
||||
read(id, '(A)', iostat = stat) dummy
|
||||
!If EOF or error, exit file
|
||||
if (stat /= 0) EXIT
|
||||
! !Skip comment
|
||||
! if (index(dummy,'#') /= 0) CYCLE
|
||||
!Add row
|
||||
amount = amount + 1
|
||||
|
||||
end do
|
||||
|
||||
!Go bback to initial point
|
||||
rewind(id)
|
||||
|
||||
!Allocate table arrays
|
||||
allocate(self%t(1:amount))
|
||||
allocate( self%n(1:amount), self%u(1:amount), self%Temp(1:amount))
|
||||
allocate(self%n_k(1:amount), self%u_k(1:amount), self%Temp_k(1:amount))
|
||||
self%t = 0.0_dp
|
||||
self%n = 0.0_dp
|
||||
self%u = 0.0_dp
|
||||
self%Temp = 0.0_dp
|
||||
self%n_k = 0.0_dp
|
||||
self%u_k = 0.0_dp
|
||||
self%Temp_k = 0.0_dp
|
||||
|
||||
i = 0
|
||||
read(id, *) ! Skip header
|
||||
do
|
||||
read(id, '(A)', iostat = stat) dummy
|
||||
!TODO: Make this a function
|
||||
if (stat /= 0) EXIT
|
||||
!Add data
|
||||
!TODO: substitute with extracting information from dummy
|
||||
backspace(id)
|
||||
i = i + 1
|
||||
read(id, *) self%t(i), self%n(i), self%u(i), self%Temp(i)
|
||||
|
||||
end do
|
||||
|
||||
self%t = self%t / t_ref
|
||||
self%n = self%n / n_ref
|
||||
self%u = self%u / u_ref
|
||||
self%Temp = self%Temp * eV_to_K / Temp_ref
|
||||
|
||||
close(id)
|
||||
|
||||
self%t_min = self%t(1)
|
||||
self%t_max = self%t(amount)
|
||||
self%n_min = self%n(1)
|
||||
self%n_max = self%n(amount)
|
||||
self%u_min = self%u(1)
|
||||
self%u_max = self%u(amount)
|
||||
self%Temp_min = self%Temp(1)
|
||||
self%Temp_max = self%Temp(amount)
|
||||
|
||||
do i = 1, amount - 1
|
||||
self%n_k(i) = ( self%n(i+1) - self%n(i))/(self%t(i+1) - self%t(i))
|
||||
self%u_k(i) = ( self%u(i+1) - self%u(i))/(self%t(i+1) - self%t(i))
|
||||
self%Temp_k(i) = (self%Temp(i+1) - self%Temp(i))/(self%t(i+1) - self%t(i))
|
||||
|
||||
end do
|
||||
|
||||
end subroutine initTableBC
|
||||
|
||||
subroutine getValueTableBC(self, t, n, u, Temp)
|
||||
implicit none
|
||||
|
||||
class(tableBC), intent(in):: self
|
||||
real(dp), intent(in):: t
|
||||
real(dp), intent(out):: n, u, Temp
|
||||
real(dp):: delta_t
|
||||
integer:: i
|
||||
|
||||
if (t <= self%t_min) THEN
|
||||
n = self%n_min
|
||||
u = self%u_min
|
||||
Temp = self%Temp_min
|
||||
|
||||
elseif (t >= self%t_max) THEN
|
||||
n = self%n_max
|
||||
u = self%u_max
|
||||
Temp = self%Temp_max
|
||||
|
||||
else
|
||||
i = minloc(abs(t - self%t), 1)
|
||||
delta_t = t - self%t(i)
|
||||
if (delta_t < 0 ) THEN
|
||||
i = i - 1
|
||||
delta_t = t - self%t(i)
|
||||
|
||||
end if
|
||||
|
||||
n = self%n(i) + self%n_k(i)*delta_t
|
||||
u = self%u(i) + self%u_k(i)*delta_t
|
||||
Temp = self%Temp(i) + self%Temp_k(i)*delta_t
|
||||
|
||||
end if
|
||||
|
||||
end subroutine getValueTableBC
|
||||
|
||||
end module tableBoundary
|
||||
|
||||
148
src/modules/tableTNZ.f90
Normal file
148
src/modules/tableTNZ.f90
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
module tableTNZ
|
||||
use constantParameters, only: dp
|
||||
|
||||
type:: tableTn_to_Z
|
||||
real(dp) :: Z_min, Z_max
|
||||
real(dp) :: Temp_min, Temp_max
|
||||
real(dp), allocatable, dimension(:):: Temp
|
||||
real(dp), allocatable, dimension(:,:):: Z
|
||||
real(dp), allocatable, dimension(:,:):: Z_k
|
||||
real(dp), allocatable, dimension(:):: ne
|
||||
contains
|
||||
procedure, pass:: init => initTableTtoZne
|
||||
procedure, pass:: get => getValueTableTtoZne
|
||||
|
||||
end type tableTn_to_Z
|
||||
|
||||
contains
|
||||
subroutine initTableTtoZne(self, tableFile)
|
||||
use constantParameters, only: eV_to_K
|
||||
use referenceValues, only: Temp_ref, n_ref
|
||||
implicit none
|
||||
|
||||
class(tableTn_to_Z), intent(inout):: self
|
||||
character(:), allocatable, intent(in):: tableFile
|
||||
character(100):: dummy
|
||||
character(len=512) :: line
|
||||
character(len=20), allocatable :: ne_headers(:)
|
||||
integer:: amount, num_ne
|
||||
integer:: i,j
|
||||
integer:: stat
|
||||
integer:: id = 20
|
||||
num_ne = 0
|
||||
|
||||
open(id, file = tableFile)
|
||||
amount = -1 ! Remove header
|
||||
do
|
||||
read(id, '(A)', iostat = stat) dummy
|
||||
!If EOF or error, exit file
|
||||
if (stat /= 0) EXIT
|
||||
! !Skip comment
|
||||
! if (index(dummy,'#') /= 0) CYCLE
|
||||
!Add row
|
||||
amount = amount + 1
|
||||
|
||||
end do
|
||||
|
||||
!Go bback to initial point
|
||||
rewind(id)
|
||||
read(id, '(A)', iostat = stat) dummy
|
||||
do i = 1, len_trim(dummy)
|
||||
if (dummy(i:i) == ",") num_ne = num_ne + 1
|
||||
end do
|
||||
allocate(ne_headers(num_ne))
|
||||
allocate(self%ne(num_ne))
|
||||
|
||||
rewind(id)
|
||||
read(id, '(A)') line
|
||||
|
||||
! Read values while skipping the first entry
|
||||
read(line, *) dummy, (self%ne(i), i=1, num_ne)
|
||||
|
||||
|
||||
! read(id, *) ! Skip 'x'
|
||||
! do i = 1, num_ne
|
||||
! read(dummy, *) ne_headers(i)
|
||||
! read(ne_headers(i), *) self%ne(i)
|
||||
! print *, self%ne(i)
|
||||
! end do
|
||||
rewind(id)
|
||||
|
||||
|
||||
!Allocate table arrays
|
||||
allocate(self%Temp(1:amount))
|
||||
allocate(self%Z(1:amount, 1:num_ne))
|
||||
allocate(self%Z_k(1:amount, 1:num_ne))
|
||||
self%Temp = 0.0_dp
|
||||
self%Z = 0.0_dp
|
||||
self%Z_k = 0.0_dp
|
||||
|
||||
i = 0
|
||||
read(id, *) ! Skip header
|
||||
do
|
||||
read(id, '(A)', iostat = stat) dummy
|
||||
!TOdo: Make this a function
|
||||
if (stat /= 0) EXIT
|
||||
!Add data
|
||||
!TODO: substitute with extracting information from dummy
|
||||
backspace(id)
|
||||
i = i + 1
|
||||
read(id, *, iostat= stat) self%Temp(i), (self%Z(i, j), j = 1, num_ne)
|
||||
|
||||
end do
|
||||
self%Temp = self%Temp * eV_to_K / Temp_ref
|
||||
self%ne = self%ne / n_ref
|
||||
|
||||
close(id)
|
||||
|
||||
self%Temp_min = self%Temp(1)
|
||||
self%Temp_max = self%Temp(amount)
|
||||
self%Z_min = self%Z(1,1)
|
||||
self%Z_max = self%Z(amount,num_ne)
|
||||
do i = 1, amount - 1
|
||||
do j = 1, num_ne
|
||||
self%Z_k(i,j) = ( self%Z(i+1,j) - self%Z(i,j))/(self%Temp(i+1) - self%Temp(i))
|
||||
end do
|
||||
end do
|
||||
|
||||
end subroutine initTableTtoZne
|
||||
|
||||
subroutine getValueTableTtoZne(self, Temp, ne, Z)
|
||||
implicit none
|
||||
|
||||
class(tableTn_to_Z), intent(in):: self
|
||||
real(dp), intent(in):: Temp, ne
|
||||
real(dp), intent(out):: Z
|
||||
real(dp):: delta_Temp
|
||||
integer:: i, j
|
||||
|
||||
j = minloc(abs(ne - self%ne), 1)
|
||||
! print *, "ne : ", ne
|
||||
! print *, "Temp : ", Temp
|
||||
|
||||
|
||||
if (Temp <= self%Temp_min) THEN
|
||||
Z = self%Z_min
|
||||
|
||||
elseif (Temp >= self%Temp_max) THEN
|
||||
Z = self%Z_max
|
||||
|
||||
else
|
||||
i = minloc(abs(Temp - self%Temp), 1)
|
||||
delta_Temp = Temp - self%Temp(i)
|
||||
if (delta_Temp < 0 ) THEN
|
||||
i = i - 1
|
||||
delta_Temp = Temp - self%Temp(i)
|
||||
|
||||
end if
|
||||
|
||||
Z = self%Z(i,j) + self%Z_k(i,j)*delta_Temp
|
||||
|
||||
end if
|
||||
|
||||
end subroutine getValueTableTtoZne
|
||||
|
||||
|
||||
|
||||
end module tableTNZ
|
||||
|
||||
411
src/vlaplex.f90
Normal file
411
src/vlaplex.f90
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
program VlaPlEx
|
||||
use constantParameters, only: dp, kb, qe, eps_0, ev_to_K, cm3_to_m3, PI
|
||||
use input
|
||||
use output
|
||||
use referenceValues
|
||||
use tableBoundary
|
||||
use tableTNZ
|
||||
use omp_lib
|
||||
implicit none
|
||||
|
||||
real(dp), parameter:: gamma_i = 1.0_dp ! Adiabatic coefficient for ions
|
||||
real(dp), parameter:: m_e = 9.1093837e-31_dp ! Electron mass in kg
|
||||
real(dp), parameter:: gamma_e = 4.0_dp / 3.0_dp ! Adiabatic coefficient for electrons
|
||||
real(dp), parameter:: gamma_e_exp = 1.0_dp /(gamma_e - 1.0_dp) ! Exponent for polytropic electrons
|
||||
real(dp), parameter:: gamma_e_dexp = (2.0_dp - gamma_e)/(gamma_e - 1.0_dp) ! Exponent for polytropic db_dphi
|
||||
real(dp), parameter:: n_epsilon = 1.0e-16_dp
|
||||
|
||||
real(dp):: r0, rf
|
||||
real(dp), allocatable, dimension(:):: r
|
||||
real(dp):: v0, vf
|
||||
real(dp), allocatable, dimension(:):: v
|
||||
real(dp):: t0, tf
|
||||
real(dp):: CFL
|
||||
real(dp):: time
|
||||
real(dp):: dr, dv, dt
|
||||
integer:: nr, nv, nt, nz
|
||||
integer:: i, iz, j, t, z_inj
|
||||
integer:: j0 ! First integer of positive velocity
|
||||
|
||||
real(dp):: Temp_bc ! Temperature
|
||||
real(dp):: Zave_bc, Zave_bc_old ! Average charge state
|
||||
real(dp):: u_bc ! Injection velocity
|
||||
real(dp):: n_bc ! Injection density
|
||||
type(tableBC):: boundaryConditions
|
||||
type(tableTn_to_Z):: Tene_to_Z
|
||||
|
||||
real(dp), allocatable, dimension(:,:,:):: f_i, f_i_old
|
||||
real(dp), allocatable, dimension(:):: f0 ! Boundary at r = x_0
|
||||
real(dp), allocatable, dimension(:,:):: n_i
|
||||
real(dp), allocatable, dimension(:):: sum_ni
|
||||
real(dp), allocatable, dimension(:,:):: u_i
|
||||
real(dp), allocatable, dimension(:):: E_i
|
||||
real(dp), allocatable, dimension(:,:):: T_i
|
||||
real(dp), allocatable, dimension(:):: n_e
|
||||
real(dp), allocatable, dimension(:):: Zave
|
||||
real(dp), allocatable, dimension(:):: Zlist
|
||||
real(dp), allocatable, dimension(:):: diag, diag_low, diag_high
|
||||
real(dp), allocatable, dimension(:,:):: A
|
||||
real(dp), allocatable, dimension(:):: Res
|
||||
real(dp), allocatable, dimension(:):: b
|
||||
integer:: info
|
||||
|
||||
real(dp), allocatable, dimension(:):: phi, phi_old, E, db_dphi
|
||||
real(dp):: phiConv
|
||||
real(dp):: phi0
|
||||
real(dp):: T_e
|
||||
! real(dp):: phiF
|
||||
integer:: k
|
||||
|
||||
integer:: nThreads ! number of threads for OpenMP
|
||||
|
||||
real(dp), allocatable, dimension(:,:):: fCum_i
|
||||
real(dp):: rCum
|
||||
integer:: rCum_index
|
||||
|
||||
character(len=128) arg
|
||||
|
||||
CALL get_command_argument(1, arg)
|
||||
if (arg == '') then
|
||||
write (*, '(a)') "No input file provided"
|
||||
return
|
||||
|
||||
end if
|
||||
inputFile = trim(arg)
|
||||
call openInputFile()
|
||||
call readReference()
|
||||
call readGrid(r0, rf, dr, v0, vf, nv)
|
||||
call readTime(t0, tf, CFL)
|
||||
call readDetector(rCum)
|
||||
call readBoundary(boundaryConditions)
|
||||
nThreads = 16
|
||||
call readZ(Zlist, nz, Tene_to_Z)
|
||||
call closeInputFile()
|
||||
|
||||
! Set number of threads
|
||||
call omp_set_num_threads(nThreads)
|
||||
|
||||
! Grid in the position space
|
||||
nr = nint((rf - r0) / dr) + 1
|
||||
dr = (rf - r0) / float(nr-1)
|
||||
allocate(r(1:nr))
|
||||
do i = 1, nr
|
||||
r(i) = dr * float(i-1) + r0
|
||||
end do
|
||||
|
||||
! Index for cumulative sum
|
||||
rCum_index = minloc(abs(r - rCum), 1)
|
||||
|
||||
! Grid in the velocity space
|
||||
print*, v0, vf
|
||||
dv = (vf - v0) / float(nv-1)
|
||||
allocate(v(1:nv))
|
||||
do j = 1, nv
|
||||
v(j) = dv * float(j-1) + v0
|
||||
end do
|
||||
! Shift v mesh so it passes by 0
|
||||
v = v - (minval(abs(v)))
|
||||
j0 = minloc(abs(v), 1)
|
||||
if (v(j0) < 0.0_dp) then
|
||||
j0 = j0 + 1
|
||||
end if
|
||||
|
||||
dt = CFL*dr/vf
|
||||
nt = nint((tf - t0) / dt)
|
||||
dt = (tf - t0) / float(nt)
|
||||
|
||||
everyOutput = nint(1.0e-9_dp/t_ref/dt)
|
||||
if (everyOutput == 0) then
|
||||
everyOutput = 1
|
||||
|
||||
end if
|
||||
|
||||
everyWrite = everyOutput/10
|
||||
if (everyWrite == 0) then
|
||||
everyWrite = 1
|
||||
|
||||
end if
|
||||
|
||||
! Allocate vectors
|
||||
allocate(f_i(1:nz,1:nr,1:nv), f_i_old(1:nz,1:nr,1:nv))
|
||||
allocate(n_i(1:nz,1:nr))
|
||||
allocate(sum_ni(1:nr))
|
||||
allocate(u_i(1:nz,1:nr), E_i(1:nr), T_i(1:nz,1:nr))
|
||||
allocate(Zave(1:nr))
|
||||
allocate(n_e(1:nr))
|
||||
allocate(phi(1:nr), phi_old(1:nr), E(1:nr))
|
||||
allocate(fCum_i(1:nz,1:nv))
|
||||
f_i = 0.0_dp
|
||||
f_i_old = 0.0_dp
|
||||
n_i = 0.0_dp
|
||||
sum_ni = 0.0_dp
|
||||
u_i = 0.0_dp
|
||||
E_i = 0.0_dp
|
||||
T_i = 0.0_dp
|
||||
n_e = 0.0_dp
|
||||
T_e = 0.0_dp
|
||||
Zave = 0.0_dp
|
||||
Zave_bc_old = 0.0_dp
|
||||
phi = 0.0_dp
|
||||
phi_old = 0.0_dp
|
||||
E = 0.0_dp
|
||||
fCum_i = 0.0_dp
|
||||
|
||||
! Allocate matrix for Poisson equation
|
||||
allocate(diag(1:nr), diag_low(1:nr-1), diag_high(1:nr-1))
|
||||
allocate(b(1:nr))
|
||||
allocate(db_dphi(1:nr))
|
||||
diag = 0.0_dp
|
||||
diag_low = 0.0_dp
|
||||
diag_high = 0.0_dp
|
||||
b = 0.0_dp
|
||||
db_dphi = 0.0_dp
|
||||
diag = -2.0_dp / dr**2
|
||||
diag_low = 1.0_dp / dr**2 - 1.0_dp / (r(2:nr) * dr)
|
||||
diag_high = 1.0_dp / dr**2 + 1.0_dp / (r(1:nr-1) * dr)
|
||||
diag(1) = 1.0_dp ! Dirichlet
|
||||
diag_high(1) = 0.0_dp ! Dirichlet
|
||||
! diag_high(1) = 2.0_dp / dr**2 ! Neumann
|
||||
! diag(nr) = 1.0_dp ! Dirichlet
|
||||
! diag_low(nr-1) = 0.0_dp ! Dirichlet
|
||||
diag_low(nr-1) = 2.0_dp / dr**2 ! Neumann
|
||||
|
||||
allocate(A(1:nr,1:nr))
|
||||
A = 0.0_dp
|
||||
A(1,1) = diag(1)
|
||||
A(1,2) = diag_high(1)
|
||||
do i = 2, nr - 1
|
||||
A(i, i-1) = diag_low(i-1)
|
||||
A(i, i) = diag(i)
|
||||
A(i, i+1) = diag_high(i)
|
||||
end do
|
||||
A(nr,nr-1) = diag_low(nr-1)
|
||||
A(nr,nr) = diag(nr)
|
||||
|
||||
allocate(Res(1:nr))
|
||||
Res = 0.0_dp
|
||||
|
||||
! Set boundary values
|
||||
phi0 = 1.0e2_dp / phi_ref ! Dirichlet
|
||||
phi(1) = phi0 ! Dirichlet
|
||||
! phi0 = phi(1) ! Neumann
|
||||
allocate(f0(j0:nv))
|
||||
f0 = 0.0_dp
|
||||
|
||||
! Output initial values
|
||||
call createPath()
|
||||
call setTimeFormat(nt)
|
||||
t = 0
|
||||
call writeOutputRef()
|
||||
! call writeOutputF(t, dt, nr, r, nv, v, f_i_old)
|
||||
call writeOutputFCum(t, dt, nz, r(rCum_index), nv, v, fCum_i, Zlist)
|
||||
call writeOutputPhi(t, dt, nr, r, phi, E, n_e)
|
||||
call writeOutputMom(t, dt, nz, nr, r, n_i, u_i, T_i, Zlist)
|
||||
call writeOutputZList(nz, Zlist)
|
||||
|
||||
! Main loop
|
||||
do t = 1, nt
|
||||
time = t * dt + t0
|
||||
|
||||
! Get boundary conditions for specific time
|
||||
call boundaryConditions%get(time, n_bc, u_bc, Temp_bc)
|
||||
! Find new \bar{Z}_i based on T_e = Temp_bc and n_e = n_bc
|
||||
call Tene_to_Z%get(Temp_bc, n_bc, Zave_bc)
|
||||
! Assign Z(T,n) to bin
|
||||
z_inj = minloc(abs(Zlist - Zave_bc),1)
|
||||
! Calculate inject (sonic) speed
|
||||
u_bc = sqrt(Zlist(z_inj)* Temp_bc)
|
||||
! Calculate ion density to inject
|
||||
n_bc = n_bc / Zlist(z_inj)
|
||||
call writeOutputBoundary(t, dt, n_bc, u_bc, Temp_bc, Zave_bc, Zlist(z_inj))
|
||||
|
||||
! f0(j0:nv) = v(j0:nv)**2 / sqrt(PI*Temp_bc**3) * exp(-(v(j0:nv) - u_bc)**2 / Temp_bc)
|
||||
f0(j0:nv) = 1.0_dp / sqrt(PI*Temp_bc) * exp(-(v(j0:nv) - u_bc)**2 / Temp_bc)
|
||||
f0 = f0 * n_bc / (sum(f0)*dv)
|
||||
|
||||
f_i_old(:,1,j0:nv) = 0.0_dp
|
||||
f_i_old(z_inj,1,j0:nv) = f0
|
||||
f_i(:,1,j0:nv) = f_i_old(:,1,j0:nv)
|
||||
|
||||
T_e = Temp_bc
|
||||
|
||||
! r = rf, v<0
|
||||
f_i_old(:,nr,1:j0-1) = 0.0_dp
|
||||
f_i(:,nr,1:j0-1) = f_i_old(:,nr,1:j0-1)
|
||||
! set edge velocities to 0
|
||||
f_i_old(:,:,1) = 0.0_dp
|
||||
f_i_old(:,:,nv) = 0.0_dp
|
||||
sum_ni = 0.0_dp
|
||||
! Advect in the r direction
|
||||
do iz = 1, nz
|
||||
if (all(n_i(iz,:) < n_epsilon) .and. iz .ne. z_inj) then
|
||||
cycle
|
||||
end if
|
||||
!$omp parallel do
|
||||
do i = 1, nr
|
||||
! Advect negative velocity
|
||||
if (i < nr) then
|
||||
f_i(iz,i,1:j0-1) = f_i_old(iz,i,1:j0-1) - v(1:j0-1)*dt/dr/r(i)**2*(r(i+1)**2*f_i_old(iz,i+1,1:j0-1) - &
|
||||
r(i )**2*f_i_old(iz,i ,1:j0-1))
|
||||
end if
|
||||
! Advect positive velocity
|
||||
if (i > 1) then
|
||||
f_i(iz,i,j0:nv) = f_i_old(iz,i, j0:nv) - v( j0:nv)*dt/dr/r(i)**2*(r(i )**2*f_i_old(iz,i , j0:nv) - &
|
||||
r(i-1)**2*f_i_old(iz,i-1, j0:nv))
|
||||
end if
|
||||
|
||||
n_i(iz,i) = sum(f_i(iz,i,:))*dv
|
||||
if (n_i(iz,i) > n_epsilon) then
|
||||
u_i(iz,i) = sum(v(:) *f_i(iz,i,:))*dv / n_i(iz,i)
|
||||
E_i(i) = sum(v(:)**2*f_i(iz,i,:))*dv / n_i(iz,i)
|
||||
T_i(iz,i) = 2.0_dp*E_i(i) - 2.0_dp*u_i(iz,i)**2
|
||||
else
|
||||
f_i(iz,i,:) = 0.0_dp
|
||||
n_i(iz,i) = 0.0_dp
|
||||
u_i(iz,i) = 0.0_dp
|
||||
T_i(iz,i) = 0.0_dp
|
||||
end if
|
||||
|
||||
end do
|
||||
!$omp end parallel do
|
||||
sum_ni = sum_ni + Zlist(iz) * n_i(iz,:)
|
||||
end do
|
||||
|
||||
! Assume quasi-neutrality to start iterating
|
||||
n_e = sum_ni
|
||||
db_dphi = 0.0_dp
|
||||
|
||||
! Solve Poission (maximum number of iterations, break if convergence is reached before)
|
||||
do k = 1, 2000
|
||||
! Store previous value
|
||||
phi_old = phi
|
||||
|
||||
diag = -2.0_dp / dr**2 - db_dphi
|
||||
diag_low = 1.0_dp / dr**2 - 1.0_dp / (r(2:nr) * dr)
|
||||
diag_high = 1.0_dp / dr**2 + 1.0_dp / (r(1:nr-1) * dr)
|
||||
diag(1) = 1.0_dp ! Dirichlet
|
||||
diag_high(1) = 0.0_dp ! Dirichlet
|
||||
! diag(nr) = 1.0_dp ! Dirichlet
|
||||
! diag_low(nr-1) = 0.0_dp ! Dirichlet
|
||||
diag_low(nr-1) = 2.0_dp / dr**2 - db_dphi(nr) ! Neumann
|
||||
|
||||
! Calculate charge density
|
||||
b = - (sum_ni - n_e)
|
||||
! Apply boundary conditions
|
||||
b(1) = phi0 ! Dirichlet
|
||||
! b(nr) = 0.0_dp ! Dirichlet
|
||||
|
||||
! Calculate residual
|
||||
!$omp parallel workshare
|
||||
Res = -(MATMUL(A, phi_old) - b)
|
||||
!$omp end parallel workshare
|
||||
|
||||
! Iterate system
|
||||
call dgtsv(nr, 1, diag_low, diag, diag_high, Res, nr, info)
|
||||
phi = phi_old + Res
|
||||
! phi0=phi(1) ! Neumann
|
||||
|
||||
! Calculate distribution of electrons
|
||||
! n_e = sum_ni(1) * exp((phi- phi0) / T_e) ! Isothermal (Boltzmann)
|
||||
n_e = sum_ni(1) * (1.0_dp + (gamma_e - 1.0_dp)/gamma_e*(phi-phi0)/T_e)**gamma_e_exp !Polytropic
|
||||
! Diagonal matrix for Newton integration scheme
|
||||
! db_dphi = n_e / T_e ! Isothermal (Boltzmann)
|
||||
db_dphi = sum_ni(1) / (gamma_e * T_e) * &
|
||||
(1.0_dp + (gamma_e - 1.0_dp)/gamma_e*(phi-phi0)/T_e)**gamma_e_dexp !Polytropic
|
||||
|
||||
! Check if the solution has converged
|
||||
phiConv = maxval(abs(Res),1)
|
||||
if (phiConv < 1.0e-6_dp) then
|
||||
exit
|
||||
|
||||
end if
|
||||
|
||||
! ! Calculate new potential to ensure 0 current at the edge
|
||||
! if (n_i(nr) > n_epsilon) then
|
||||
! phiF = phi0 + T_e * log((2.0_dp*sqrt(pi)*Zave(nr)*n_i(nr)*u_i(nr)) / (Zave(1)*n_i(1)*sqrt(m_i*T_e/m_e)))
|
||||
!
|
||||
! else
|
||||
! phiF = phi(nr-5)
|
||||
!
|
||||
! end if
|
||||
|
||||
end do
|
||||
|
||||
! Calculate electric field
|
||||
E(1) = - (phi(2) - phi(1)) / dr ! Dirichlet
|
||||
! E(1) = 0.0_dp ! Neumann
|
||||
!$omp parallel do
|
||||
do i = 2, nr-1
|
||||
E(i) = - 0.5_dp*(phi(i+1) - phi(i-1)) / dr
|
||||
|
||||
end do
|
||||
!$omp end parallel do
|
||||
! E(nr) = - (phi(nr) - phi(nr-1)) / dr ! Dirichlet
|
||||
E(nr) = 0.0_dp ! Neumann
|
||||
|
||||
! Update intermediate f
|
||||
f_i_old = f_i
|
||||
|
||||
do iz = 1, nz
|
||||
if (all(n_i(iz,:) < n_epsilon) .and. iz .ne. z_inj) then
|
||||
cycle
|
||||
end if
|
||||
! Advect in the v direction
|
||||
! i = 1, v<0
|
||||
i = 1
|
||||
if (E(i) >= 0.0_dp) then
|
||||
f_i(iz,i,2:j0-2) = f_i_old(iz,i,2:j0-2) - Zlist(iz)*E(i)*dt/dv*(f_i_old(iz,i,2:j0-2) - f_i_old(iz,i,1:j0-3))
|
||||
else
|
||||
f_i(iz,i,2:j0-2) = f_i_old(iz,i,2:j0-2) - Zlist(iz)*E(i)*dt/dv*(f_i_old(iz,i,3:j0-1) - f_i_old(iz,i,2:j0-2))
|
||||
|
||||
end if
|
||||
! i = 2, nr-1; all v
|
||||
!$omp parallel do
|
||||
do i = 2, nr-1
|
||||
if (E(i) >= 0.0_dp) then
|
||||
f_i(iz,i,2:nv-1) = f_i_old(iz,i,2:nv-1) - Zlist(iz)*E(i)*dt/dv*(f_i_old(iz,i,2:nv-1) - f_i_old(iz,i,1:nv-2))
|
||||
else
|
||||
f_i(iz,i,2:nv-1) = f_i_old(iz,i,2:nv-1) - Zlist(iz)*E(i)*dt/dv*(f_i_old(iz,i,3:nv) - f_i_old(iz,i,2:nv-1))
|
||||
|
||||
end if
|
||||
|
||||
end do
|
||||
!$omp end parallel do
|
||||
! i = nr, v>=0
|
||||
i = nr
|
||||
if (E(i) >= 0.0_dp) then
|
||||
f_i(iz,i,j0+1:nv-1) = f_i_old(iz,i,j0+1:nv-1) - Zlist(iz)*E(i)*dt/dv*(f_i_old(iz,i,j0+1:nv-1) - f_i_old(iz,i,j0:nv-2))
|
||||
else
|
||||
f_i(iz,i,j0+1:nv-1) = f_i_old(iz,i,j0+1:nv-1) - Zlist(iz)*E(i)*dt/dv*(f_i_old(iz,i,j0+2:nv) - f_i_old(iz,i,j0+1:nv-1))
|
||||
|
||||
end if
|
||||
end do
|
||||
|
||||
! Reset values for next iteration
|
||||
f_i_old = f_i
|
||||
do iz = 1, nz
|
||||
if (all(n_i(iz,:) < n_epsilon) .and. iz .ne. z_inj) then
|
||||
cycle
|
||||
end if
|
||||
fCum_i(iz,:) = fCum_i(iz,:) + f_i_old(iz,rCum_index,:)
|
||||
end do
|
||||
! Write output
|
||||
if (mod(t,everyOutput) == 0 .or. t == nt) then
|
||||
! call writeOutputF(t, dt, nz, nr, r, nv, v, f_i_old, Zlist)
|
||||
call writeOutputPhi(t, dt, nr, r, phi, E, n_e)
|
||||
call writeOutputMom(t, dt, nz, nr, r, n_i, u_i, T_i, Zlist)
|
||||
call writeOutputFCum(t, dt, nz, r(rCum_index), nv, v, fCum_i, Zlist)
|
||||
|
||||
end if
|
||||
|
||||
! Write progress
|
||||
if (mod(t,everyWrite) == 0) then
|
||||
write (*, '(I10, A, I10)' ) t, '/', nt
|
||||
write (*, '(A, ES0.4e3,","ES0.4e3)') 'phi max,min: ', maxval(phi)*phi_ref, minval(phi)*phi_ref
|
||||
|
||||
end if
|
||||
|
||||
end do
|
||||
|
||||
end program VlaPlEx
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue