MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_opal_opacity.t
Go to the documentation of this file.
1!> This module reads in Rosseland-mean opacities from OPAL tables. Table opacity
2!> values are given in base 10 logarithm and are a function of mass density (R)
3!> and temperature (T), which are also both given in base 10 logarithm.
4
6
7 use mod_comm_lib, only: mpistop
9
10 implicit none
11 private
12
13 !> min and max indices for R,T-range in opacity table
14 integer, parameter :: iRmin = 2, irmax = 20
15 integer, parameter :: iTmin = 7, itmax = 76
16
17 !> If user wants to read tables from different location than AMRVAC source
18 !> NOTE: the tables should have same size as AMRVAC tables
19 logical :: set_custom_tabledir = .false.
20
21 !> The opacity tables are read once and stored globally in Kappa_vals
22 double precision, public :: kappa_vals(itmin:itmax,irmin:irmax)
23 double precision, public :: logr_list(irmin:irmax), logt_list(itmin:itmax)
24
25 public :: init_opal_table
26 public :: set_opal_opacity
27
28contains
29
30 !> This subroutine is called when the FLD radiation module is initialised.
31 !> The OPAL tables for different helium abundances are read and interpolated.
32 subroutine init_opal_table(tabledir,set_custom_tabledir)
33
34 character(len=*), intent(in) :: tabledir
35 logical, optional, intent(in) :: set_custom_tabledir
36
37 ! Local variables
38 character(len=256) :: amrvac_dir, path_table_dir
39
40 if (present(set_custom_tabledir) .and. set_custom_tabledir) then
41 path_table_dir = trim(tabledir)
42 else
43 call get_environment_variable("AMRVAC_DIR", amrvac_dir)
44 path_table_dir = trim(amrvac_dir)//"/src/tables/OPAL_tables/"//trim(tabledir)
45 endif
46
47 ! Read in the OPAL table
48 call read_table(logr_list, logt_list, kappa_vals, path_table_dir)
49
50 if(mype==0)then
51 write(*,*)' Initialized OPAL tables: read in the table from', path_table_dir
52 endif
53
54 end subroutine init_opal_table
55
56 !> This subroutine calculates the opacity for a given temperature-density
57 !> structure. Opacities are read from a table with given metalicity.
58 subroutine set_opal_opacity(rho, temp, kappa)
59
60 double precision, intent(in) :: rho, temp
61 double precision, intent(out) :: kappa
62 ! Local variables
63 double precision :: logr_in, logt_in, logkappa_out
64
65 if (temp <= 0.0d0) call mpistop('Input temperature < 0 in set_opal_opacity.')
66 if (rho <= 0.0d0) call mpistop('Input density < 0 in set_opal_opacity.')
67
68 ! Convert input density and temperature to OPAL table convention
69 logr_in = log10(rho/(temp*1.0d-6)**3.0d0)
70 logt_in = log10(temp)
71
72 !!print *,'enter get_kappa with logR_in and logT_in=',logR_in,logT_in
73 call get_kappa(kappa_vals, logr_list, logt_list, logr_in, logt_in, logkappa_out)
74 !!print *,'got logKappa_out=',logKappa_out
75
76 ! If the outcome is 9.999 (no table entry), look right in the table
77 !!do while (logKappa_out > 9.0d0)
78 !! logR_in = logR_in + 0.5d0
79 !! call get_kappa(Kappa_vals, logR_list, logT_list, logR_in, logT_in, logKappa_out)
80 !!enddo
81
82 ! If the outcome is NaN, look left in the table
83 !!do while (logKappa_out <= 1.0d-4)
84 !! logR_in = logR_in - 0.5d0
85 !! call get_kappa(Kappa_vals, logR_list, logT_list, logR_in, logT_in, logKappa_out)
86 !!enddo
87
88 ! Convert OPAL opacity for output
89 kappa = 10.0d0**logkappa_out
90
91 end subroutine set_opal_opacity
92
93 !> This routine reads in 1-D (rho,T) values from an opacity table and gives
94 !> back as output the 1-D (rho,T) values and 2-D opacity
95 subroutine read_table(R, T, K, filename)
96
97 character(*), intent(in) :: filename
98 double precision, intent(out) :: k(itmin:itmax,irmin:irmax), r(irmin:irmax), t(itmin:itmax)
99
100 ! Local variables
101 character :: dum
102 integer :: row, col, funit=98
103 logical :: alive
104
105 inquire(file=trim(filename), exist=alive)
106
107 if (alive) then
108 open(funit, file=trim(filename), status='unknown')
109 else
110 call mpistop('Table file you want to use cannot be found: '//filename)
111 endif
112
113 ! Skip first 4 lines
114 do row = 1,4
115 read(funit,*)
116 enddo
117
118 ! Read rho
119 read(funit,*) dum, r(irmin:irmax)
120 read(funit,*)
121
122 ! Read T and kappa
123 do row = itmin,itmax
124 read(funit,'(f4.2,19f7.3)') t(row), k(row,irmin:irmax)
125 enddo
126
127 close(funit)
128
129 end subroutine read_table
130
131 !> This subroutine looks in the table for the four couples (T,rho) surrounding
132 !> a given input T and rho
133 subroutine get_kappa(Kappa_vals, logR_list, logT_list, R, T, K)
134
135 double precision, intent(in) :: kappa_vals(itmin:itmax,irmin:irmax)
136 double precision, intent(in) :: logr_list(irmin:irmax), logt_list(itmin:itmax)
137 double precision, intent(in) :: r, t
138 double precision, intent(out) :: k
139
140 ! Local variables
141 integer :: low_r_index, up_r_index
142 integer :: low_t_index, up_t_index
143
144 !print *,'enter with R and T=',R,T
145 !print *,'check max-min(logR_list)=',maxval(logR_list),minval(logR_list)
146 if (r .ge. maxval(logr_list)) then
147 low_r_index = irmax-1
148 up_r_index = irmax
149 elseif (r .le. minval(logr_list)) then
150 low_r_index = irmin
151 up_r_index = irmin+1
152 else
153 call get_low_up_index(r, logr_list, irmin, irmax, low_r_index, up_r_index)
154 endif
155
156 if (t .ge. maxval(logt_list)) then
157 low_t_index = itmax-1
158 up_t_index = itmax
159 elseif (t .le. minval(logt_list)) then
160 low_t_index = itmin
161 up_t_index = itmin+1
162 else
163 call get_low_up_index(t, logt_list, itmin, itmax, low_t_index, up_t_index)
164 endif
165
166 call interpolate_krt(low_r_index, up_r_index, low_t_index, up_t_index, logr_list, logt_list, kappa_vals, r, t, k)
167
168 end subroutine get_kappa
169
170 !> This subroutine finds the indices in rho and T arrays of the two values
171 !> surrounding the input rho and T
172 subroutine get_low_up_index(var_in, var_list, imin, imax, low_i, up_i)
173
174 integer, intent(in) :: imin, imax
175 double precision, intent(in) :: var_in, var_list(imin:imax)
176 integer, intent(out) :: low_i, up_i
177
178 ! Local variables
179 double precision :: low_val, up_val, res(imin:imax)
180
181 res = var_list - var_in
182
183 ! Find all bounding values for given input
184 up_val = minval(res, mask = res >= 0) + var_in
185 low_val = maxval(res, mask = res <= 0) + var_in
186
187 ! Find all bounding indices
188 up_i = minloc(abs(var_list - up_val),1) + imin -1
189 low_i = minloc(abs(var_list - low_val),1) + imin -1
190
191 if (up_i == low_i) low_i = low_i - 1
192
193 end subroutine get_low_up_index
194
195 !> This subroutine does a bilinear interpolation in the R,T-plane
196 subroutine interpolate_krt(low_r, up_r, low_t, up_t, logR_list, logT_list, Kappa_vals, R, T, kappa_interp)
197
198 integer, intent(in) :: low_r, up_r, low_t, up_t
199 double precision, intent(in) :: kappa_vals(itmin:itmax,irmin:irmax)
200 double precision, intent(in) :: logr_list(irmin:irmax), logt_list(itmin:itmax)
201 double precision, intent(in) :: r, t
202 double precision, intent(out) :: kappa_interp
203
204 ! Local variables
205 double precision :: r1, r2, t1, t2, k1, k2, k3, k4, ka, kb
206
207 ! First interpolate twice in the T coord to get ka and kb, then interpolate
208 ! in the R coord to get ki
209
210 ! r_1 rho r_2
211 ! | |
212 ! | |
213 ! ----k1--------ka-----k2----- t_1
214 ! | | |
215 ! | | |
216 ! T | | |
217 ! | | |
218 ! | ki |
219 ! | | |
220 ! ----k3--------kb-----k4----- t_2
221 ! | |
222 ! | |
223
224 r1 = logr_list(low_r)
225 r2 = logr_list(up_r)
226 t1 = logt_list(low_t)
227 t2 = logt_list(up_t)
228
229 k1 = kappa_vals(low_t, low_r)
230 k2 = kappa_vals(low_t, up_r)
231 k3 = kappa_vals(up_t, low_r)
232 k4 = kappa_vals(up_t, up_r)
233
234 call interpolate1d(r1,r2,r,k1,k2,ka)
235 call interpolate1d(r1,r2,r,k3,k4,kb)
236 call interpolate1d(t1,t2,t,ka,kb,kappa_interp)
237
238 end subroutine interpolate_krt
239
240 !> Interpolation in one dimension
241 subroutine interpolate1d(x1, x2, x, y1, y2, y)
242
243 double precision, intent(in) :: x, x1, x2, y1, y2
244 double precision, intent(out) :: y
245
246 y = y1 + (x-x1)*(y2-y1)/(x2-x1)
247
248 end subroutine interpolate1d
249
250end module mod_opal_opacity
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer mype
The rank of the current MPI task.
double precision, dimension(:), allocatable, parameter d
This module reads in Rosseland-mean opacities from OPAL tables. Table opacity values are given in bas...
subroutine, public init_opal_table(tabledir, set_custom_tabledir)
This subroutine is called when the FLD radiation module is initialised. The OPAL tables for different...
double precision, dimension(itmin:itmax), public logt_list
double precision, dimension(itmin:itmax, irmin:irmax), public kappa_vals
The opacity tables are read once and stored globally in Kappa_vals.
subroutine, public set_opal_opacity(rho, temp, kappa)
This subroutine calculates the opacity for a given temperature-density structure. Opacities are read ...
double precision, dimension(irmin:irmax), public logr_list