MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_cak_opacity.t
Go to the documentation of this file.
1!> This module reads in CAK line opacities in the Gayley (1995) notation
2!> (alpha, Qbar, Q0, kappae) from corresponding tables. Tabulated values assume
3!> LTE conditions and are a function of mass density (D) and temperature (T),
4!> which are both given in base 10 logarithm.
5!> The construction of the tables is outlined in Poniatowski+ (2021), A&A 667.
6!>
7!> The CAK opacity tables are stored in src/tables/CAK_tables. It is possible
8!> to use different tables when giving the absolute or relative path to the
9!> directory containing the tables. The only limitation is that the size of the
10!> non-default tables equals the size of the tables in src/tables/CAK_tables.
11!>
12!> This module is used in the FLD radiation module and the CAK force module.
14
15 use mod_comm_lib, only: mpistop
17
18 implicit none
19 private
20
21 !> min and max indices for R,T-range in opacity table
22 integer, parameter :: iDmin = 2, idmax = 51
23 integer, parameter :: iTmin = 2, itmax = 21
24
25 !> If user wants to read tables from different location than AMRVAC source
26 !> NOTE: the tables should have same size as AMRVAC tables
27 logical :: set_custom_tabledir = .false.
28
29 !> The opacity tables are read once and stored globally
30 double precision, public :: alpha_vals(idmin:idmax,itmin:itmax)
31 double precision, public :: qbar_vals(idmin:idmax,itmin:itmax)
32 double precision, public :: q0_vals(idmin:idmax,itmin:itmax)
33 double precision, public :: kappae_vals(idmin:idmax,itmin:itmax)
34 double precision, public :: logd_list(idmin:idmax), logt_list(itmin:itmax)
35
36 public :: init_cak_table
37 public :: set_cak_opacity
38
39contains
40
41 !> This routine is called when the FLD or CAK module is initialised.
42 subroutine init_cak_table(tabledir,set_custom_tabledir)
43
44 character(len=*), intent(in) :: tabledir
45 logical, optional, intent(in) :: set_custom_tabledir
46
47 ! Local variables
48 character(len=256) :: amrvac_dir, path_table_dir
49
50 if (present(set_custom_tabledir) .and. set_custom_tabledir) then
51 path_table_dir = trim(tabledir)
52 else
53 call get_environment_variable("AMRVAC_DIR", amrvac_dir)
54 path_table_dir = trim(amrvac_dir)//"/src/tables/CAK_tables/"//trim(tabledir)
55 endif
56
57 call read_table(logd_list, logt_list, alpha_vals, trim(path_table_dir)//"/al_TD")
58 call read_table(logd_list, logt_list, qbar_vals, trim(path_table_dir)//"/Qb_TD")
59 call read_table(logd_list, logt_list, q0_vals, trim(path_table_dir)//"/Q0_TD")
60 call read_table(logd_list, logt_list, kappae_vals, trim(path_table_dir)//"/Ke_TD")
61
62 if (mype == 0)then
63 write(*,*)'Initialized CAK tables, read in from ',path_table_dir
64 endif
65
66 end subroutine init_cak_table
67
68 !> This subroutine calculates the opacity for a given temperature-density
69 !> structure. Opacities are read from a table with given metalicity.
70 subroutine set_cak_opacity(rho, temp, alpha_output, Qbar_output, Q0_output, kappae_output)
71
72 double precision, intent(in) :: rho, temp
73 double precision, intent(out) :: alpha_output, qbar_output, q0_output, kappae_output
74
75 ! Local variables
76 double precision :: d_input, t_input, kappa_cak
77
78 if (temp <= 0.0d0) call mpistop('set_cak_opacity: local temperature <= 0')
79 if (rho <= 0.0d0) call mpistop('set_cak_opacity: local density <= 0')
80
81 d_input = log10(rho)
82 t_input = log10(temp)
83
84 call get_val_comb(alpha_vals,qbar_vals,q0_vals,kappae_vals, &
85 logd_list, logt_list, d_input, t_input, &
86 alpha_output, qbar_output, q0_output, kappae_output)
87
88 end subroutine set_cak_opacity
89
90 !> This routine reads in 1-D (T,rho) values from a line opacity table and gives
91 !> back as output the 1-D (T,rho) values and 2-D line opacity value
92 subroutine read_table(D, T, K, filename)
93
94 character(*), intent(in) :: filename
95 double precision, intent(out) :: k(idmin:idmax,itmin:itmax), d(idmin:idmax), t(itmin:itmax)
96
97 ! Local variables
98 character :: dum
99 integer :: row, col, funit=99
100 logical :: alive
101
102 inquire(file=trim(filename), exist=alive)
103
104 if (alive) then
105 open(funit, file=trim(filename), status='unknown')
106 else
107 call mpistop('Table file you want to use cannot be found: '//filename)
108 endif
109
110 ! Read temperature
111 read(funit,*) dum, t(itmin:itmax)
112
113 ! Read rho and kappa
114 do row = idmin,idmax
115 read(funit,*) d(row), k(row,itmin:itmax)
116 enddo
117
118 close(funit)
119
120 end subroutine read_table
121
122 !> This subroutine looks in the table for the four couples (T,rho) surrounding
123 !> a given input T and rho
124 subroutine get_val_comb(K1_vals,K2_vals,K3_vals,K4_vals, &
125 logD_list, logT_list, D, T, K1, K2, K3, K4)
126
127 double precision, intent(in) :: k1_vals(idmin:idmax,itmin:itmax)
128 double precision, intent(in) :: k2_vals(idmin:idmax,itmin:itmax)
129 double precision, intent(in) :: k3_vals(idmin:idmax,itmin:itmax)
130 double precision, intent(in) :: k4_vals(idmin:idmax,itmin:itmax)
131 double precision, intent(in) :: logd_list(idmin:idmax), logt_list(itmin:itmax)
132 double precision, intent(in) :: d, t
133 double precision, intent(out) :: k1, k2, k3, k4
134
135 ! Local variables
136 integer :: low_d_index, up_d_index, low_t_index, up_t_index
137
138 if (d .ge. maxval(logd_list)) then
139 ! print*, 'Extrapolating in logR'
140 low_d_index = idmax-1
141 up_d_index = idmax
142 elseif (d .le. minval(logd_list)) then
143 ! print*, 'Extrapolating in logR'
144 low_d_index = idmin
145 up_d_index = idmin+1
146 else
147 call get_low_up_index(d, logd_list, idmin, idmax, low_d_index, up_d_index)
148 endif
149
150 if (t .ge. maxval(logt_list)) then
151 ! print*, 'Extrapolating in logT'
152 low_t_index = itmax-1
153 up_t_index = itmax
154 elseif (t .le. minval(logt_list)) then
155 ! print*, 'Extrapolating in logT'
156 low_t_index = itmin
157 up_t_index = itmin+1
158 else
159 call get_low_up_index(t, logt_list, itmin, itmax, low_t_index, up_t_index)
160 endif
161
162 call interpolate_krt(low_d_index, up_d_index, low_t_index, up_t_index, &
163 logd_list, logt_list, k1_vals, d, t, k1)
164
165 call interpolate_krt(low_d_index, up_d_index, low_t_index, up_t_index, &
166 logd_list, logt_list, k2_vals, d, t, k2)
167
168 call interpolate_krt(low_d_index, up_d_index, low_t_index, up_t_index, &
169 logd_list, logt_list, k3_vals, d, t, k3)
170
171 call interpolate_krt(low_d_index, up_d_index, low_t_index, up_t_index, &
172 logd_list, logt_list, k4_vals, d, t, k4)
173
174 end subroutine get_val_comb
175
176 !> This subroutine finds the indices in rho and T arrays of the two values
177 !> surrounding the input rho and T
178 subroutine get_low_up_index(var_in, var_list, imin, imax, low_i, up_i)
179
180 integer, intent(in) :: imin, imax
181 double precision, intent(in) :: var_in, var_list(imin:imax)
182 integer, intent(out) :: low_i, up_i
183
184 ! Local variables
185 double precision :: low_val, up_val, res(imin:imax)
186
187 res = var_list - var_in
188
189 ! Find all bounding values for given input
190 up_val = minval(res, mask = res >= 0) + var_in
191 low_val = maxval(res, mask = res <= 0) + var_in
192
193 ! Find all bounding indices
194 up_i = minloc(abs(var_list - up_val),1) + imin -1
195 low_i = minloc(abs(var_list - low_val),1) + imin -1
196
197 if (up_i == low_i) low_i = low_i - 1
198
199 end subroutine get_low_up_index
200
201 !> This subroutine does a bilinear interpolation in the R,T-plane
202 subroutine interpolate_krt(low_r, up_r, low_t, up_t, logD_list, logT_list, Kappa_vals, D, T, kappa_interp)
203
204 integer, intent(in) :: low_r, up_r, low_t, up_t
205 double precision, intent(in) :: kappa_vals(idmin:idmax,itmin:itmax)
206 double precision, intent(in) :: logd_list(idmin:idmax), logt_list(itmin:itmax)
207 double precision, intent(in) :: d, t
208 double precision, intent(out) :: kappa_interp
209
210 ! Local variables
211 double precision :: r1, r2, t1, t2, k1, k2, k3, k4, ka, kb
212
213 ! First interpolate twice in the T coord to get ka and kb, then interpolate
214 ! in the R coord to get ki
215
216 ! r_1 rho r_2
217 ! | |
218 ! | |
219 ! ----k1--------ka-----k2----- t_1
220 ! | | |
221 ! | | |
222 ! T | | |
223 ! | | |
224 ! | ki |
225 ! | | |
226 ! ----k3--------kb-----k4----- t_2
227 ! | |
228 ! | |
229
230 r1 = logd_list(low_r)
231 r2 = logd_list(up_r)
232 t1 = logt_list(low_t)
233 t2 = logt_list(up_t)
234
235 k1 = kappa_vals(low_r, low_t)
236 k2 = kappa_vals(low_r, up_t)
237 k3 = kappa_vals(up_r, low_t)
238 k4 = kappa_vals(up_r, up_t)
239
240 call interpolate1d(r1,r2,d,k1,k2,ka)
241 call interpolate1d(r1,r2,d,k3,k4,kb)
242 call interpolate1d(t1,t2,t,ka,kb,kappa_interp)
243
244 end subroutine interpolate_krt
245
246 !> Interpolation in one dimension
247 subroutine interpolate1d(x1, x2, x, y1, y2, y)
248
249 double precision, intent(in) :: x, x1, x2, y1, y2
250 double precision, intent(out) :: y
251
252 y = y1 + (x-x1)*(y2-y1)/(x2-x1)
253
254 end subroutine interpolate1d
255
256end module mod_cak_opacity
This module reads in CAK line opacities in the Gayley (1995) notation (alpha, Qbar,...
double precision, dimension(itmin:itmax), public logt_list
double precision, dimension(idmin:idmax, itmin:itmax), public q0_vals
double precision, dimension(idmin:idmax, itmin:itmax), public qbar_vals
subroutine, public init_cak_table(tabledir, set_custom_tabledir)
This routine is called when the FLD or CAK module is initialised.
double precision, dimension(idmin:idmax, itmin:itmax), public alpha_vals
The opacity tables are read once and stored globally.
double precision, dimension(idmin:idmax), public logd_list
subroutine, public set_cak_opacity(rho, temp, alpha_output, qbar_output, q0_output, kappae_output)
This subroutine calculates the opacity for a given temperature-density structure. Opacities are read ...
double precision, dimension(idmin:idmax, itmin:itmax), public kappae_vals
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